Add custom certificate for iphone HTTP API - iphone

Is there any way to bundle a certificate in my application - and then use that to perform HTTP GET/POST using a NSURLRequest?
I.e. the certificate should not be used for other HTTP traffic on the device, only by my application.
Cheers

I don't believe so, but since all applications are sandboxed any special authentication measures you may have within your application cannot be accessed by other applications.

Best (in my opinion) you put the private key and certificate that you want to use on the keychain (or keychains of other 3rd party apps that share the same provisioning certificate).
As for the actual loading of the p12 we do use openssl (we did write a obj-c wrapper around it) to decode the .p12 that we send to the app (you can always use .DER or .PEM to ship the p12 with your app)

Related

Best practice to SSL Pinning in Flutter, fetch the certificate every time? or storing it in assets?

I went down the rabbit hole reading about SSL Pinning and how to implement it in Flutter, And I have two questions:
Is it secure to store (.pem) certificate file in assets? And if not, where to store it?
Is it secure and better practice to hit on the server on app load and get the certificate from there instead of storing it in app
I'm currently storing the certificate file in assets and fetching the path to it from app_settings.json using GlobalConfiguration().getValue() method.
That's how it usually works AFAIK
In this case the first API call isn't protected from MITM attack and SSL pinning purpose becomes broken
We used this plugin while implemented SSL pinning in our app (our client used Dio).
To implement this plugin you need to find corresponding fingerprint of your server certificate:
Click "lock" icon at the url address line
"Connection is secure"
"Certificate is valid"
General
Look for SHA-256 fingerprint at the Fignerprints section
Then you need to write this fingerprint into a constant list in your app to be used by the plugin.
The check should happen for EACH request you send because this is the main security purpose of SSL pinning - to check whether somebody modifies the request in the middle, between a server and a client. As per using Dio, you can use InterceptorWrapper to perform checks. The checker will look like:
class SslPinningInterceptor extends InterceptorsWrapper {
#override
Future<void> onRequest(
RequestOptions options,
RequestInterceptorHandler handler,
) async {
try {
// if the fingerprints do not match the plugin will throw a PlatformException
// SslPinningPlugin.check
// you can perform handler.next here because the exception hasn't been thrown
} on PlatformException catch (_) {
// you can perform handler.reject because check hasn't passed
}
}
#override
void onResponse(Response response, ResponseInterceptorHandler handler) {
// handler.next
}
#override
void onError(DioError err, ErrorInterceptorHandler handler) {
// handler.next
}
}
Your Problem
Is it secure to store (.pem) certificate file in assets? And if not, where to store it?
No where in the app is secure to store it because it's easy to extract via static binary analyses. The attacker will take the binary de-compile it with one of the many open-source tools out there, for example MobSF - Mobile Security Framework:
Mobile Security Framework is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing framework capable of performing static analysis, dynamic analysis, malware analysis and web API testing.
In a series of articles about Mobile API Security I show how to use MobSF to extract an API key, but the principle would be the same to extract a pem certificate. To have an idea on how MobSF can be used to decompile your app take a look to the article How to Extract an API key from a Mobile App with Static Binary Analysis:
The range of open source tools available for reverse engineering is huge, and we really can't scratch the surface of this topic in this article, but instead we will focus in using the Mobile Security Framework(MobSF) to demonstrate how to reverse engineer the APK of our mobile app. MobSF is a collection of open source tools that present their results in an attractive dashboard, but the same tools used under the hood within MobSF and elsewhere can be used individually to achieve the same results.
During this article we will use the Android Hide Secrets research repository that is a dummy mobile app with API keys hidden using several different techniques.
TOFU (Trust on First Use)
Is it secure and better practice to hit on the server on app load and get the certificate from there instead of storing it in app
Not recommended to trust on the first usage, because you are trusting to retrieve the certificatie on the first API request made by your mobile app, thus making it easier for an attacker to bypass your pinning by MitM attack this first request and provide instead it's own certificate.
Possible Solutions
I really don't recommend you to store the certificate in your mobile app, neither I recommend to use a PEM certificate to perform pinning due its operational complexities and how easy is to get it stolen, instead I recommend you to use public key pinning, where you pin to the hash of leaf, intermediate or root certificate, thus you only need to change pinning on your app when the pinned certificate its renewed with a different private key. Another benefit it's that your PEM certificate it's not anymore for grab by attackers and the public key hash used for pinning it's not a secret, after all it's an hash of the public key.
Using the PEM Certificate
Now, if you insist in going down this root of using a PEM certificate then you need a mechanism to only deliver the PEM certificate to the mobile app when it's not running in a compromised device (rooted, jail broken), not running on an emulator, no debugger attached, not under a MitM attack, not being instrumented at runtime by Frida or similar, and that the mobile app itself is the same exact one that you uploaded to the official store, not a repackaged/cloned one. In other words you need to attest the device and app integrity before you return the PEM certificate from your server, as you suggested in 2:
Is it secure and better practice to hit on the server on app load and get the certificate from there instead of storing it in app
Read more about this approach in this answer to the question How to use an API from my mobile app without someone stealing the token where you will secure the PEM certificate as I suggest to secure the API token, by using a Runtime Secrets Protection.
Public Key Pinning
Did you considered to perform certificate pinning through the public key (not private, like the pem file) of the certificate? Android and iOS support this via configuration
Android docs:
Normally, an app trusts all pre-installed CAs. If any of these CAs were to issue a fraudulent certificate, the app would be at risk from an on-path attacker. Some apps choose to limit the set of certificates they accept by either limiting the set of CAs they trust or by certificate pinning.
Certificate pinning is done by providing a set of certificates by hash of the public key (SubjectPublicKeyInfo of the X.509 certificate). A certificate chain is then valid only if the certificate chain contains at least one of the pinned public keys.
iOS docs:
If your app sends or receives data over the network, it’s critical to preserve the privacy and integrity of a person’s information and protect it from data breaches and attacks. You should use the Transport Layer Security (TLS) protocol to protect content in transit and authenticate the server receiving the data.
When you connect through TLS, the server provides a certificate or certificate chain to establish its identity. You can further limit the set of server certificates your app trusts by pinning their public-key identities in your app. Here’s how to get started.
For example, to generate the config for Android and iOS you can use the Mobile Certificate Pinning Generator online tool:
Android App Example:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">approov.io</domain>
<pin-set expiration="2023-07-21">
<pin digest="SHA-256">INBbf7pLOYb+mX9IcJDaUPxo6DSqKObPtdy+uT92ccQ=</pin>
</pin-set>
</domain-config>
</network-security-config>
iOS App Example:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSPinnedDomains</key>
<dict>
<key>approov.io</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSPinnedLeafIdentities</key>
<array>
<dict>
<key>SPKI-SHA256-BASE64</key>
<string>INBbf7pLOYb+mX9IcJDaUPxo6DSqKObPtdy+uT92ccQ=</string>
</dict>
</array>
</dict>
</dict>
</dict>
You can check in more detail how its done for Android on the article
Securing HTTPS with Certificate Pinning:
In order to demonstrate how to use certificate pinning for protecting the https traffic between your mobile app and your API server, we will use the same Currency Converter Demo mobile app that I used in the previous article.
In this article we will learn what certificate pinning is, when to use it, how to implement it in an Android app, and how it can prevent a MitM attack.
Do You Want To Go The Extra Mile?
In any response to a security question I always like to reference the excellent work from the OWASP foundation.
For APIS
OWASP API Security Top 10
The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.
For Mobile Apps
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.
OWASP - Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.

