<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Toonwire</title>
    <description>The latest articles on DEV Community by Toonwire (@toonwire).</description>
    <link>https://dev.to/toonwire</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F516373%2F06a0f34d-7da6-428e-a58a-4e6c83653d62.png</url>
      <title>DEV Community: Toonwire</title>
      <link>https://dev.to/toonwire</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/toonwire"/>
    <language>en</language>
    <item>
      <title>The importance of protecting your APIs with SSL pinning</title>
      <dc:creator>Toonwire</dc:creator>
      <pubDate>Fri, 20 Nov 2020 09:53:47 +0000</pubDate>
      <link>https://dev.to/itminds/the-importance-of-protecting-your-apis-with-ssl-pinning-3nf8</link>
      <guid>https://dev.to/itminds/the-importance-of-protecting-your-apis-with-ssl-pinning-3nf8</guid>
      <description>&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;Networking is a core part of most apps, passing information between the application client and backend system(s). A very standard approach to this communication is TLS, a protocol meant for message integrity and message privacy between communicating parties. When establishing a connection using the TLS protocol, the first step is the supplying and verification of certificates.&lt;/p&gt;

&lt;p&gt;E.g. a client initiates a request and the server responds with one or more digital certificates, which are then verified (or not) by the client. This verification establishes trust between the communicating entities. Once trust has been established, the cryptograhpic step can commence and finally the information exchanges can take place, using said encryption/decryption schemes. &lt;/p&gt;

&lt;p&gt;So with SSL certificates set up and the TLS protocol invoked, our precious and secret information is securely communicated between front- and backend systems, right?&lt;/p&gt;

&lt;p&gt;Many developers will assume so (or do not care about their network security), leaving handling of the TLS session to the OS. &lt;/p&gt;

&lt;h2&gt;
  
  
  Quick history tour
&lt;/h2&gt;

&lt;p&gt;Any app will by default trust the system root certificate, but will on versions before Android 7 (Nougat), by default also trust user-defined certificates just as much. This being an obvious security issue, without developer intervention, was then changed in Android 7 and onwards to no longer accepting user-defined certificates by default. While this does make it so that the communication cannot be hijacked out-of-the-box, a very simple effort will open the security issue right back up.&lt;/p&gt;

&lt;p&gt;Let's see how easy it is to listen in on a supposedly secure channel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting the stage
&lt;/h2&gt;

&lt;p&gt;Taking a look at a real world example, I have chosen the official parking app from the Swedish municipality of Gothenburg, &lt;a href="https://play.google.com/store/apps/details?id=se.goteborg.pbolaget.android" rel="noopener noreferrer"&gt;Parkering Göteborg&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Being a parking app, the information flowing about includes the license plates of cars, credit cards for charging, along with personal user information etc. Information that &lt;em&gt;really&lt;/em&gt; should be kept secure.&lt;/p&gt;

&lt;p&gt;DISCLAIMER: &lt;em&gt;I have been in contact with the developers of this app roughly 6 months ago, and made them aware of the issues presented here. Since then, the application have received numerous updates - including its security aspects.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Exposing HTTPS traffic
&lt;/h2&gt;

&lt;p&gt;Here is a short outline of how to expose TLS communication in Android apps which rely on the OS to handle everything about the session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools needed:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ibotpeaches.github.io/Apktool/documentation/" rel="noopener noreferrer"&gt;APKTool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.charlesproxy.com/" rel="noopener noreferrer"&gt;Charles Proxy&lt;/a&gt; (Fiddler2 can be used alternatively)&lt;/li&gt;
&lt;li&gt;Java build tools 24.0.2+&lt;/li&gt;
&lt;li&gt;Android SDK&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Java build tools and Android SDK are only used for signing the apk.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make the app trust user Certificate Authorities
&lt;/h3&gt;

&lt;p&gt;Since apps will not trust user certificate authorities (since Android 7) just because the device trusts them, a small modification to the app must be made.&lt;/p&gt;

&lt;h4&gt;
  
  
  Download apk of target app
&lt;/h4&gt;

&lt;p&gt;Usually you can find the app at APKMirror or similar sites.&lt;br&gt;
E.g. &lt;a href="https://apkpure.com/parkering-g%C3%B6teborg/se.goteborg.pbolaget.android" rel="noopener noreferrer"&gt;APKPure&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Decode apk file
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;apktool d app.apk -o decoded_app&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Modify AndroidManifest.xml
&lt;/h4&gt;

&lt;p&gt;Inside the &lt;code&gt;decoded_app&lt;/code&gt; folder, find and open up the &lt;code&gt;AndroidManifest.xml&lt;/code&gt; file.&lt;br&gt;
Add &lt;code&gt;android:networkSecurityConfig="@xml/network_security_config"&lt;/code&gt; to the &lt;code&gt;application&lt;/code&gt; tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- AndroidManifest.xml --&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;application&lt;/span&gt; 
    &lt;span class="na"&gt;android:allowBackup=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; 
    &lt;span class="na"&gt;android:appComponentFactory=&lt;/span&gt;&lt;span class="s"&gt;"androidx.core.app.CoreComponentFactory"&lt;/span&gt; 
    &lt;span class="na"&gt;android:icon=&lt;/span&gt;&lt;span class="s"&gt;"@mipmap/ic_launcher"&lt;/span&gt; 
    &lt;span class="na"&gt;android:label=&lt;/span&gt;&lt;span class="s"&gt;"@string/parking_application_name"&lt;/span&gt; 
    &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"se.goteborg.pbolaget.android.ParkingApplication"&lt;/span&gt; 
    &lt;span class="na"&gt;android:theme=&lt;/span&gt;&lt;span class="s"&gt;"@style/AppTheme"&lt;/span&gt;
    &lt;span class="na"&gt;android:networkSecurityConfig=&lt;/span&gt;&lt;span class="s"&gt;"@xml/network_security_config"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Trust user Certificate Authorities
