Titanium JIRA Archive
Appcelerator Modules (MOD)

[MOD-2293] iOS: SSL Pinning / HTTPS module not working for wildcard-certificates

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionFixed
Resolution Date2016-10-18T07:04:34.000+0000
Affected Version/sn/a
Fix Version/shttps 2.0.1, https 1.1.4
ComponentsHttps
LabelsHTTPS, Module, SSL
ReporterRodolfo Perottoni
AssigneeJan Vennemann
Created2016-08-31T04:48:44.000+0000
Updated2018-08-06T17:49:19.000+0000

Description

I don't know who else to contact in regards of this critical issue, so I'm opening this ticket to report a problem that has a important impact on an app that uses the HTTPs module. We've recently tested our app against MITM attacks and found out that all the packets exchanged from the app to the servers are traceable and not encrypted. This is a serious issue because the app is breaching agreements between several data providers / parties.We believe that you can understand the gravity of this problem and that it must be resolved. According your Terms and Conditions for your Team Account Plan purchased last year, a VIP support was offered. Therefore we expect your team to address this issue urgently. The code below used within our App creates a Security Manager for HTTP requests:
var https = require('appcelerator.https');

var securityManager = https.createX509CertificatePinningSecurityManager([
    {
        url: "https://*.server.com/",
        serverCertificate: "certificate_server1.der"
    },
    {
        url: "https://*.server2.com/",
        serverCertificate: "certificate_server2.der"
    }
]);
Both certificates point to a *wildcard* domain because the app consume different API's (depends on the version of the app that the user has downloaded). All the HTTPClient objects are being created like this:
var xhr = Ti.Network.createHTTPClient({
	validatesSecureCertificate : true,
	tlsVersion : Titanium.Network.TLS_VERSION_1_0,
	securityManager: securityManager,
	timeout: 120000,
	autoEncodeUrl: false
});
This code works correctly. Now if we change the URLs of the Security Manager to:
var securityManager = https.createX509CertificatePinningSecurityManager([
    {
        url: "https://google.com",
        serverCertificate: "certificate_server1.der"
    },
    {
        url: "https://google.com",
        serverCertificate: "certificate_server2.der"
    }
]);
Everything still works normally. Correct me if I'm wrong, but I don't think that's normal. From my understanding, it appears the securityManager and my HTTPClient objects are not working as they are supposed to. Find attached 2 images of requests that I've sent to the server being tracked through Fiddler (via Proxy). I should not be able to see the content of these packets. Fiddler is being able to capture my packets and forward them to my server without any problem. Also, here's a link that guides you on how to configure Fiddler: http://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/ConfigureForiOS

Attachments

FileDateSize
faceboo.der2016-09-05T02:18:55.000+00001875
goog.der2016-09-05T02:18:55.000+00008251
image002 copy.png2016-08-31T04:53:27.000+0000893555
image003 copy.png2016-08-31T04:53:27.000+0000201091

