Use case of increased https security in JAVA - java

I am writing an application that should ensure secured connection between two parties (call them Client and Server).
Server should restrict which clients can connect using https. For this purpose, server will issue a certain number of certificates that will be checked when a client tries to connect. If the certificate that the client is using is not in trusted list, connection would not be established.
This certificate should be distributed using some kind of usb device. So when Client using my application tries to get something from server using https, application should read that certificate from usb device and USE IT to establish https connection. Private key should be kept secret on the device at all times.
So far I managed to create local keystores on client and server (JKS), add them to each other trusted list and use them to achieve proper connection.
My question is: can client certificates be issued by a server and transported to clients, all together with private key required for https connection? I dont want any data or keystore to be created on the client machine, everything required for establishing https connection should be on that device. Device could have some procedures and api to help this process and ensure secrecy of private key.
Any help will be greatly appreciated :)

can client certificates be issued by a server and transported to
clients, all together with private key required for https connection?
Technically, they can, but you're going to have to authenticate that connection by some other means if you want to make sure that private key only gets to its intended user. As far as your overall scheme is concerned, this doesn't really help. In addition by sending the private key as data to the client, they may be able to extract it one way or another.
If you can physically send a USB device, you can use a hardware cryptographic token that supports PKCS#11. Such tokens tend to have options to store a private key in a way in can't be extracted (it can only be used with the device). They tend to come in to forms: as a smart card (in which case you need a reader) or as a USB token (it looks like a memory stick, but it's not). Depending on the model, the USB token can in fact be a smart card with an embedded reader.
Java supports PKCS#11 keystores, so if this token comes with a PKCS#11 driver/library, it could be used from Java.

The normal client certificate approach to authentication doesn't work well if you don't trust the client to protect their credentials - which seems to be your scenario.
Putting the certificate on the USB device keeps it off the client machine's disk, but doesn't stop the client user from accessing it and distributing it to others. On the other hand, it reduces the risk of 3rd parties stealing the certificate from the client machine "at rest" - but only if the client protects the USB key properly. So you need to be clear about what threats you are trying to defend against, and who you trust.
The only way to make the certificate at all 'private' from the client user is to put it on some kind of tamper-resistant device, and use an approach that does not transmit the certificate to the client machine during authentication.
Compare your approach with those used for internet banking, where the customer is issued a device that can do challenge-response, using their bank card and PIN (two-factor authentication). The card details are protected from casual attack by the card's chip; but the system assumes that the client looks after their card and PIN, and reports thefts promptly (because it's their money at risk!). If the client is not motivated to look after the credentials, then this approach does not make sense.
If you just want to ensure that the client has an unsharable token, you could consider using SecurID devices, or similar, which are an off-the-shelf solution to your problem.

Related

Rest API security for mobile apps