Store & access x509 certificate in iPhone's keychain

Can 3rd party application access iPhone's keychain in order to add X509 certificate to it? If yes, how can it be done?
If not, can it access keychain just to read certificates from it?
Basically, what I need is:
1) my application needs to access https site which uses certificate not signed by any trusted CA. when trying to connect via https, I get an exception.
2) it would be great If I could programmatically add the root's certificate to the keychain; it would be sufficient if the user could access the site via Safari, accept its certificate, and then access the site using my application.
So far, I've been using the following interface to surpass https:
#interface NSURLRequest (DummyInterface)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host;
#end
but this is not exactly what I want.
Any suggestions?
This Apple document should document enough stuff to permit adding self-signed certificate (or a self-signed certificate authority) into the keychain, and make it trusted. I didn't test it, though. Source
See also the top answer on this question. It, however, doesn't seem to actually verify the validity of the certificate. Cocoanetics has also documented how to use NSURLConnection with self-signed certificates, and similarly also doesn't seem to verify the validity.
So, you almost certainly want to follow Apple's instructions. The "Extracting and Evaluating an Identity From a *.P12 file" section appears to contain a complete example on how to import a certificate, even one protected with a passphrase.
Combine that with "AdvancedURLConnections" sample code and the ServerTrustChallengeHandler class and you should be good to go.
Here's also a more complete example by Vanja Komadinović.

IPhone app with SSL client certs

