Securing Your Communications

Why (Android) SSL isn't always secure...
and how to make it secure

By Dennis M. Sosnoski, Sosnoski Software Associates Ltd

## About me Java and Scala developer, writer, consultant and training instructor Open source developer * Apache CXF web services for Java * JiBX XML data binding for Java * Apache Axis2 web services for Java, other older projects Security background from data communications and enterprise systems experience Consulting and training services to clients worldwide Currently developing new products for secure personal communications

Security background

White spy

There are many threats to your data security:

  • Unaffiliated hackers
  • Criminal organizations
  • National governments

If your data is "valuable", any or all of these may target you

All you can do is make it as difficult as possible

This talk looks at securing communications

Black spy
## SSL isn't secure (in general) Usually relies on commercial certificates Allows obsolete/insecure options Man-in-the-middle attacks can take over the connection: * Directly, by using a fraudulent certificate * Indirectly, by weakening strength so encryption can be broken Data can be stored for later decryption: * When private keys are obtained (computer or legal hacks) * Long term, when better decryption technologies become available If you control both ends of the connection, you can fix these weaknesses If you control one end, you can at least make them harder to exploit
## Android SSL isn't secure SSL implementation part of system * Conscrypt JSSE implementation * JNI wrapper for OpenSSL native code * Devices may be using outdated versions The good news: * Most **client** security issues in older versions are minor * Your app can use new Play Services ProviderInstaller API to update The bad news: * **Server** security issues potentially more significant * Newer / better security options not supported (TLS 1.2, GCM, etc.) The mixed news: * You can use BouncyCastle / SpongyCastle as an alternative
## BouncyCastle BouncyCastle is fully portable Java code (no native components) Long-running project, widely used as JCE implementation * Largely motivated by need to subvert US regulations * First version released May 2000 (27K lines) * Current version 1.51 released July 2014 (>300K lines) * Also supports many other crypto functions * But some drawbacks: * Poorly documented for direct use * API changes from one version to the next * Performance much worse than native code Then-current version of BouncyCastle included in Dalvik library SpongyCastle renames packages to allow your own version
## Public key cryptography Uses a pair of linked key values * Private key must be kept secret by owner * Public key may be known to anyone Based on mathematical problems with no known "efficient" solution * Factorization * Discrete logarithm * Elliptic curve Easy to generate a pair of key values that will work together Much, much, more difficult to find the private key value given the public key
## Using public-private key pairs Encryption the basic operation Public key used to encrypt data for holder of private key * Anyone with access to the public key can encrypt data * Only the holder of the private key can decrypt Data encrypted with private key can be decrypted by anyone with public key * Q. What's the point of an encrypted message anyone can read? * A. If the recipient knows what the message is supposed to be, they can verify it came from you
## Digital signatures Cryptographic hash algorithms: * Take any number of bytes as input (message) * Produce a fixed-length output (digest) * Given a message, very hard to alter without changing digest * Given just a digest value, very hard to find any message to match * So very hard to find two different messages with the same digest Digital signatures encrypt digest using private key Anyone with public key can decrypt and verify digest If the recomputed digest matches the decrypted digest, then: * 1) The message was from the holder of the private key, and * 2) The message was not altered in transit

Certificates

Certificate

Certificate wraps public key inside digital signature

  • Includes identity information for the private key holder
  • Signed by a trusted source to vouch for authenticity

X.509 certificates most widely used

  • Issuer information
  • Certificate serial number and valid time span
  • Subject information for private key holder:
    • Country, state or province, locality
    • Organization name and unit
    • Common name (for SSL, the host and domain name)
  • Not designed for the internet, overly complex and much irrelevance