Comments

  1. Hans Knöchel 2016-08-31

    We have the module working in several production apps and it works there. There was a problem between 5.0.0 and 5.1.0 I think, but that was fixed in 5.2.0 and later. So in order to investigate this further, we need your full environment and validation that your certificates and connections are correctly implemented. Please also attach your logs if possible or send them directly to us. But - I would suggest it is a valid issue that is caused by the wildcard-syntax. Is the syntax documented to be valid? Thank you! A list of possible helpful link(s): - http://stackoverflow.com/a/26494515/5537752
  2. Rodolfo Perottoni 2016-08-31

    That syntax is not documented, but having wildcard certificates is pretty standard for SSL pinning. That's how we've been using the HTTPS module since we acquired it. If it doesn't work, an error should be thrown to make it easy for us to detect this. As I've said in the description: * Our app can contact the API without any problems by using that securityManager. Why no errors are being thrown (since the packets are completely exposed as you can see in the images attached) ? * If I change the URLs in the security manager the app still works flawlessly. At least an error should be thrown in case the URL passed to the object doesn't match the one in the certificate, right ? I'll have to discuss with my team whether it's possible to give you our environment / certificates, because as said above this information is very sensitive.
  3. Rodolfo Perottoni 2016-08-31

    Also, is the implementation mentioned in the StackOverflow link above the same one used in the HTTPS module? If so, I can try and generate another certificate with the wildcard server address in the Subject Alternate Name section.
  4. Rodolfo Perottoni 2016-09-01

    I've just confirmed that both of our certificates have the wildcard domains in the Subject Alternative Name section. I think this is not the root of the problem. Here's how my certificate looks like (omitting the content):
       X509v3 extensions:
           X509v3 Authority Key Identifier: 
               <ommited>
           X509v3 Subject Key Identifier: 
               <ommited>
           X509v3 Key Usage: critical
               <ommited>
           X509v3 Basic Constraints: critical
               <ommited>
           X509v3 Extended Key Usage: 
               <ommited>
           X509v3 Certificate Policies: 
               <ommited>
           X509v3 CRL Distribution Points: 
               <ommited>
           Authority Information Access: 
               <ommited>
           X509v3 Subject Alternative Name: 
               DNS:*.example.com.au, DNS:example.com.au
       
  5. Rodolfo Perottoni 2016-09-05

    Any answers on this? Could you guys try and run a test using a wildcard certificate in house ?
  6. Chee Kiat Ng 2016-09-05

    I am unable to reproduce your issue about {quote} If I change the URLs in the security manager the app still works flawlessly. At least an error should be thrown in case the URL passed to the object doesn't match the one in the certificate, right ? {quote} It's working correctly with the an error thrown A host name can only be pinned to one public key. This is my environment and this is my code: Ti SDK: 5.5.0.v20160831100821 APPC CLI: 5.5.0-5 APPC NPM: 4.2.7 HTTPS module: 1.1.3
       // Require in the module
       var https = require('appcelerator.https'),
           securityManager,
           httpClient;
       
       var securityManager = https.createX509CertificatePinningSecurityManager([
           {
               url: "https://google.com",
               serverCertificate: "goog.der"
           },
           {
               url: "https://google.com",
               serverCertificate: "faceboo.der"
           }
       ]);
       
       var httpClient = Ti.Network.createHTTPClient({
           onload: function(e) {
               Ti.API.info("Received text: " + this.responseText);
       //        alert("Received text: " + this.responseText);
           },
           onerror: function(e) {
               Ti.API.error(e.error);
       //        alert(e.error);
           },
           timeout : 5000,
           // You can only set this property when creating the HTTPClient
           securityManager: securityManager,
           validatesSecureCertificate : true,
           tlsVersion : Titanium.Network.TLS_VERSION_1_0,
       	autoEncodeUrl: false
       });
       
       httpClient.open("GET", "https://docs.google.com");
       httpClient.send();
       
       
    And wildcards work just fine. I have attached the der files if you need them. I haven't configured fiddler but from what we understand from our iOS implementation, we based it entirely on apple's API for TLS and SSL, so the packet encryption should be equivalent to native behavior. The HTTPS module's certificate pinning is only for determining if party A is party A, and party B is party B (prevent MITM). May I suggest you have another look at the implementation? at least to make sure that the error *is* thrown when using the same url, before we investigate the other claims? Thanks.
  7. Rodolfo Perottoni 2016-09-05

    The error you're getting is being caused because you're trying to use 2 different certificates to the same URL. I can get this error too if I use the code you shared above. Can you please install Fiddler with the link I provided above and double check if the SSL Pinning is working for you ? Trusting the "no errors showing, no problems happening" premise was our first mistake... you shouldn't be able to see the content of packets originated by the app. Thanks!
  8. Rodolfo Perottoni 2016-09-06

    Waiting...
  9. Eric Wieber 2016-09-07

    I set up Fiddler on my Windows machine, configured my iOS device to send traffic to it, then tested the above code samples as well as modified the URLs and HTTPClient properties. I was not able to reproduce this issue. All of my packets were encoded. After installing a recommended plugin, I had the option to decode them and they would then appear in plain text. A menu option also appeared (under 'Rules') to 'Remove All Encodings' and after selecting that, everything was decoded automatically.
  10. Rodolfo Perottoni 2016-09-12

    @Chee Kiat Ng
  11. Shak Hossain 2016-09-13

    [~rdperottoni] - can you please file a support ticket with us? As of now this is not indicating any platform issue. If you file support ticket (under your enterprise org), we can prioritize this and our support team can help to troubleshoot this further.
  12. Rodolfo Perottoni 2016-09-13

    No, I can't until a proper testing is done according to what I've commented above: bq. The error you're getting is being caused because you're trying to use 2 different certificates to the same URL. I can get this error too if I use the code you shared above. bq. Can you please install Fiddler with the link I provided above and double check if the SSL Pinning is working for you ? Trusting the "no errors showing, no problems happening" premise was our first mistake... you shouldn't be able to see the content of packets originated by the app. bq. Thanks!
  13. Chee Kiat Ng 2016-09-15

    [~rdperottoni] In your description of your issue at the very beginning, you said {quote} This code works correctly. Now if we change the URLs of the Security Manager to:
        var securityManager = https.createX509CertificatePinningSecurityManager([
            {
                url: "https://google.com",
                serverCertificate: "certificate_server1.der"
            },
            {
                url: "https://google.com",
                serverCertificate: "certificate_server2.der"
            }
        ]);
        
    Everything still works normally. Correct me if I'm wrong, but I don't think that's normal. {quote} I understand from this that you are saying 1 url + 2 certs = working = wrong behavior. But when i try to reproduce, i got 1 url + 2 certs = not working = correct behavior. So I think there's no problems here. please also see my colleague's comments when he tried to reproduce using Fiddler.
  14. Rodolfo Perottoni 2016-09-15

    Hey Kiat. I've seen Eric's answer. And yes, the problem itself is that the packets are decodable. Since day 1 of our Team plan we thought that no one would be able to see / decode our packets because of the SSL pinning. Because well.. that's the purpose of it. The app should not work if the packets being sent by it were intercepted by an authority other than the server (which has the same certificate used for creating the handshake). Any suggestions on what we should do now ?
  15. Chee Kiat Ng 2016-09-16

    We'll investigate further.
  16. Hans Knöchel 2016-09-20

    Hey [~rdperottoni], I am taking a look now. Some general questions beforehand: - Is it only happening to wildcard-certificates or certificates in general? - Did it work with earlier versions of the module and/or Titanium SDK? - -Does changing the value of autoEncodeUrl to true change something?- - I read about changing https://*.server.com/ to *.server.com, please try that. If the error "Scheme must be https for URL xxxx" is thrown, let me know. Please revalidate and answer those ones very closely. I will setup the environment and do some code-level tests afterwards. I am wondering especially about the answer regarding the latter one, since that might be the causing one.
  17. Rodolfo Perottoni 2016-09-21

    Hey Hans. * I don't have other certificates to test this; * I don't know. We only tested the SSL pinning a couple of weeks ago and discovered that it was not working (since we can see the packets). We assumed in the first time we implemented it (Nov/2015) that it was working normally since no errors were being presented to us. * Tried doing that and got this error:
        Error: *** setObjectForKey: key cannot be nil
        
  18. Rodolfo Perottoni 2016-10-03

    Following up on this ticket: Hans asked me to run a test using *2.0.0* and removing the https://. I'm getting the same error as reported above:
        [ERROR] Error: *** setObjectForKey: key cannot be nil 
        [ERROR] File: od_plugins/network/http.js 
        [ERROR] Line: 3 
        [ERROR] SourceId: <null> 
        [ERROR] Backtrace: 
        [ERROR] undefined
        
  19. Hans Knöchel 2016-10-03

    Ok, so that error is in your http-class and indicates that you want to set a key-value with a key that does not exist, did you validate that before? I just attached an example project we used to test certificates and it worked using the changes. Example-project: https://www.dropbox.com/s/g29qqngr0lwqvzo/appc-https-example.zip?dl=1
  20. Rodolfo Perottoni 2016-10-03

    In the project you mentioned above you're not using the **.server.com* syntax you told me. What's the right syntax then? The only different thing between my project and yours is the *serverCertificate*.
  21. Rodolfo Perottoni 2016-10-11

    1 week without any replies.
  22. Jan Vennemann 2016-10-11

    Rodolfo, can you please use this new example project and test it together with the module version 2.0.1 which Hans will send you? https-test: https://www.dropbox.com/s/cjmuip8b057r4jr/https-test.zip?dl=1 I tested this project with the iOS 10.0 Simulator on my Mac together with Fiddler on my Windows machine. Steps used for testing: * Start Fiddler and make sure HTTPS decryption is disabled by unchecking Tools > Fiddler Options > HTTPS > Decrypt HTTPS traffic * [Configure Fiddler for Mac](http://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/ConfigureForMac) when using the Sim or [Configure for iOS](http://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/ConfigureForiOS) when running on Device. * Build the attached example app with appc run -p ios -I 10.0 -l trace * Run the different test cases by tapping the buttons. The expected test result is displayed in the App and should match the actual result displayed in the undermost label and logs in the console. Also all traffic in Fiddler should be encrypted and not readable. * To emulate a Man-in-the-middle attack enable HTTPS decryption in Fiddler by checking Tools > Fiddler Options > HTTPS > Decrypt HTTPS traffic. * The first two tests will now also fail due to wrong SSL certs. The Appcelerator one will still succeed because its not configured for SSL Pinning and should be the only request where you can read decrypted HTTPS traffic. Please let us know about any different behaviour between the URLs i used for testing and your own server URLs.
  23. Rodolfo Perottoni 2016-10-16

    I didn't receive the 2.0.1 module. Can someone send it to me in my e-mail ?
  24. Rodolfo Perottoni 2016-10-17

    Just confirmed that the 2.0.1 release is working properly. You can close this ticket.
  25. Eric Merriman 2018-08-06

    Cleaning up older fixed issues. If this issue should not have been closed as fixed, please reopen.

JSON Source