In a recent discussion with colleague we analysed the implications of letting the default Android's system validation of CA signed TLS certificates from a known CAs like Verising, Comodo, etc. The discussion centered on the issue that the OS might be compromised (maybe rooted with malware or hacked) and the entire CA certificates library modified to validate certificates not signed by actual CAs.
A possible proposed solution to this was implementing Certificate validation in the app itself, having a list (which would in theory be much narrower considering that the app developer knows which certificates he'll be using) of Root CA Certificates in the app and let the app do the verification. This would allow for real validation without depending on the systems CA certificates.
I'm still a bit worried of wrongfully implementing this, how smart is it to let de app do the validation?
If the system is compromised an application running with same or less privileges than the compromised system can not save the day. Essentially you would not only need to implement TLS validation by your own but also the full TLS stack because the encryption libraries might be changed on the system and provide a backdoor to the attacker to get to the plain text. Additionally you would need to make sure that your application is not hijacked and the plain text information are stolen outside the encryption process, i.e. before encryption and after decryption. But, if the attacker has fully compromised the system you cannot stop this.
It is probably way more likely that you introduce new bugs while implementing the fairly complex TLS stack by your own and thus make your application not only insecure on compromised systems but also on others.
Related
I am implementing SSL pinning in our android app. I have pinned 2 certificates (current and backup) at the client by embedding them in the app.
Now, I want to have a mechanism in place to update these certificates without requiring to roll out an app upgrade in case certificates are expired or private key is compromised. How can I implement that?
One possible solution I am seeing is through app notification. I can broadcast a notification with new certificates and store them in the client. Is there any problem in this approach or is there any better approach?
PUBLIC KEY PINNING
I am implementing SSL pinning in our android app. I have pinned 2 certificates (current and backup) at the client by embedding them in the app.
If you pin against the public key you do not need to update your mobile app each time a certificate is rotated in the server, once you will sign it with the same public key, and you can read the article Hands On Mobile APi Security: Pinning Client Connections for more details in how this can be done:
For networking, the Android client uses the OKHttp library. If our digital certificate is signed by a CA recognized by Android, the default trust manager can be used to validate the certificate. To pin the connection it is enough to add the host name and a hash of the certificate’s public key to the client builder(). See this OKHttp recipe for an example. All certificates with the same host name and public key will match the hash, so techniques such as certificate rotation can be employed without requiring client updates. Multiple host name - public key tuples can also be added to the client builder().
For a situation where the private key used to sign the certificate gets compromised you will end-up in the same situation that you are trying to solve now, that is the need to release a new mobile app to update what you trust to pin against. By other words, the public key cannot be trusted anymore, thus the server must rotate the certificate with one signed with the backup public key you have released with your mobile app. This approach will give you time for a new release, that removes the public key used to sign the compromised certificate, without locking out all your users.
You should always store the backup private keys in separated places, so that if one is compromised you don't get all compromised at once, because then having a backup pin being release with the mobile app is useless.
DON'T DO THIS
Now, I want to have a mechanism in place to update these certificates without requiring to roll out an app upgrade in case certificates are expired or private key is compromised. How can I implement that?
Unfortunately the safer method to deal with a compromised private key is to release a new mobile app that doesn't trust on it anymore. Any remote solution you may devise to update the certificates will open the mobile app doors for attackers to replace the certificates you are pinning against.
So my advice is to not go down this road, because you will shoot yourself on the foot more easily than you can think off.
One possible solution I am seeing is through app notification. I can broadcast a notification with new certificates and store them in the client. Is there any problem in this approach or is there any better approach?
While the mobile app have the connection pinned it can be bypassed, thus a MitM attack can be performed and the new certificates retrieved from the attackers server, instead from your server. Please read the article The Problem with Pinning for more insights on bypassing it:
Unpinning works by hooking, or intercepting, function calls in the app as it runs. Once intercepted the hooking framework can alter the values passed to or from the function. When you use an HTTP library to implement pinning, the functions called by the library are well known so people have written modules which specifically hook these checking functions so they always pass regardless of the actual certificates used in the TLS handshake. Similar approaches exist for iOS too.
While certificate pinning can be bypassed is still strongly advised to use it, because security is all about layers of defense, the more you have the more hard it will be to overcome all them... This is nothing new, if you think of medieval castles, they where built with this approach.
A POSSIBLE BETTER APPROACH
But you also asked for a better approach:
Is there any problem in this approach or is there any better approach?
As already mentioned you should pin against the public key of the certificate to avoid lockouts of the client when you rotate the server certificates.
While I cannot point you a better approach to deal with compromised private keys, I can point out to protect the certificate pinning from being bypassed with introspection frameworks, like xPosed or Frida, we can employ the Mobile App Attestation technique, that will attest the authenticity of the mobile app.
Frida
Inject your own scripts into black box processes. Hook any function, spy on crypto APIs or trace private application code, no source code needed. Edit, hit save, and instantly see the results. All without compilation steps or program restarts.
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.
Before we dive into the Mobile App Attestation technique, I would like to clear first a usual misconception among developers, regarding the WHO and the WHAT is calling the API server.
The Difference Between WHO and WHAT is Accessing the API Server
To better understand the differences between the WHO and the WHAT are accessing an API server, let’s use this picture:
The Intended Communication Channel represents the mobile app being used as you expected, by a legit user without any malicious intentions, using an untampered version of the mobile app, and communicating directly with the API server without being man in the middle attacked.
The actual channel may represent several different scenarios, like a legit user with malicious intentions that may be using a repackaged version of the mobile app, a hacker using the genuine version of the mobile app, while man in the middle attacking it, to understand how the communication between the mobile app and the API server is being done in order to be able to automate attacks against your API. Many other scenarios are possible, but we will not enumerate each one here.
I hope that by now you may already have a clue why the WHO and the WHAT are not the same, but if not it will become clear in a moment.
The WHO is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.
OAUTH
Generally, OAuth provides to clients a "secure delegated access" to server resources on behalf of a resource owner. It specifies a process for resource owners to authorize third-party access to their server resources without sharing their credentials. Designed specifically to work with Hypertext Transfer Protocol (HTTP), OAuth essentially allows access tokens to be issued to third-party clients by an authorization server, with the approval of the resource owner. The third party then uses the access token to access the protected resources hosted by the resource server.
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.
While user authentication may let the API server know WHO is using the API, it cannot guarantee that the requests have originated from WHAT you expect, the original version of the mobile app.
Now we need a way to identify WHAT is calling the 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 a genuine instance of the mobile app, or is a bot, an automated script or an attacker manually poking around with the API server, using a tool like Postman?
For your surprise you may end up discovering that It can be one of the legit users using a repackaged version of the mobile app or an automated script that is trying to gamify and take advantage of the service provided by the application.
The above write-up was extracted from an article I wrote, entitled WHY DOES YOUR MOBILE APP NEED AN API KEY?, and that you can read in full here, that is the first article in a series of articles about API keys.
Mobile App Attestation
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.
So this solution works in a positive detection model without false positives, thus not blocking legit users while keeping the bad guys at bays.
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
So I recommend you to switch to pin the certificates by the public key, and if you want to protect against certificate pinning being bypassed, and other threats, then you should devise your own Mobile App Attestation solution or use one that is ready for plug and play.
So In the end, the solution to use in order to protect your Mobile APP and API server must be chosen in accordance with the value of what you are trying to protect and the legal requirements for that type of data, like the GDPR regulations in Europe.
DO YOU WANT TO GO THE EXTRA MILE?
OWASP Mobile Security Project - Top 10 risks
The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.
I am trying to learn about making secure mobile applications. I am curious to know, do we need Certificate pinning if our network calls from mobile to server use https ?
Yes, you should save it as a raw file in the folder of your app and use it to call the server for the requests.
Pay attention, if you have a self signed certificate you should force it as made by trusted authority.
I am curious to know, do we need Certificate pinning if our network calls from mobile to server use https ?
https guarantees that the data in transit between your mobile app and API server is encrypted and cannot be spied on by third parties, thus partially preventing it against Man in the Middle attacks.
So I say partially because an attacker can induce users to install a custom ssl certificate in order for them to use a free wifi. This is usually done with fake wifi captive portals where you have to sign in in order to have free wifi, like the ones you found in airports, trains, etc. If an attacker succeeds in tricking the user then all the traffic is routed through the attackers computer and despite being https it can be decrypted once the mobile app is using the attackers custom certificate, but the attacker will always use the original certificate when communicating with the API server, thus neither the API, server, mobile app or the user are aware that the communication is being intercepted and maybe even tampered with.
So using certificate pinning will prevent any type of a Man in Middle Attack to occur, even the ones where the user of the mobile app is the attacker that intentionally decrypts is own traffic in order to reverse engineer the mobile app communication with the API server in order to gain enough knowledge to mount an attack against it.
Now is time for the bad news... Certificate pinning can be bypassed when the attacker as access or controls the mobile device. This article walks you through on how certificate pinning can be used and bypassed by using a framework like xPosed, that will intercept the calls to validate the certificate, thus bypassing the validation process.
So should I use certificate pinning? Yes you should, because is one more layer of defence and requires more effort for an attacker to reverse engineer your mobile app, that he may deem not be worthy the effort, but if he deems worthy the effort then you may want to search in google for a Mobile App Attestation solution to protect further the communication between the mobile app and the API server.
But keep in mind that while certificate pinning may be easy to implement in your mobile app it may be an operational nightmare to maintain. Be sure to read the section PINNING IS A NIGHTMARE in the link I referenced previously about bypassing certificate pinning.
Edit
You can read the article Steal that API Key with a Man in the Middle Attack to see a practical example on how a secret can be extracted from a https request sent from a mobile app to the backend API, by performing a MitM attack.
So, in this article you will learn how to setup and run a MitM attack to intercept https traffic in a mobile device under your control, so that you can steal the API key. Finally, you will see at a high level how MitM attacks can be mitigated.
While we can use advanced techniques, like JNI/NDK, to hide the API key in the mobile app code, it will not impede someone from performing a MitM attack in order to steal the API key. In fact a MitM attack is easy to the point that it can even be achieved by non developers.
Afterwards you can also take a look to the article Securing HTTPS with Certificate Pinning on Android to understand how you can implement certificate pinning to prevent a MitM attack.
In this article you have learned that certificate pinning is the act of associating a domain name with their expected X.509 certificate, and that this is necessary to protect trust based assumptions in the certificate chain. Mistakenly issued or compromised certificates are a threat, and it is also necessary to protect the mobile app against their use in hostile environments like public wifis, or against DNS Hijacking attacks.
You also learned that certificate pinning should be used anytime you deal with Personal Identifiable Information or any other sensitive data, otherwise the communication channel between the mobile app and the API server can be inspected, modified or redirected by an attacker.
Finally you learned how to prevent MitM attacks with the implementation of certificate pinning in an Android app that makes use of a network security config file for modern Android devices, and later by using TrustKit package which supports certificate pinning for both modern and old devices.
I hope that both articles have made more clear why certificate pinning is recommended to be used to secure https connections from prying eyes.
EDIT 2
If you want to implement certificate pinning but are afraid of making any mistake while creating the network_security_config.xml configuration file then just use this free Mobile Certificate Pinning Generator to create it for you:
and it will give you a network_security_config.xml configuration file ready to be copy pasted:
I am going to create a Social media Application similar to facebook for both Android and IOS.I have login form where user need to give their uname and password.My server Team is handling webservices.
how to protect uname and password in Android and IOS App.
how to protect uname and pwd on remote ie while transferring from mobile to webservice.(I have an idea of using AES encryption Algorithm)
how to keep webservice url safe inside app(both android and ios)
what are the flaws could happen while creating these kind of app and how to restrict our app from Hackers?
what are the security steps server Team need to implement (they gonna write server in php).
thanks in advance?
Keep the password in the keychain (iOS).
Use SSL to communicate with the server, use POST for the username/password, Pin the certificate.
The webservice URL is public, anyone with a network sniffer will be able to see it.
The major hack will be against the server. Jailbreaking can compromise the app. The keychain is rather immune to jailbreaking.
The main thing for the server is how they handle the user personal information and password. Do not save the password, just a well salted SHA hash of it.
Define the value of the data you are securing from several perspectives: The user's perspective, the value to you,, your reputation, the value to an attacker. Then design the security to the highest level of all perspectives. Keep in mind that high security can be painful to the user. Find a balance.
If you care about security there is only one answer: Have the security designed and vetted by a security domain expert. I always have my designs and code vetted. Such a domain expert will have several years of full-time security experience in this area and possibly a certification such as CISSP. Anything short of this is just a "nice try".
Security bugs are different than normal code bugs. A normal app can have quite a few bugs that are just annoying but still be usable and even a good app. One security bug and there is no security, one security bug is all the attacker needs.
I'd like to have secure communication between my Android/iOS app and my Internet-accessible backend service, so I'm investigating HTTPS/SSL.
If I create self-signed certificates, then put a client certificate in the app and cause the backend service to require that client certificate, is this truly secure?
Here's why I'm asking. It seems that the client certificate could be "hacked" by interrogating the .apk. The client certificate is just a string constant, right? That means anyone could use the client certificate to access my backend. Is the .apk (and iOS equivalent) sufficiently opaque to prevent the client certificate from being discovered?
Are you doing client side authentication with certificates over SSL? Not that it really matters for this question. Any private keys you store in your app is accessible to an attacker. Each client should have it's own certificate and key pair, to prevent a mass compromise. Your server should also enforce protections, ensuring a compromised client can't just request anything.
This is true for any authentication scheme. If you embed passwords, API keys, decryption keys, whatever. Anything on the device should be assumed to be accessible.
The added security from certificates in part comes from there being nothing to brute force. If you went the username/password route for each clients, passwords can be guessed. Same with API keys (albeit they are longer and harder). With certificates, it's an entirely different class of attacks, and a considerably harder problem.
But, most importantly, the backend service shouldn't allow the app to do anything it wouldn't normally do.
Now, dealing with certificates, you're going to have a whole host of other problems. You probably want to sign each client certificate with your self-signed CA cert. Managing that CA cert can be problematic, depending on your use case. Are you going to generate these client certs on the fly, or manually yourself? Meaning, is this an app that a million people can download, and you need an automated system for generating them? Or is this a private/internal app that you personally will handle generating certs?
The certificate is harmless. It is the private key that needs protection, and it is only as safe as the device itself, no safer. Distributing the certificate and private key with the application just means that anyone who has the application has the key, so it doesn't provide you any security whatsoever. I think you need some kind of post-install registration step.
Typically, client SSL certificates are stored in keystores (BKS formatted in the case of Android) and the keystore is included as a resource within your APK. Keystores are encrypted and protected with a password. So, that client certificate cannot be readily extracted from an APK, as it is stored in an encrypted form.
Now...what do you do about the password? Here is the crux of the matter and you have two alternatives.
If you want your application to be able to communicate with the server (so, to be able to access the certificate) without user interaction, you will need to embed the password into your application and then, yes, an attacker could reverse engineer your code to find it, grab the keystore, and then decrypt it to recover the certificate. You can apply techniques like obfuscating your code so that it is harder for an attacker to do so, but this will just slow someone down and not prevent it.
Your alternative is to prompt the user for a password every time your application communicates to the server and use that to decrypt the keystore (or ask when the app starts and cache the certificate for a certain amount of time). The advantage here is that if someone reverse engineers your APK, they will find the encrypted keystore and no password so your certificate is safe. The disadvantage is having the user provide the password.
Which approach is best? It completely depends on the sensitivity of the data you are concerned with and the level of risk you are willing to accept. Only you can answer that question.
Daniel Guillamot, some tricks I've come over:
split server side key. Make the passphrase for the SSL-key be the result of string-in-app XOR string-fetched-from webservice.
make the string-in-app be created by calling some app-functions, instead of hard coded string.
deny tracing the app while it's running, to avoid someone picking up the final passphrase when it's calling the decryption of the private key. Ref: http://books.google.no/books?id=2D50GNA1ULsC&lpg=PA294&ots=YPQQ7DLjBD&dq=The%20example%20just%20shown%20demonstrates%20how%20calls%20to%20ptrace%20can%20be%20hijacked&hl=no&pg=PA293#v=onepage&q&f=false
I'd love to hear more if anybody have other ideas.
APK can be accessed and copied, so putting anything in it won't help. Activation and maybe binding the certificate to the device after installation would be necessary. Binding can be done for example by putting the IMEI of the device to one of certificate extensions and passing the IMEI together with the certificate by your application (or, better, pass IMEI after authentication and establishing the secure channel).
I have a website with a number of RESTful web services that are used by an Android app. I want to let all requests go through HTTPS. Hence, I need an SSL certificate for my website.
Q: Do I need to buy an SSL certificate or can I use a self-signed certificate in this case? (I don't want to waste money on something I don't need.)
I can think of these approaches:
Buy an SSL certificate with Extended Validation (green address
bar). Probably not necessary.
Buy an SSL certificate without Extended Validation. This should suffice, no?
Self-sign an SSL certificate. Not sure what this implies?
If your biggest concern is not spending money http://www.startssl.com/ provides free basic SSL certificates for a year so that may be worth looking into. I do not know off-hand which CAs are trusted by default in Android so it may turn out to be effectively the same as a self-signed certificate from the app's perspective.
Using a self-signed certificate would require finding a way to make sure the Android app expected that self-signed certificate and trusted not only your initial certificate but any replacement certificates in the future. I suspect this is more trouble than it is worth although I do not know much about Android development or the app in question so I may be overestimating the difficulty involved.
An EV certificate does provide a stronger guarantee to the client that the service is actually your service and owned by you but it does incur additional costs. Choosing an EV versus DV certificate becomes more of a risk/reward judgement call. Annecdotally, I typically only see EV certificates on financial sites and others where you would typically expect to find a high bar for security.