I've been developing a web server application using Ruby on Rails and a client one with Android. The web server has some routes to client access, with no authentication. I thought creating a token to verify if the request is from client or not. I imagine a solution like this:
Create a key, for example, "stackoverflow;
Share this key in client and server application;
Generate a token using AES cryptography with a generate random String function + key;
When the client app is sending a request to server, send also the generated token;
Server verifies if token is valid or not using the shared key and AES cryptography.
Here are my doubts:
Is this the best way to develop a communication between them?
Is there a gem/api crypt and decrypt to use in both systems?
Please, do not hesitate to describe a suggestion or examples to guide me =)
Thanks in advance
A more secure and standard way would be to use SSL client certificates.
Issue a client certificate for every new version of your app, make sure it is signed using a certificate (ie CA cert) of which only you, or your signing CA has the private key.
Setup your web server to require client certificates before allowing the connection. Set the web server to verify the certificates agains the CA certificate you hold.
This way there is no "shared secret" that can be extracted from your app. If someone extracts and steals the client certificate, issue an updated version of your app with a new certificate, next add the old certificate to the revocation list of you CA, or just tell the web server to block that specific one.
No ruby, java or javascript code to be written.
Related
I have a platform for building real-time local apps called Bashoto and I am going to build an Android client.
Bashoto applications have the option of being authenticated which is done via generating a one-time use, expiring JSON Web Token (JWT for short) with the application token and a signature to verify that the token is valid. Each connection will have a unique JWT that is generated by signing the content with a Secret.
In a web environment, this means that the client backend has a copy of the Secret, signs the token and passes it to the client front-end which is then used in a request to the BashotoIO server.
The problem here in the mobile environment, and in this case Android, is that keeping that Secret in the application code itself is a potential attack vector, since someone can inspect the APK to find it.
What is the best way to truly keep the Secret secret in an Android application, while still keeping the Bashoto integration simple and streamlined?
I would like the usage to look something like this
Bashoto bashoto = Bashoto.fromAppKey("my-app-key");
bashoto.locate();
BashotoTopic topic = bashoto.topic("my-topic-name"); //token signing and connection happens here
topic.send("Some message that only gets seen by nearby people");
That depends on how secure you want the key to be. You can obfuscate your code using proguard http://responsiveandroid.com/2014/12/10/android-proguard-tutorial.html . This will still have the string literal in there but will be harder to get through a decompilation but not impossible.
If that's not secure enough then you can't keep it in the APK, you have to keep it on a remote server. Ideally that server would use SSL to keep the traffic private. You could fetch the key if you don't have it and store it securely locally using the android keystore https://developer.android.com/training/articles/keystore.html . This means that a user won't be able to decompile your app and find the key.
If you're worried about SSL sucking then you need to move to SSL pinning which will verify the authenticity of any server. https://developer.android.com/training/articles/security-ssl.html#Pinning
I'm setting up a server which an android app and an iPhone app will connect to. And I'm wondering what type of security is more secure for sending/requesting data?
Currently I generate a HMAC-SHA256 of the content I'm sending to the server in the header to verify its integrity.
But I'm wondering if its more secure to use a https connection instead? If I use https, could I skip the HMAC?
I would like to know the differences in security, which is more secure?
And also, if I'm using either is it better to use both for an extra layer of security?
Quick answer to your questions: SSL if used properly should give you more security guarantees than HMAC. So, usually SSL can be used in a way that removes the need for HMAC.
HMAC provides integrity as well as authenticity. Assuming the client and the server use pre-shared symmetric keys to calculate the HMACs, one side can be sure that the device on the other end has the secret key. This provides authenticity of both server and client.
What is missing in this picture (with just HMAC) is confidentiality. What is the nature of data exchanged between the server and client? Is there any sensitive user data being transferred during the communication that you don't want a man-in-the-middle to see? If so, then you may want to use SSL.
SSL gives you confidentiality (among other things). Meaning that you can be sure that you have a secured end-to-end connection and no man-in-the-middle can see what data is being exchanged between the server and client. However, common SSL usage does not include client machine authentication. Fro example, your web browser checks for Paypal's authenticity when you go to their https webpage. But the Paypal server does not ask your browser to send any certificate from your side.
Since you are comparing SSL with HMAC, I am assuming you care about authenticity of both sides. So, use SSL with both server and client authentication. This basically means that both of them would ask for each other's certificates and check different aspects of the certificates (i.e. common name, certificate issuer etc.). You can create your own certificate issuer to sign these certificates.
If you are making an app for AppStore or Google Play that users can simply install and start using, you may want to think through how the client side certificates will be generated, signed or who will sign them. You can remove the need for client side certificate (and signing) by adopting a model similar to GitHub's, where the user manually informs the server of trusted public keys to authenticate devices. But you can probably see how this process might not be user friendly.
We have a web service that should only be called by a specific Android app. What solutions are there for this problem?
The requirement is to not use authentication at all.
If it's only your client and your server, you can (and should) use SSL without purchasing anything. You control the server and the client, so each should only trust one certificate, the one belonging to the other and you don't need CAs for this purpose.
Here's the high-level approach. Create a self-signed server SSL certificate and deploy on your web server. You can use the keytool included with the Android SDK for this purpose. Then create a self-signed client and deploy that within your application in a custom keystore included in your application as a resource (keytool will generate this as well). Configure the server to require client-side SSL authentication and to only accept the client certificate you generated. Configure the client to use that client-side certificate to identify itself and only accept the one server-side certificate you installed on your server for that part of it.
A step-by-step for this is a much longer answer than is warranted here. I would suggest doing this in stages as there are resources on the web about how to deal with self-signed SSL certificate in Android, both server and client side. There is also a complete walk-through in my book, Application Security for the Android Platform, published by O'Reilly.
You'll normally store that certificate/private-key in a keystore of sometype (a KeyStore if you're using Android) and that keystore will be encrypted. That encryption is based on a password, so you'll either need to (1) store that password in your client somewhere, or (2) ask the user for the password when they start your client app. What you need to do depends on your usecase. If (2) is acceptable, then you've protected your credential against reverse engineering since it will be encrypted and the password will not be stored anywhere (but the user will need to type it in everytime). If you do (1), then someone will be able to reverse engineer your client, get the password, get the keystore, decrypt the private key and certificate, and create another client that will be able to connect to the server.
There is nothing you can do to prevent this; you can make reverse engineering your code harder (by obfuscation, etc) but you cannot make it impossible. You need to determine what the risk you are trying to mitigate with these approaches is and how much work is worth doing to mitigate it.
I guess this will work with proper authentification in place. First post I just stumpled upon was this one:
Securing communication from android to a web service
Hope it helps =)
If you're absolutely certain this web service will only need to be accessed by authorized applications/devices, go with client-side SSL certificates and restrict access at the server to only clients with authorized certs. This has the bonus feature of forcing SSL at all times so you don't like auth secrets over an open channel. Here's a quick guide for Apache, but you could use nginx too:
http://it.toolbox.com/blogs/securitymonkey/howto-securing-a-website-with-client-ssl-certificates-11500
I have client/server data passing all working correctly. Text, Images, etc. My users create blog-type posts on their android device, and upload to my server.. All is done using HTTP Multipart and Input/Output Streams. My issue is - How do I know the client is actually my app and not some script/other hacker app?
I want to avoid abuse scenarios.
Malicious user A creates a PC script that sends the appropriate form data to my server and is able to spam the server, creating 1000s of malicious posts.
Malicious user B creates a simple Android App that sends the appropriate form data to my server and he is able to spam the server.
Malicious user C signs up to my service, Has a valid account and password, and he spams the server using a PC script or Android App.
One idea I have is to force a wait period server side on frequent posts to prevent spam..
But beyond that, how can I check that the person sending data to my server is
An android device and
Is running my App to send form data and not another.
I want to avoid SSL as I don't want to register with Verisign, TRUST and go through all of that..
If it's only your client and your server, you can (and should) use SSL without purchasing anything. You control the server and the client, so each should only trust one certificate, the one belonging to the other and you don't need CAs for this purpose.
Here's the high-level approach. Create a self-signed server SSL certificate and deploy on your web server. You can use the keytool included with the Android SDK for this purpose. Then create a self-signed client and deploy that within your application in a custom keystore included in your application as a resource (keytool will generate this as well). Configure the server to require client-side SSL authentication and to only accept the client certificate you generated. Configure the client to use that client-side certificate to identify itself and only accept the one server-side certificate you installed on your server for that part of it.
A step-by-step for this is a much longer answer than is warranted here. I would suggest doing this in stages as there are resources on the web about how to deal with self-signed SSL certificate in Android, both server and client side. There is also a complete walk-through in my book, Application Security for the Android Platform, published by O'Reilly.
I finally got it all working, server and client two-way ssl authentication.
I used the instructions here to setup my own cert authority (ca) http://www.garex.net/apache/
I followed the commands there to generate my own ca, server and client files..
The big "GOTCHA" was that in the "create client certificate" section, the garex.net link uses a 1024 size client key. As it turns out, this was throwing the exception java.io.IOException: Wrong version of key store
To get around the above exception, I had to use only 512 sized keys.. This is done by NOT including the "1024" parameter to the openssl genrsa genkey command..
Finally I want to add a link to a tool I ended up using instead of Portecle.. I found the keytool gui program here of great help and easier to use than the portecle one - http://www.lazgosoftware.com/kse/index.html
This issue was a bit of a pain in the butt so I will keep an eye on this thread.. Feel free to reply if you run into any roadblocks..
You can use a captcha to solve this problem.
Before submitting the post, request the server for a captcha.
Server associates a random captcha image with a unique key, and sends the application both the captcha and the key.
Show the captcha image to the user.
Send the post, the letters entered by the user and the unique key in your http request.
Server verifies the captcha letters based on the unique key.
If captcha verification succeeded you add the post, otherwise you don't.
This should solve all the scenarios.
I am developing an Android app which need to consume .Net webservices over SSL which I have no experience in. Now I am looking for some guidance and explanation on SSL handshake and certificates.
Note: the server is using IP address and NOT domain name. It is an intranet application.
So far I have created a certificate(called self-signed?) in web server from IIS 7.
To consume it from Android app, I found two ways of doing it :
1). Embedded the certificate in the app (Which certificate? How do I get it?)
2). Trust all the certificates ( ppl said there is security issue with this approach, could you elaborate more? Does it still do the handshake?)
CERTIFICATES:
How many type of certificates are there in the handshake and what are they?
Does self-signed certificate have root certificate? If yes, how can i get them?
Is it possible to move/copy the self-signed certificate from one server to another?
HANDSHAKE:
First of all, is this process correct?
The SSL handshake process(copied from a website) is described below:
The client initiates the SSL handshake process by sending a URL
starting with the following: https:// to the server.
The client initially sends the Web server a list of each encryption
algorithm which it supports. Algorithms supported by SSL include RC4
and Data Encryption Standard (DES). The client also sends the server
its random challenge string which will be utilized later in the
process.
Will the embedded cert be sent in here?
The Web server next performs the following tasks:
Selects an encryption algorithm from the list of encryption
algorithms supported by, and received from the client.
Sends the client a copy of its server certificate.
Sends the client its random challenge string
The client utilizes the copy of the server certificate received from
the server to authenticate the identity of the server.
The client obtains the public key of the server from the server
certificate.
The client next generates a premaster secret. This is a different
random string which will in turn be utilized to generate the session
key for the SSL session. The client then encrypts a different value
called the premaster secret using the public key of the server, and
returns this encrypted value to the server. This is accompanied with
a keyed hash of the handshake messages, and a master key. The hash
is used to protect the messages exchanged in the handshake process.
The hash is generated from the former two random strings transmitted
between the server and the client.
What is a master key?
The server sends the client a keyed hash of all the handshake
messages exchanged between the two parties so far.
What is this keyed hash made from?
The server and the client then generate the session key from the
different random values and keys, and by applying a mathematical
calculation.
The session key is used as a shared secret key to encrypt and
decrypt data exchanged between the server and the client.
The session key is discarded when the SSL session either times-out or is terminated.
I'll try to answer to the best of my knowledge here
Embedded the certificate in the app (Which certificate? How do I get it?)
This the certificate identifying the client's/app identity. You can either get it through CA or self signed. This certificate will be used by the server to verify the client's/app identity
Trust all the certificates ( ppl said there is security issue with this approach, could you elaborate more? Does it still do the handshake?)
It still does the handshake but it doesn't do the certificate validation which is dangerous unless you are connecting internally (which seems you are). Trusting all certificate means an entity can claim as someone who they are not and thus could obtain confidential information from the users.
How many type of certificates are there in the handshake and what are they? In handshake you have the server's certificate and optionally the client certificate (for two factors authentication)
Does self-signed certificate have root certificate? If yes, how can i get them? Root certificate as far as I know means the ones that identifies by CA itself and thus it has no else to sign it. As your identity can still be verified and needs to be signed by CA, yours would not be classified as root certificate
Is it possible to move/copy the self-signed certificate from one server to another? The short answer is yes though the procedures from one platform to the others are different. Check [this link)(http://www.sslshopper.com/how-to-move-or-copy-an-ssl-certificate-from-one-server-to-another.html), it has instructions to copy certificate for few platforms
Will the embedded cert be sent in here? No, the embedded (client's) certificate is sent after validation of the server's identify is complete
What is a master key? Master key is the key that is used to derived the session key for later communication. It is also used to hash the messages and to verify authenticity of the messages in the next set of stages
What is this keyed hash made from? It's made from the master key sent by the client. In order to verify all messages, the server sent all messages that have been passed and hashed it with the master key. The client will hashed its messages as well with the same key and then compared with the data sent by the server. Only when the hash matches then we could be sure we are still communicating with the same server