I'm building an iphone app that needs to access a web service over https using client certificates. If I put the client cert (in pkcs12 format) in the app bundle, I'm able to load it into the app and make the https call (largely thanks to stackoverflow.com).
However, I need a way to distribute the app without any certs and leave it to the user to provide his own certificate. I thought I would just do that by instructing the user to import the certificate in iphone's profiles (settings->general->profiles), which is what you get by opening a .p12 file in Mail.app and then I would access that item in my app. I would expect that the certificates in profiles are available through the keychain API, but I guess I'm wrong on that.
1) Is there a way to access a certificate that I've already loaded in iphone's profile in my app?
2) What other options I have for loading a user specified certificate in my app? The only thing I can come up with is providing some interface where the user can give an URL to his .p12 cerificate, which I can then load into the app's keychain for later use, but thats not exactly user-friednly. I'm looking for something that would allow the user to put the cert on phone (email it to himself) and then load it in my app.
I've tried with this:
NSString *thePath = [[NSBundle mainBundle] pathForResource:#"certificate" ofType:#"p12"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data;
CFStringRef password = CFSTR("pass");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);
inPKCS12Data is correct but items is empty. What is happening?
I've done this for a recent app by making the documents folder for the app accessible via itunes. Our users are then instructed to drag their generated key (in a p12 format file) into the documents panel for our app in iTunes. When the app is started, it checks for the existence of the p12 file and, if it exists, imports the file into the keychain.
It's not the simplest procedure, but it is the most secure because you don't have a private key file being sent around via email.
If a .p12 file isn't too big you could encode it using Base64 and then embed a link in an email with a custom url scheme, e.g.:
myapp://certificate/<base 64 data>
User clicks the link, your app saves the certificate somewhere for future use. Just make sure that Mail.app on the iPhone won't mangle the email.
Apple does restrict the use of device-wide keys/certificates to it's own applications/services, such as WiFi, VPN, Mail, etc. Third-party applications are not able to use any of these keys/certs (without jailbreaking). However, applications are able to import, store, and use keys and certificates in a in-app keychain. In addition, you can share keys/certs across multiple applications with the keychain-access-group feature in iOS.
I recently published a blog post titled In-App Mobile Certificates Made Easy with mCMS, which may have helped you out. Our company is developing an API that makes it easy to support in-app certificates, obtained directly from your Microsoft-based PKI. Our solution also offers on-device key generation, instead of generating a P12 on another machine and trying to import it into your app.
If you're using AirWatch for app distribution, their SDK provides the ability to provision certificates from your Certificate Authority to your registered devices. This allows you to provision your certs, and then access them from your app's code.
Does the code suggested in Finding a Certificate In the Keychain work for you?
Oh man, this brings up painful memories from October/November 2009. I was able to successfully get client-side certs to work but I had to port libcurl to the iPhone (which wasn't easy since the NDA was still in effect at the time).
I haven't done iPhone app development in over a year so I don't know how much is changed, but if I were you I'd first try to get by without client-side certs and if you absolutely must have them you can use libcurl with PEM formatted certs.

iPhone https authorization using client certificates

I am interested in playing HTTP live streaming data from my app. The stream (which I create) is encrypted, and a URL pointing to the AES key is included in the stream index file.
MPMoviePlayer hits this URL for the AES key, when it sees that encryption is enabled.
I would like this URL to be served by https, and for MMMoviePlayer to use a client certificate that I provide when the user purchases the content. I also do not want any user interaction for authentication, since they have already agreed to purchase the certificate.
Can I programmatically install the client certificate from my app so that MMMoviePlayer transparently uses this certificate to authenticate when getting the AES key?
Thanks!
Yes you can, check out the CredentialImportController class in this sample code http://developer.apple.com/iphone/library/samplecode/AdvancedURLConnections/Introduction/Intro.html#//apple_ref/doc/uid/DTS40009558
you will store the information in the application keychain which is not accessible by any other application unless you share that keychain using your app id.

How can I access identity profiles and certificates with iPhone SDK?

I am trying to verify the user identity on my application using a certificate / identity that the user has stored by opening a .cer / .p12 attached to an email. The certificate appears on the settings app of the phone under the group "Configuration Profiles".
Is there any way of accessing the certificate using the iphone SDK (I have tried to use the Security Framework, but it seems that it is only possible to access certificates stored in the application keychain or other keychains from its group)?
You talked about the Security framework already, but did you try the following functions in the doc?
I personally never tried/had to do this myself, but anyway it seems that there are some functions like SecCertificateCreateWithData in the framework, so you should be able to build a SecCertificateRef from some NSData/CFDataRef… data which is the content of your mail attachment.
From there you may use it as any other certificate using the other functions (like you would do for a certificate extracted from the Keychain)
Well this is only a guess after simply reading the documentation but let's give it a try as the doc seems to indicate it is the way to go.