&lt;/h4&gt;

&lt;p&gt;To make the app trust user-defined certificates once again, the network security configuration file simply needs to add the user argument to a certificate tag.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;network_security_config.xml&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- network_security_config.xml --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;network-security-config&amp;gt;&lt;/span&gt;  
    &lt;span class="nt"&gt;&amp;lt;base-config&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;trust-anchors&amp;gt;&lt;/span&gt;
            &lt;span class="c"&gt;&amp;lt;!-- Additionally trust user added CAs --&amp;gt;&lt;/span&gt;  
            &lt;span class="nt"&gt;&amp;lt;certificates&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;/trust-anchors&amp;gt;&lt;/span&gt;  
    &lt;span class="nt"&gt;&amp;lt;/base-config&amp;gt;&lt;/span&gt;  
&lt;span class="nt"&gt;&amp;lt;/network-security-config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;network_security_config.xml&lt;/code&gt; to the &lt;code&gt;decoded_app/res/xml&lt;/code&gt; folder.&lt;/p&gt;

&lt;h4&gt;
  
  
  Rebuild apk file
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;apktool b decoded_app -o ca_modified_app.apk&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The new apk file can then be found at either &lt;code&gt;decoded_app/dist/ca_modified_app.apk&lt;/code&gt; or as a sibling to the &lt;code&gt;decoded_app&lt;/code&gt; folder.&lt;/p&gt;

&lt;h4&gt;
  
  
  Sign the modified app
&lt;/h4&gt;

&lt;p&gt;Here, I am using the default created android debug keystore to sign the apk&lt;br&gt;
&lt;code&gt;jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore {some_path_x}\.android\debug.keystore {some_path_y}\ca_modified_app.apk androiddebugkey -storepass android&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Install the modified app
&lt;/h4&gt;

&lt;p&gt;Transfer the &lt;code&gt;ca_modified_app.apk&lt;/code&gt; to an Android device and press to install.&lt;/p&gt;

&lt;p&gt;You may have to trust installations from outside Google Play (should prompt).&lt;/p&gt;

&lt;p&gt;We now effectively have a copy of the original app installed on our device, which trusts user-defined certificates. &lt;br&gt;
Now we just need to install one such certificate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Charles' SSL certificate
&lt;/h3&gt;

&lt;p&gt;On your device visit &lt;a href="https://chls.pro/ssl" rel="noopener noreferrer"&gt;https://chls.pro/ssl&lt;/a&gt; to download the Charles SSL certificate.&lt;/p&gt;

&lt;p&gt;After the download completes, install the certificate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Man-in-the-middle
&lt;/h3&gt;

&lt;p&gt;This step sets up your PC to act as an intermediary between the client and the server, using the HTTP(S) proxy.&lt;/p&gt;

&lt;p&gt;Open network settings for the WiFi network your device is connected to.&lt;/p&gt;

&lt;p&gt;Wi-Fi → Long press connected network → Modify network → Advanced options → Set Proxy to Manual → As hostname; enter the IPv4 address of your computer, which must be connected to the same network → As port, CharlesProxy defaults to 8888.&lt;/p&gt;

&lt;h4&gt;
  
  
  Enable SSL Proxy in Charles
&lt;/h4&gt;

&lt;p&gt;Top menu → Proxy → SSL Proxying Settings → SSL Proxying → Check Enable SSL Proxying → Include location host = * and port = * (wildcards)&lt;/p&gt;

&lt;h4&gt;
  
  
  Reading the network traffic
&lt;/h4&gt;

&lt;p&gt;Now, browsing the app will redirect all network traffic through the SSL proxy, which certificate is trusted by the device, making the traffic visible to the proxy (Charles), with exposed and unencrypted &lt;code&gt;https&lt;/code&gt; requests and responses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdiy8dqhpr4qqhy89qycq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdiy8dqhpr4qqhy89qycq.png" alt="Exposed API of Parkering Göteborg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  SSL pinning
&lt;/h2&gt;

&lt;p&gt;So what can we, as developers, do to avoid this issue? Que SSL pinning.&lt;/p&gt;

&lt;p&gt;SSL pinning is a technique which entails embedding your server certificate into the app itself. Once networking happens, the app can simply compare the certificate of the responding entity to the embedded certificate. If they do not match, chances are the response is not coming from our server. For more information on SSL security implementations, check out &lt;a href="https://developer.android.com/training/articles/security-ssl" rel="noopener noreferrer"&gt;the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The but
&lt;/h3&gt;

&lt;p&gt;Although SSL pinning is neat, this security installment can be bypassed. However it is a much more involved process, and requires rooting the device amongst other things. Alas, we can rarely achieve complete security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates
&lt;/h2&gt;

&lt;p&gt;The most recent Android version, Android 11 (September 8. 2020), introduces further certificate installation restrictions, however seemingly only those prompted by applications. So while this prevents app automation of the man-in-the-middle attack presented here, the manual process will likely still work.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this blog post. If you have any questions, feel free to comment below!&lt;/p&gt;

</description>
      <category>android</category>
      <category>security</category>
      <category>ssl</category>
      <category>tls</category>
    </item>
  </channel>
</rss>