I'm in the process of designing a mobile application that will need to connect to a server-side process for its business logic and data transactions. I'm writing my server-side code in Java using Spring Boot and I intend to create a Rest API in order for the mobile app to connect to the server.
I'm just doing some research at the moment for the best way to secure the connection between mobile app and server. What I'd like to do is allow the user on the mobile app to log in once they open the app and for them to use the app for as long as they like and for their access to time out after a period of inactivity.
Can anyone recommend any very simple reading on this? I've looked at OAuth2 but that appears to be for logging into web services using another account (like Google, GitHub, etc).
Would it be acceptable to login over https (SSL) by passing username and password to a rest endpoint and returning some sort of token (a GUID?). Then have the client (mobile app) pass that GUID with each subsequent call so the server can verify the call? Is it better to just do everything over SSL in this scenario?
I have done a fair bit of research but I don't seem to be able to find anything that quite matches what I'm trying to do.
Hope someone can help
Thanks
OAUTH2 IS NOT ONLY FOR WEB
Can anyone recommend any very simple reading on this?
I've looked at OAuth2 but that appears to be for logging into web services using another account (like Google, GitHub, etc).
No OAUTH2 is not only for web apps is also for mobile apps and you read this article for a more in depth explanation, but I will leave you with the article introduction:
Like single-page apps, mobile apps also cannot maintain the confidentiality of a client secret. Because of this, mobile apps must also use an OAuth flow that does not require a client secret. The current best practice is to use the Authorization Flow along with launching an external browser, in order to ensure the native app cannot modify the browser window or inspect the contents. If the service supports PKCE, then that adds a layer of security to the mobile and native app flow.
The linked article is very brief, you will need to follow the next chapters to get the full picture.
DO NOT ROLL YOUR OWN AUTHENTICATION / AUTHORIZATION SOLUTION
Would it be acceptable to login over https (SSL) by passing username and password to a rest endpoint and returning some sort of token (a GUID?). Then have the client (mobile app) pass that GUID with each subsequent call so the server can verify the call?
While you can do it I strongly advise you to use an already established OAUTH2 or OPENID connect solution, because they are developed and maintained by experts in the field and battle tested by millions of web and mobile apps using them. This enables to identify ans fix security issues much more quickly that anyone could do in their own in-house solution.
OAuth2
OAuth 2.0 is the industry-standard protocol for authorization. OAuth 2.0 supersedes the work done on the original OAuth protocol created in 2006. OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications, desktop applications, mobile phones, and living room devices. This specification and its extensions are being developed within the IETF OAuth Working Group.
OpenID Connect
OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.
OpenID Connect performs many of the same tasks as OpenID 2.0, but does so in a way that is API-friendly, and usable by native and mobile applications. OpenID Connect defines optional mechanisms for robust signing and encryption. Whereas integration of OAuth 1.0a and OpenID 2.0 required an extension, in OpenID Connect, OAuth 2.0 capabilities are integrated with the protocol itself.
So for your authentication/authorization needs I would recommend you to go with an OpenID connect solution, that leverages OAuth2 under the hood.
SSL IS ALWAYS NECESSARY?
Is it better to just do everything over SSL in this scenario?
SSL must be always used for everything, http MUST not be used at all in any situation, because once you allow an http request you are vulnerable to a man in the middle attack and I strongly recommend you to read this article from a well know security researcher, Troy Hunt, to see how even a static website must use https and he goes to a great extent to explain why and names very important attack vectors that can harm an application not using https, like WiFi hot-spots hijacking, DNS Hijeacking, Router Exploits, China great cannon, and others.
IMPROVE SSL WITH CERTIFICATE PINNING
Communicating using https is the way to go for any kind of application but developers must be aware that an attacker in control of device where the application is installed can spy https traffic by doing a man in the middle attack with a custom certificate installed in the device the mobiel app is installed, enabling this way for him to understand how the mobile app communicates with the API server in order to mount automated attacks to abuse from same API.
Certificate Pinning
Pinning is the process of associating a host with their expected X509 certificate or public key. Once a certificate or public key is known or seen for a host, the certificate or public key is associated or 'pinned' to the host. If more than one certificate or public key is acceptable, then the program holds a pinset (taking from Jon Larimer and Kenny Root Google I/O talk). In this case, the advertised identity must match one of the elements in the pinset.
You can read this article, with code sample to see how easy is to implement certificate pinning, how it can be difficult to maintain in the operational side, and with a video to see how an attacker can bypass pass certificate pinning in the client side by using Xposed framework.
xPosed
Xposed is a framework for modules that can change the behavior of the system and apps without touching any APKs. That's great because it means that modules can work for different versions and even ROMs without any changes (as long as the original code was not changed too much). It's also easy to undo.
EDIT:
Nowadays, you can use the Mobile Certificate Pinning Generator to help you with implementing certificate pinning in your mobile app:
That will give you a ready to use pinning configuration for Android and iOS:
RESEARCHING FOR A SOLUTION
Before I point you out to a possible solution I would like to make clear the distinction between 2 concepts that developers frequently are not aware off or take as being the same thing...
The Difference Between WHO and WHAT is Accessing the API Server
The WHO is the user of the mobile app that you can authenticate,authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.
Now you need a way to identify WHAT is calling your API server and here things become more tricky than most developers may think. The WHAT is the thing making the request to the API server, is it really your genuine mobile app or is a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?
Well to identify the WHAT developers tend to resort to an API key that usually they hard-code in the code of their mobile app and some go the extra mile and compute it at run-time in the mobile app, thus becomes a dynamic secret in opposition to the former approach that is a static secret embedded in the code.
Some Mobile API Security Techniques
I have done a fair bit of research but I don't seem to be able to find anything that quite matches what I'm trying to do.
You can start by read this series of articles about Mobile API Security techniques to understand how Https, Certificate Pinning, APi Keys, HMAC, OAuth2 and other techniques can be used to protect the communication channel between your mobile app and the API serve, and how they can be bypassed.
To solve the problem of WHAT is accessing your mobile app you need to use one or all the solutions mentioned in the series of articles about Mobile API Security Techniques that I mentioned above and accepted that they can only make unauthorized access to your API server harder to bypass but not impossible.
A better solution can be employed by using a Mobile App Attestation solution that will enable the API server to know is receiving only requests from a genuine mobile app.
A POSSIBLE BETTER SOLUTION
The use of a Mobile App Attestation solution will enable the API server to know WHAT is sending the requests, thus allowing to respond only to requests from a genuine mobile app while rejecting all other requests from unsafe sources.
The role of a Mobile App Attestation service is to guarantee at run-time that your mobile app was not tampered or is not running in a rooted device by running a SDK in the background that will communicate with a service running in the cloud to attest the integrity of the mobile app and device is running on.
On successful attestation of the mobile app integrity a short time lived JWT token is issued and signed with a secret that only the API server and the Mobile App Attestation service in the cloud are aware. In the case of failure on the mobile app attestation the JWT token is signed with a secret that the API server does not know.
Now the App must sent with every API call the JWT token in the headers of the request. This will allow the API server to only serve requests when it can verify the signature and expiration time in the JWT token and refuse them when it fails the verification.
Once the secret used by the Mobile App Attestation service is not known by the mobile app, is not possible to reverse engineer it at run-time even when the App is tampered, running in a rooted device or communicating over a connection that is being the target of a Man in the Middle Attack.
This is a positive model where false positives do not occur, thus the API server is able to deny requests with the confidence of not blocking legit users of your mobile app.
The Mobile App Attestation service already exists as a SAAS solution at Approov(I work here) that provides SDKs for several platforms, including iOS, Android, React Native and others. The integration will also need a small check in the API server code to verify the JWT token issued by the cloud service. This check is necessary for the API server to be able to decide what requests to serve and what ones to deny.
CONCLUSION
Properly securing a mobile app and the API server is a task composed of several layers of defense that you must put together in order to protect it.
How many layers to use will depend on the data your are protecting, the value it have for the business, the damage it can cause when leaked in a data breach and how much you may be penalized by law enforcement, like GDPR in Europe.
What I usually do is crafting a JSON web token (https://jwt.io/), and handle the sessions on my own.
JWT is really nice, since you only need to define a secret key on the server side. As long as your clients are able to pass the string you crafted (inside the headers for example), and as long as nobody gets to retrieve your secret key, you are sure that every data you push when creating the token was generated by you. (Don't hesitate to use the strongest encryption algorithm)
For a secure connection use HTTPS at level TLS 1.2 level. Then pin the server certificate in the app, that will prevent MITM attacks.
It is safe to pass the user name and password. You can return a time-limited token for further authentication is needed/desired.
With HTTPS everything but the address portion of the URL is encrypted. But be careful with the query string, it may end up in the server logs.
Thanks again for these replies. I've been implementing my service to run under https by using server.ssl.key-store parameters and it looks like it's working okay. I have used keytool.exe to create a trust store and I run my SpringBoot app (with Tomcat embedded) using that trust store. I can open a browser to my REST endpoint (using https this time, not http), the browser asks for authentication and when I enter my user details, it matches them against my db user and allows me to see the response from the server.
One question though, what's the point of having a trust store on the server side (Java) if I can just access the REST endpoint using any old browser and just enter my user name and password? Eventually, this REST endpoint won't be accessed via a browser, it'll be accessed using a mobile app programmatically, so I assume I'll be logging on using that with username and password over https. I thought I'd need to have a certificate of some sort on the client side in order to communicate or does it not work like this?
Thanks again

Handling security when deploying Java application

I have a Java app (deployed as a JAR file) that allows file sharing through SLLSockets. If all users use the same certificate, file transfers are not secure, since it violates the core concept of asymmetric encrypted communication. Therefore, I understand that each user needs to have its own certificate. This brings up my first question:
How can you generate a certificate programmatically, and where would you store it ? I don't want users to have to generate their own certificate with keytool, then have to tell the app where it is located.
Now, let's say my first question is answered and each user has its own certificate. Prior to opening the SSL connection between two hosts, you need to add each other's certificate to the trustStore. The only way I know to achieve this is by exchanging them through Sockets (note that I am using JGroups to exchange Socket connection info). This brings up my next two questions:
How do you guarantee authentication and integrity when exchanging the certificates ?
How do you programmatically add the received certificate to the trustStore ?
Finally, this whole post brings up my fourth question:
Are the steps described above the correct way to send data securely between two hosts, using SSLSocket asymmetric encrypted communication ?
You don't need client certificates necessarily.
Could you not use username/password authentication?
You can still secure the transfer just by using a server certificate.
Client certs are also kind of a pain, and not entirely secure. They tie you to a machine, and evil processes can read them. Smart cards mitigate this, but aren't free.

is it possible to make sure the client used is from a particular host?

I have a server application and a client application created with java that will communicate with the server application. But, since i haven't put emphasis on security in the server side it is really easy to hack the server application if a hacker creates his own client to connect with my server. I want to make sure the client application that is communicating with my server is the authentic client that i created. I upload client to a specific host like www.abcd.com. Now, can i make sure when a client that connects to my server came from that host. I am knowledgeable about signing it with trusted signer but i am looking for a cheap option.
No, this isn't possible. If it were, DRM would work, but everyone knows it's hopelessly broken.
To be truly secure, the client has to be a machine with a "trusted platform module," TPM, that supports something called remote attestation. This allows the server to verify the client is authentic and unaltered. But I've never heard of a real world application of this, and though TPMs are common, I'm not sure if the remote attestation feature is.
I want to make sure the client application that is communicating with my server is the authentic client that i created.
You have two options. One is a password or shared secret, and the other is client certificates. All three are supported in SSL/TLS. Look for TLS-SRP (password based authenticated key exchange), TLS_PSK (preshared key based on a block cipher), and the traditional SSLTLS ciphers with client side certificates.
You can even set up the tunnel with Server Authentication only, and then perform the client authentication at the application level. This is what usually happens in web apps. But this has some non-trivial defects because it does not provide mutual authentication and lacks channel binding. You are better off with TLS-SRP, TLS-PSK, or client certificates.
EDIT: I focused on SSL/TLS because you cited a hostname, but you can do it at other layers, too. For example, you can use shared secrets and certificates at the VPN level. #erickson provides one method using TPMs that could be used at the application level.
Now, can i make sure when a client that connects to my server came from that host.... host like www.abcd.com
This will work if DNS is configured and trustworthy. That is, you will have to extract the host's name, perform a reverse lookup, and then authenticate the IP address. I believe this is called network based authentication.
If an attacker controls DNS or is on the same LAN segment as the server, then I believe network based authentication has some non-trivial security defects.
In any case, HSMs and TPMs are not the answer. To understand why, see Peter Gutmann's Engineering Security, and the section on Unattended Key Storage. From his book:
TPMs don’t work because all that they can do is store the fixed key
that’s required to decrypt the other keys (TPMs are just repurposed
smart cards and don’t have the horsepower to perform anything more
than lightweight crypto themselves so you can’t offload the overall
encryption processing to them), and since for unattended operation
they have to release their secrets without a PIN being entered they’re
just providing plaintext key storage with one level of indirection.

How would I approach secure communication from Android application to Server

I need encrypted information regarding the application users to be sent over to my server. And also for the server to verify the information sent and send back an encrypted response so the client would know what to do depending on the response. I believe I should be approaching this with JSON and POST PHP but don't know what to do for the security aspects of it.
An example would be. Client buys coins through in-app billing. Server receives notice from in-app billing and updates how many coins Client has. Client then proceeds to use coins to buy an item in the game and sends its verification and id to server which the server verifies and then sends a response code either stating that the Client is banned for doing fraudulent activity or insufficient coins or lets the Client buy the item in question.
Some questions I have.
I understand that any application or game can always be hacked on the clients end but gets progressively harder if its verifying things coinciding a server. How can I make sure that it is very hard for the client to mess with the response code and also with the sending of verification? Would SSL be enough? If so, could you direct me to an article on how to implement SSL for Android php posting?
How does Google billing verify it's users? By e-mail or device ID?
It's all written here. In the coins example, you'll likely need an unmanaged in-app billing. Unmanaged means that Google Play won't store the transaction and you are responsible of tracking users (by email, device ID, both or an username).
Regarding security, it really depend on your requirements. Google Play's in-app billing doesn't require you to deploy your own server. You don't even need to talk to the network: it's all managed by the Play app, which acts like a Proxy. Assuming you want to use your own server, SSL only grants a transport security, ie integrity and confidentiality of the message, not typically guaranteed by HTTP, are now guaranteed by SSL. This prevents man-in-the-middle attacks and the like, but it really doesn't protect your app from application-level flaws.
If your backend has a standard RESTful interface, you need to authenticate users against at least one private piece of information, like a password. Otherwise, anyone could make requests impersonating 1234567890 or john#example.com, which are publid data. In other words, you simply need to create accounts for users and communicating over HTTPS.

Difference between client (java standalone client)application authentication and user authentication

In case of webapplicaiton I can understand that there is no difference between the client authentication and user authenticaiton; Ignoring XSS and other exploits the web client is generated by the server/servlet.
But suppose you have a Java client application talking to the Java Server application; The server has a certificate associated with it so that the client can validate and verify if server is trusted. Now client also has a certificate (client cert) so that the server can verify if this is a trusted client; Once this mutual authentication is done, instead of presenting a username/password dialog to the user, the users certificate (user cert) can be passed to the server.
Question is whether there is any advantage/use in this case in having a (client cert); Or will the user certificate alone will suffice to trust the client as well ??
I know this is an obvious question/ but cant a rouge client application be created ?? So will the client cert protect against this scenario.
Any time you have a client server application the server needs to assume the client is compromised. When an authentication occurs (username/password, certificate, etc... it doesn't matter) the server should grant the user certain permissions to use the functionality of the server. Whenever a request is made to the server the server needs to check whether the authenticated user has the permission to perform that action.
Trusting the client to only make authorized requests opens yourself up to attacks. If you check permissions on the server and scrub inputs then you don't have to worry about whether the user is using a trusted client because even an untrusted client won't be able to do more than the trusted client could with the same authentication credentials.
These principles apply regardless of wether you are using a web client or a stand alone client. Even in a web app I can write a new client and POST data, use RESTful services, or generally talk to the web server and completely bypass the web ui you present to me.
If some attacker gets to alter in some way the client application, it could use the valid user certification to access the server.
The server should verify the client app, not for server sake (we assume the server checks if client can do this or that operation, but for ensuring the client is not being phished by a bogus client). Then the server can proclaim that all operations made by client-1 we're made through some verified client-app (agent) so they were really intended by the user.
The client application's certificate (and it's private key) can be easily ripped off the application and rogue application can be created. The ways to counteract this are (a) use user's certificate and let the user provide it when needed and (b) use a USB cryptotoken to store the client certificate and it's private key. Cryptotokens don't let the private keys out so the attacker can't copy it (though he can use the token with his application, if he has physical access to the token).

Categories