## Certificate authorities Certificate authorities are organizations trusted to issue certificates * Root public authorities have certificates hard-coded into software * Delegate authority to other authorities via certificates (recursively) Your software will unquestioningly accept a certificate signed by _any_ authority in hierarchy * Mozilla products have 166 trusted root certificates * Oracle Java 7 has 81 trusted root certificates * Android (git code) has 156 trusted root certificates * Counting secondary certificate authorities, number certainly in 100s and possibly 1000s
## The problems with trust Public certificate authorities can't be trusted! Don't always verify certificate they issue is really for "owner" * Authorities make money by issuing certificates * No liability to them if they issue to wrong party * Worst ones eventually may get eliminated, but still a lot of slop Authorities have been hacked and had their private keys stolen Many are under the control of governments (legally or not)
## Knowing where to go Connections normally use human-readable names Domain Name System (DNS) used to convert names to IP addresses * System asks DNS server for the IP address matching a name * If the DNS server has the information cached it just sends it back * If not cached, the DNS server queries other servers to find it * Names cached for a limited period of time Cache poisoning attacks add wrong information to DNS server cache * Attacker sends fake DNS response to caching server * If server accepts the response as valid, it will misdirect traffic Harder now than it used to be, but still possible in many cases

Bandits on the road

Burglar

Internet connections routed through intermediaries

  • Local network routers
  • ISP routers
  • Backbone routers

Routers can be hacked

  • Illegal hacks common
    • Router software often has poor security
    • Need firmware updates to fix known problems
    • Criminal organizations (and NSA) track hacks
  • "Legal" hacks also common
    • NSA monitors/subverts internet backbones
    • GCHQ monitors/subverts international cables
    • Likely NSA and others insert backdoors in routers
## Man-in-the-middle Both DNS cache poisoning and hacked routers allow man-in-the-middle * Pretends to be server in talking to client * Pretends to be client in talking to server * Sees, and can interfere with, everything going both ways... * Unless connection is secured! If man-in-the-middle has fake certificate client accepts, game over Even without an accepted fake certificate, may still be able to break in
## Blocking fake certificates No good approaches for browsers * Can use browser extensions to monitor certificate changes * Works on selected sites * But multiserver sites will give you constant warnings * No way to tell when a fake has been inserted * Certificate or authority pinning in browser best solution Easiest approach for software is to install server certificate on client * Configure software to trust *only* that certificate * Provides certainty that you're really talking to the server If working with many servers, alternative is to be your own authority * Configure software to only trust certificates signed by your authority * Need to install authority certificate, but less work when many servers

Java per-connection certificate control

At a per-connection level:

        // open the keystore
        KeyStore keyStore = KeyStore.getInstance("JKS");
        FileInputStream fis = new FileInputStream(Constants.TRUSTSTORE_NAME);
        keyStore.load(fis, Constants.TRUSTSTORE_PASS.toCharArray());
        
        // create trust manager that trusts only the server certificate
        String alg = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmfact = TrustManagerFactory.getInstance(alg);
        tmfact.init(keyStore);
        X509TrustManager tm = (X509TrustManager)tmfact.getTrustManagers()[0];
        
        // create the connection configured to use trust manager
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, new TrustManager[] { tm }, null);
        SSLSocketFactory sockfactory = context.getSocketFactory();
        ((HttpsURLConnection)conn).setSSLSocketFactory(sockfactory);
        conn.connect();
        conn.getInputStream();
## Being the authority Can generate self-signed certificates: * Offline, using Java keytool, Portecle or similar tool * In application code, using BouncyCastle * But needs to be shared securely! Can create your own certificate authority with open source: * OpenSSL for manual process * [EJBCA](http://www.ejbca.org/) for online management * EJB implementation, runs on EJB servers such as JBoss * Supports CRL, OCSP, OCSP stapling
## SSL and TLS Secure Socket Layer (SSL) the original protocol from Netscape First public release version 2.0 (1995) * Many security issues, should never be used! (but is) Version 3.0 a complete redesign (1996) * Better security, but questionable Transport Layer Security (TLS) an internet standard * Version 1.0 an upgrade of SSL v3.0 (1999), but still questionable * Version 1.1 better protection against attacks (2006), good * Version 1.2 adds more algorithms (2008), best practice Many browsers stuck on SSL 3.0 and TLS 1.0 So was Android! * TLS 1.1/1.2 not supported until Android 4.1 (Jellybean) * Not __enabled__ by default until Android 5.0

Negotiating a connection

Initial steps in establishing a secure connection:

  1. Client sends ClientHello message:
    • Highest protocol version supported
    • Suggested ciphersuites
    • Random number
  2. Server sends ServerHello message
    • Chosen protocol version
    • Chosen ciphersuite
    • Random number
  3. Server sends Certificate message with actual cert
  4. Server sends ServerHelloDone message

Remaining steps use server cert to secure exchange

Bug Greeting
## Breaking the security Man-in-the-middle may be able to interfere with negotiation: * Modify *ClientHello* for weaker protocol version and ciphersuites * Negotiated connection has weak protection and easy to break TLS includes protection against this type of attack * TLS 1.0 may be vulnerable * TLS 1.1, 1.2 should not be Browsers don't generally allow you to restrict to latest versions Software should let you set the version to be used * Java can be controlled per-connection in code * But older Android only allows up to TLS 1.0 * Newer Android needs you to specifically enable

Anything you've ever said or done online...

NSA Utah

NSA already able to break much encryption

  • Massive hardware — for RC4? or RSA 1024-bit keys?
  • Deliberate weaknesses in algorithms — elliptic curves?
  • Clandestine access to private keys for major companies?

Looks like NSA is starting(?) to store encrypted intercepts

  • Majority of internet traffic is media
  • Most of what remains is published pages
  • Very little internet traffic is actually personal

Decryption can be done later (technology, or stolen keys)

Spy
## Perfect forward secrecy Perfect forward secrecy protects from intercepts Diffie-Hellman key exchange the standard: * Based on multiplicative properties of groups of integers * Uses agreed large prime number __p__ and base number __g__ * Alice picks secret __a__ and computes __x = g^a mod p__, sends to Bob * Bob picks secret __b__ and computes __y = g^b mod p__, sends to Alice * Alice computes __s = y^a mod p__ * Bob computes __s = x^b mod p__ * In both cases __s = g^(a*b) mod p__ * __s__ can be used to encrypt messages between Alice and Bob Can be unbreakable with known mathematics in any reasonable time But still requires certificate to establish identity!
## Requiring forward secrecy TLS supports many different protocol suites Chromium browser will tell you specifics in use on connection For applications you can specify what you want Best current choices for perfect forward secrecy in Java probably: * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 or * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 or * AES_256 versions of the above (bigger not necessarily better) Not clear which of these are supported on Android
## Getting the latest Conscrypt Conscrypt is Android's version of OpenSSL code Since approximately June, can update through Play Services Uses ProviderInstaller API with Context#createPackageContext Audience participation code...
## Using SpongyCastle SpongyCastle gives you better security options * Newer TLS protocol support: * Client and server TLS 1.1 * Support for DTLS 1.0 * Uses UDP instead of TCP * Good for minimal latency (and potentially lossy) communications * Full set of ciphersuites (including GCM) * Demonstration
## References Keeping Your Secrets - http://www.infoq.com/articles/keeping-your-secrets Java code github - https://github.com/dsosnoski/keep-secrets Portecle key/certificate tool - https://sourceforge.net/projects/portecle dd-wrt open source router firmware - http://www.dd-wrt.com/site/index ProviderInstaller - http://developer.android.com/reference/com/google/android/gms/security/ProviderInstaller.html BouncyCastle - http://bouncycastle.org/ SpongyCastle - http://rtyley.github.io/spongycastle/ Bruce Schneier on personal security - http://www.theguardian.com/world/2013/sep/05/nsa-how-to-remain-secure-surveillance Sosnoski Software Associates Ltd. * New Zealand and worldwide - http://www.sosnoski.co.nz * United States - http://www.sosnoski.com