<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">
	<channel>
		<title>Android App Penetration Testing Guide | Infinum</title>
		<atom:link href="https://infinum.com/blog/how-to-prepare-your-android-app-for-a-pentest/feed/" rel="self" type="application/rss+xml" />
		<link>https://infinum.com/blog/how-to-prepare-your-android-app-for-a-pentest/</link>
		<description>Building digital products</description>
		<lastBuildDate>Thu, 23 Apr 2026 13:14:19 +0000</lastBuildDate>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>

					<item>
				<image>
					<url>8029https://infinum.com/uploads/2020/01/how-to-prepare-your-android-app-for-a-pentest-0.webp</url>
				</image>
				<title>How to Prepare Your Android App for a Pentest – Networking Edition</title>
				<link>https://infinum.com/blog/how-to-prepare-your-android-app-for-a-pentest/</link>
				<pubDate>Mon, 13 Jan 2020 09:54:00 +0000</pubDate>
				<dc:creator>Renato Turić</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/how-to-prepare-your-android-app-for-a-pentest/</guid>
				<description>
					<![CDATA[<p>Making security a priority is a must when developing an app, especially if you deal with sensitive user information.</p>
<p>The post <a href="https://infinum.com/blog/how-to-prepare-your-android-app-for-a-pentest/">How to Prepare Your Android App for a Pentest – Networking Edition</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-369"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-92">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-95"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-93">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-94'
	>
	Android app penetration testing is a must when developing an application, especially if you deal with sensitive user information. To identify the weak spots in your application’s security, it is good practice to have it tested by mobile security experts. The testing method they use for this is called <a href="https://infinum.com/cybersecurity/penetration-testing/">penetration testing</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-98"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-96">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-97'
	>
	<strong>Penetration tests</strong>, aka <em>pentests</em>, are <a href="https://infinum.com/cyber-security-penetration-testing/" id="https://infinum.com/cyber-security-penetration-testing/">simulated cyber attacks</a> on your application designed to find exploitable vulnerabilities. Android developers can then use the penetration test results to improve the app’s security.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-105"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<a	class="card-simple js-card-simple card-simple--is-ad block-card__card-simple card-simple--has-link js-card-simple-link card-simple__content-align--left"
	data-id="es-99"
	 target='_blank' rel='noopener noreferrer' href='https://infinum.com/cybersecurity/penetration-testing/'>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<p	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-100'
	>
	Penetration testing is the first step you should take to keep your business safe. Explore our pentesting services and discover any vulnerabilities in your system before malicious actors do.</p>		</div>

		<button	class="btn btn--color-infinum btn--size-small btn--width-default btn__icon-position--right card-simple__btn js-block-card-btn js-card-simple-link"
	data-id="es-102"
	 tabindex='-1'>
		<div class="btn__inner">
					<div	class='typography typography--size-none js-typography btn__label'
	data-id='es-103'
	>
	Find out more </div>		
		<i
	class="icon btn__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='arrow-right-16' data-id='es-104'>
	<svg fill='none' height='16' viewBox='0 0 17 16' width='17' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g stroke='currentColor' stroke-width='2'><path d='m.5 7.99999 14 .00001'/><path d='m9.23352 2.7251 5.97848 5.97852'/><path d='m9.23352 13.2744 5.97848-5.9785'/></g></svg></i>	</div>
	</button>	</div>
</a>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-108"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-106">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-107'
	>
	The comprehensive guide to Android app penetration testing</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-111"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-109">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-110'
	>
	In this blog post, we will concentrate on the <strong>networking part</strong> of Android app penetration testing – specifically on the TLS protocol, and tips on making your app as secure as possible when connecting to a specific web service.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-114"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-112">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-113'
	>
	Furthermore, this post is the first in <strong>a series of articles about pentesting</strong>, which will present an overview of what you can expect when having your app pentested. The <a href="https://infinum.com/api-penetration-testing/">pentesting articles</a> will also provide recommendations on the necessary preparations ahead of it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-117"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-115">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-116'
	>
	<em>Disclaimer: In our examples, we will use <a href="https://square.github.io/okhttp/">OkHttp</a> for the integration part, because it is a well established library and probably the most popular one in the Android community.</em></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-120"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-118">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-119'
	>
	TLS connection</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-123"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-121">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-122'
	>
	Most applications today communicate with a web service of some kind. Therefore, it’s very important to have a secure connection.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-126"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-124">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-125'
	>
	The worst case scenario is having an app that uses HTTP connection without the Transport Layer Security (TLS) protocol. It will inevitably fail because your data will be transferred in plain text – and therefore, very easy to track. TLS is a core part of encrypted communication, which makes HTTPS calls secure and authenticated.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-129"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-127">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-128'
	>
	Even though it is based on SSL 3.0, you will often hear people using SSL as a synonym for TLS- That’s not 100% correct as SSL, a predecessor for TLS, was deprecated in <a href="https://tools.ietf.org/html/rfc7568">2015</a> by the IETF.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-132"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-130">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-131'
	>
	In fact, most of the big companies are switching to TLS 1.2 as the Internet’s new minimum standard, starting from early 2020. (<a href="https://blog.mozilla.org/security/2018/10/15/removing-old-versions-of-tls/">Mozzila</a>, <a href="https://security.googleblog.com/2018/10/modernizing-transport-security.html">Google</a>, <a href="https://blogs.windows.com/msedgedev/2018/10/15/modernizing-tls-edge-ie11/">Microsoft</a>, <a href="https://webkit.org/blog/8462/deprecation-of-legacy-tls-1-0-and-1-1-versions/">Apple</a>).</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-135"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-133">
	<h2	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-134'
	>
	What does Android OS offer, with regard to TLS?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-138"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-136">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-137'
	>
	According to the <a href="https://developer.android.com/reference/javax/net/ssl/SSLSocket#default-configuration-for-different-android-versions">documentation</a>, Android supports TLS 1.2 since API level 16, and is enabled by default since level 21. Unfortunately, this is not 100% correct either.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-141"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-139">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-140'
	>
	Yes, you can rely on TLS 1.2 from API level 21/22 and above. However, you cannot count on that for API levels 16 to 19. There is an excellent article written by Ankush Gupta that describes this problem in more detail, so feel free to <a href="https://medium.com/tech-quizlet/working-with-tls-1-2-on-android-4-4-and-lower-f4f5205629a">check it out</a> if you want to know more about the how and why.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-144"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-142">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-143'
	>
	With the knowledge of what Android OS offers and the goal of achieving a secure connection using at least TLS 1.2, we’re moving on to the implementation guide.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-147"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-145">
	<h2	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-146'
	>
	Preparation phase in Android app penetration testing – What you’ll need to know</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-150"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-148">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-149'
	>
	We will cover two specific cases in this section of the Android app penetration testing guide. The first case is when your minSdk is between API levels 16 and 19. In the other case, your minSdk is API level 21 or higher.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-153"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-151">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-152'
	>
	MinSdk between API levels 16 and 19</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-156"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-154">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-155'
	>
	If you want TLS 1.2 enabled on versions before Android 5, you will have to extend the <code>SSLSocketFactory</code> and create your own implementation. The implementation is quite straightforward, and would look something like this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-158"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">class TlsSocketFactory </span><span class="token">constructor</span><span class="token">(</span><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token">val </span><span class="token">socketFactory</span><span class="token">: </span><span class="token" style="color: #6f42c1;">SSLSocketFactory</span><span class="token">) </span><span class="token">: </span><span class="token" style="color: #6f42c1;">SSLSocketFactory</span><span class="token">() {
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun getDefaultCipherSuites</span><span class="token">()</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Array</span><span class="token">&lt;</span><span class="token" style="color: #6f42c1;">String</span><span class="token">&gt; </span><span class="token">{
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">return</span><span class="token"> socketFactory.defaultCipherSuites
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun getSupportedCipherSuites</span><span class="token">()</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Array</span><span class="token">&lt;</span><span class="token" style="color: #6f42c1;">String</span><span class="token">&gt; </span><span class="token">{    
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">return</span><span class="token"> socketFactory.supportedCipherSuites
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun createSocket</span><span class="token">(socket</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Socket</span><span class="token">?</span><span class="token">, host</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">?</span><span class="token">, port</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Int</span><span class="token">, autoClose</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">)</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Socket</span><span class="token"> </span><span class="token">{
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">return</span><span class="token"> socketFactory</span><span class="token">.createSocket</span><span class="token">(socket, host, port, autoClose)</span><span class="token">.enableTls</span><span class="token">()
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun createSocket</span><span class="token">(host</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">?</span><span class="token">, port</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Int</span><span class="token">)</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Socket</span><span class="token"> </span><span class="token">{
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">return</span><span class="token"> socketFactory</span><span class="token">.createSocket</span><span class="token">(host, port)</span><span class="token">.enableTls</span><span class="token">()
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun createSocket</span><span class="token">(host</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">?</span><span class="token">, port</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Int</span><span class="token">, localHost</span><span class="token">: </span><span class="token" style="color: #6f42c1;">InetAddress</span><span class="token">?</span><span class="token">, localPort</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Int</span><span class="token">)</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Socket</span><span class="token"> </span><span class="token">{
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">return</span><span class="token"> socketFactory</span><span class="token">.createSocket</span><span class="token">(host, port, localHost, localPort)</span><span class="token">.enableTls</span><span class="token">()
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun createSocket</span><span class="token">(host</span><span class="token">: </span><span class="token" style="color: #6f42c1;">InetAddress</span><span class="token">?</span><span class="token">, port</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Int</span><span class="token">)</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Socket</span><span class="token"> </span><span class="token">{
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">return</span><span class="token"> socketFactory</span><span class="token">.createSocket</span><span class="token">(host, port)</span><span class="token">.enableTls</span><span class="token">()
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun createSocket</span><span class="token">(address</span><span class="token">: </span><span class="token" style="color: #6f42c1;">InetAddress</span><span class="token">?</span><span class="token">, port</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Int</span><span class="token">, localAddress</span><span class="token">: </span><span class="token" style="color: #6f42c1;">InetAddress</span><span class="token">?</span><span class="token">, localPort</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Int</span><span class="token">)</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Socket</span><span class="token"> </span><span class="token">{
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">return</span><span class="token"> socketFactory</span><span class="token">.createSocket</span><span class="token">(address, port, localAddress, localPort)</span><span class="token">.enableTls</span><span class="token">()
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token">fun Socket.enableTls</span><span class="token">()</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Socket</span><span class="token"> </span><span class="token">{
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">if</span><span class="token"> (</span><span class="token" style="color: #005cc5;">this</span><span class="token"> </span><span class="token" style="color: #d73a49;">is</span><span class="token"> SSLSocket) enabledProtocols </span><span class="token" style="color: #d73a49;">+=</span><span class="token"> TlsVersion.TLS_1_2</span><span class="token">.javaName</span><span class="token">()
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">return</span><span class="token"> </span><span class="token" style="color: #005cc5;">this</span><span class="token">
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-161"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-159">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-160'
	>
	This implementation contains our own <code>socketFactory</code> object, which we use as a delegate and simply update the enabled protocols.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-164"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-162">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-163'
	>
	Now that we have a custom <code>SSLSocketFactory</code> implementation, we have to tell OkHttp to use it via the <code>sslSocketFactory</code> builder parameter:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-166"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token"> </span><span class="token" style="color: #d73a49;">if</span><span class="token"> (Build.VERSION.SDK_INT </span><span class="token" style="color: #d73a49;">&lt;</span><span class="token"> Build.VERSION_CODES.LOLLIPOP_MR1) {
</span></span><span class="line"><span class="token">    </span><span class="token">val </span><span class="token">sslContext </span><span class="token" style="color: #d73a49;">=</span><span class="token"> SSLContext</span><span class="token">.getInstance</span><span class="token">(TlsVersion.TLS_1_2</span><span class="token">.javaName</span><span class="token">())
</span></span><span class="line"><span class="token">    sslContext</span><span class="token">.init</span><span class="token">(</span><span class="token" style="color: #005cc5;">null</span><span class="token">, </span><span class="token" style="color: #d73a49;">*</span><span class="token">yourTrustManagers</span><span class="token" style="color: #d73a49;">*</span><span class="token">, </span><span class="token" style="color: #005cc5;">null</span><span class="token">)
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">sslSocketFactory</span><span class="token">(</span><span class="token">TlsSocketFactory</span><span class="token">(sslContext.socketFactory), </span><span class="token" style="color: #d73a49;">*</span><span class="token">yourTrustManager</span><span class="token" style="color: #d73a49;">*</span><span class="token">)
</span></span><span class="line"><span class="token"> }
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-169"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-167">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-168'
	>
	The <em>yourTrustManagers</em> represent an array of <code>TrustManager</code> instances. If you don’t know how to create your own trust manager – or if you don’t need custom implementation, you can always load the default one. You will learn how to load the default trust manager in the next section, discussing certificates.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-172"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-170">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-171'
	>
	Note that the above-stated <code>TlsSocketFactory</code> implementation only sets the specified protocol as the default. It does not cover the case in which the protocol is not installed on the device. To cover that instance, you will have to use the <code>ProviderInstaller</code> from Google Play services.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-175"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-173">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-174'
	>
	Also, keep in mind that you can either call <code>installIfNeeded(context)</code> or <code>installIfNeededAsync(context)</code>, and that it has to be done before creating the TlsSocketFactory.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-178"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-176">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-177'
	>
	For a more specific implementation, you can check the sample implementation on these gists: <a href="https://gist.github.com/Aksi0m/2e60f7a8e5708d37be89362b682c6111">installIfNeeded</a>, <a href="https://gist.github.com/Aksi0m/5c51632d43390c0018151b3cbc14bd8c">installIfNeededAsync</a>. These implementations are provided by the OWASP team and can be found in the <a href="https://github.com/OWASP/owasp-mstg/releases/tag/1.1.3-excel">OWASP-MSTG book 1.1.3</a> on pages 206, 207 and 208.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-181"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-179">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-180'
	>
	MinSdk API level 21+</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-184"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-182">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-183'
	>
	If this is the case, you should use at least OkHttp 3.13.x – and it works only on Android 5+. If you’re already using that version of Android, you’re good to go, as this library version already uses TLS 1.2 as a default for all HTTPS calls.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-187"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-185">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-186'
	>
	If you are using an older version of the OkHttp library and cannot update it for whatever reason, you must follow the steps described in the section <em>MinSdk between API levels 16 and 19</em> above.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-190"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-188">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-189'
	>
	By the way, if you are interested in the history of TLS configuration in OkHttp, <a href="https://square.github.io/okhttp/tls_configuration_history/">this</a> is a superb read.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-193"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-191">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-192'
	>
	Returning to the topic – now that your app uses a more secure version of the TLS protocol, it’s important to know how to successfully verify a TLS connection.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-196"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-194">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-195'
	>
	Verifying a TLS connection</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-199"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-197">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-198'
	>
	Two parts are essential in the process of verifying a TLS connection:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-202"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-200">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-201'
	>
	<li>Certificate verification (Certificate pinning)</li><li>Hostname verification</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-205"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-203">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-204'
	>
	In the following paragraphs, we’ll go over the specifics of each one.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-208"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-206">
	<h2	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-207'
	>
	Certificate verification (Certificate pinning)</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-211"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-209">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-210'
	>
	This section of the Android app penetration testing guide will focus on <strong>certificate pinning</strong> and how to implement it. In addition, we’ll briefly examine how certificate verification is done.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-214"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-212">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-213'
	>
	For a TLS connection to work as expected, the Client must have a way of verifying that a certificate used on the server is trusted and valid. In our case, the Client is the Android app. This is where <strong>Certificate Authorities (CA)</strong> enter the stage.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-217"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-215">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-216'
	>
	A CA is an entity that is eligible to issue a trusted, time-limited certificate. The certificate issued by a CA is a verifiable small data file that contains identity credentials to help websites, people, and devices represent their authentic online identity.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-220"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-218">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-219'
	>
	But how does our Android device differentiate between the certificates issued by a CA and those so-called <strong>self-signed</strong> certificates? With the help of a set of CAs, which the device has stored on the Android system level. As of 4.2, Android contains over 100 CAs, which are updated in each release.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-223"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-221">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-222'
	>
	To view all certificates in an Android device programmatically, you can load the default <code>TrustManager</code>. That way, you will see all the file paths that correspond to system-level certificates and the user-installed certificates. These certificates are also known as <strong>root certificates</strong>. To retrieve the default <code>TrustManager</code> you can use this code:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-225"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token">fun getDefaultTrustManager</span><span class="token">()</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Array</span><span class="token">&lt;</span><span class="token" style="color: #6f42c1;">TrustManager</span><span class="token">&gt;? </span><span class="token">{
</span></span><span class="line"><span class="token">    </span><span class="token">val </span><span class="token">trustManagerFactory </span><span class="token" style="color: #d73a49;">=</span><span class="token"> TrustManagerFactory</span><span class="token">.getInstance</span><span class="token">(TrustManagerFactory</span><span class="token">.getDefaultAlgorithm</span><span class="token">())
</span></span><span class="line"><span class="token">    trustManagerFactory</span><span class="token">.init</span><span class="token">(</span><span class="token" style="color: #005cc5;">null</span><span class="token"> </span><span class="token" style="color: #d73a49;">as</span><span class="token"> KeyStore?)
</span></span><span class="line"><span class="token">    </span><span class="token">val </span><span class="token">trustManagers </span><span class="token" style="color: #d73a49;">=</span><span class="token"> trustManagerFactory.trustManagers
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">if</span><span class="token"> (trustManagers.size </span><span class="token" style="color: #d73a49;">!=</span><span class="token"> </span><span class="token" style="color: #005cc5;">1</span><span class="token"> </span><span class="token" style="color: #d73a49;">||</span><span class="token"> trustManagers[</span><span class="token" style="color: #005cc5;">0</span><span class="token">] </span><span class="token" style="color: #d73a49;">!</span><span class="token" style="color: #d73a49;">is</span><span class="token"> X509TrustManager) {
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">throw</span><span class="token"> </span><span class="token">IllegalStateException</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Unexpected default trust managers:</span><span class="token" style="color: #032f62;">&quot;</span><span class="token"> </span><span class="token" style="color: #d73a49;">+</span><span class="token"> Arrays</span><span class="token">.toString</span><span class="token">(trustManagers))
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">return</span><span class="token"> trustManagers
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-228"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-226">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-227'
	>
	When an Android device tries to establish a secure connection with a service, it goes through the <em>TLS handshake</em> process. During connection setup, the server can send an entire chain of certificates which the device has to verify with its set of trusted CAs.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-231"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-229">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-230'
	>
	The certificate chain is also known as <em>the chain of trust,</em> which is a linked path of verification and validation from the end user (in our case the Android device) to a root certificate.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-234"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-232">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-233'
	>
	The certificates in the chain consist of a <strong>root certificate</strong>, zero or more <strong>intermediate certificates</strong> and a <strong>leaf certificate</strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-237"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-235">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-236'
	>
	Check out the image below to clarify this confusion a bit:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-240"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-238"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-239">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2020/01/how-to-prepare-your-android-app-for-a-pentest-1-1400x638.webp				media='(max-width: 699px)'
				type=image/webp								height="638"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2020/01/how-to-prepare-your-android-app-for-a-pentest-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="655"
															width="1437"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Certificates in the chain are co-dependent		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-243"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-241">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-242'
	>
	As you can see, the chain certificates depend on each other. This means that attackers can exploit the chain of trust even if just one of the certificates’ CA is compromised. Developers can use the compromised CA to issue a certificate that will be automatically trusted by your Android device due to the default <code>TrustManager</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-246"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-244">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-245'
	>
	To further protect your app from fraudulently issued certificates, you can use a technique known as <em>certificate pinning</em>. Certificate pinning is an extra defense mechanism against MITM (ie. man-in-the-middle) attacks, in which the developer implements a custom trust manager that contains only the certificates which can validate the web server that the app is communicating with. Your app will neither trust any other system-trusted CA nor the user-installed certificates.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-249"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-247">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-248'
	>
	<strong>Certificate pinning</strong> is one of the most common test cases in a penetration test, so the following paragraph will elaborate on how to prepare an app for it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-252"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-250">
	<h2	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-251'
	>
	Preparation phase in Android app penetration testing &#8211; What you’ll need to know</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-255"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-253">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-254'
	>
	This section will show you how to successfully implement certificate pinning for both self-signed certificates and those issued by a CA. To pin a certificate, the first step is to decide which certificate from the certificate chain to pin.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-258"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-256">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-257'
	>
	We recommend pining the <strong>leaf certificate</strong> as the attack surface is very small, thanks to the app interacting with that certificate first. The app will not be usable if that certificate can’t be verified.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-261"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-259">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-260'
	>
	Self-signed certificates</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-264"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-262">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-263'
	>
	Pinning self-signed certificates is something you should only do for testing environments. To pin a certificate in an Android app, the first thing to do is to acquire the certificate, which can quickly be done with OpenSSL via the terminal:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-266"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-shellscript github-light" data-language="shellscript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">$</span><span class="token"> </span><span class="token" style="color: #032f62;">openssl</span><span class="token"> </span><span class="token" style="color: #032f62;">s_client</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">connect</span><span class="token"> </span><span class="token" style="color: #032f62;">example.com:443</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">showcerts</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-269"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-267">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-268'
	>
	The command above will return a list of the entire certificate chain for the specified website. If you want to save the certificates in a local file or download one via a browser, find out how to do that <a href="https://www.shellhacks.com/get-ssl-certificate-from-server-site-url-export-download/">here</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-272"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-270">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-271'
	>
	After acquiring the needed certificate, the next step is creating your custom <code>TrustManager</code> containing the certificate. This can be done as follows:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-274"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token">fun createCustomTrustManager</span><span class="token">(context</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Context</span><span class="token">)</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Array</span><span class="token">&lt;</span><span class="token" style="color: #6f42c1;">TrustManager</span><span class="token">&gt;? </span><span class="token">{
</span></span><span class="line"><span class="token">    </span><span class="token">val </span><span class="token">keyStore </span><span class="token" style="color: #d73a49;">=</span><span class="token"> KeyStore</span><span class="token">.getInstance</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">BKS</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)</span><span class="token">.apply </span><span class="token">{ </span><span class="token">load</span><span class="token">(</span><span class="token" style="color: #005cc5;">null</span><span class="token">, </span><span class="token" style="color: #005cc5;">null</span><span class="token">) }
</span></span><span class="line"><span class="token">    </span><span class="token">val </span><span class="token">certificateFactory </span><span class="token" style="color: #d73a49;">=</span><span class="token"> CertificateFactory</span><span class="token">.getInstance</span><span class="token">(CERT_TYPE)
</span></span><span class="line"><span class="token">    </span><span class="token">val </span><span class="token">trustManagerFactory </span><span class="token" style="color: #d73a49;">=</span><span class="token"> TrustManagerFactory</span><span class="token">.getInstance</span><span class="token">(TrustManagerFactory</span><span class="token">.getDefaultAlgorithm</span><span class="token">())
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    context.resources</span><span class="token">.openRawResource</span><span class="token">(R.raw.leaf_cert_expires_1_1_2077)</span><span class="token">.use </span><span class="token">{
</span></span><span class="line"><span class="token">        keyStore</span><span class="token">.setCertificateEntry</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">MyLeafCert</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">, certificateFactory</span><span class="token">.generateCertificate</span><span class="token">(it))
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    trustManagerFactory</span><span class="token">.init</span><span class="token">(keyStore)
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">return</span><span class="token"> trustManagerFactory.trustManagers
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-277"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-275">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-276'
	>
	This code loads a <code>leaf_cert_expires_1_1_2077.pem</code> file from the <code>raw</code> resource folder and sets it as a certificate entry inside our empty keystore, under <em>MyLeafCert</em> alias. After setting the required certificate in the keystore, use the same keystore to initialize the trustManagers.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-280"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-278">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-279'
	>
	With everything ready, it’s time to pass the instance of our <code>TrustManager</code> to OkHttp via the <code>sslSocketFactory</code> builder function, as described in the TLS connection section above. We sometimes call this method <em>hard certificate pinning</em> because we bundle the pinned certificate in our app, and we have to upload a new version of the app that contains the new certificate every time the certificate changes or gets renewed.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-283"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-281">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-282'
	>
	Certificates signed by a trusted CA</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-286"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-284">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-285'
	>
	Developers can similarly use the previous code sample for certificates signed by a trusted CA. This is a good approach if you want just one implementation for all cases. However, OkHttp does provide a different mechanism for pinning non self-signed certificates, using the <code>CertificatePinner</code> class. Find more information about this class <a href="https://square.github.io/okhttp/features/https/#certificate-pinning-kt-java">here</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-289"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-287">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-288'
	>
	<code>CertificatePinner</code> employs a different kind of pinning, using the certificate’s subject cryptographic public key for verification. Unlike the previously described approach, in which you need to bundle the pinned certificate with your app, public key pinning only needs the base64 SHA-256 hash value of the certificate public – considering that the hash can be safely stored as a plain string in your app without causing security issues.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-292"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-290">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-291'
	>
	The implementation is much more straightforward:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-294"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">const</span><span class="token"> </span><span class="token">val </span><span class="token">MY_LEAF_CERT_EXPIRES_1_1_2077 </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">sha256/A23dA8l41A46gjAcAiAA32AAA8juvAnvvlk85kub6A5=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token">fun buildCertificatePinner</span><span class="token">()</span><span class="token">: </span><span class="token" style="color: #6f42c1;">CertificatePinner</span><span class="token"> </span><span class="token">{
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">return</span><span class="token"> CertificatePinner</span><span class="token">.Builder</span><span class="token">()
</span></span><span class="line"><span class="token">        </span><span class="token">.add</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">yourHostname.com</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">, MY_LEAF_CERT_EXPIRES_1_1_2077)
</span></span><span class="line"><span class="token">        </span><span class="token">.build</span><span class="token">()
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Setting up OkHttp with the CertificatePinner object</span><span class="token">
</span></span><span class="line"><span class="token">OkHttpClient</span><span class="token">.Builder</span><span class="token">()
</span></span><span class="line"><span class="token">    </span><span class="token">.certificatePinner</span><span class="token">(</span><span class="token">buildCertificatePinner</span><span class="token">())
</span></span><span class="line"><span class="token">    </span><span class="token">.build</span><span class="token">()
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-297"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-295">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-296'
	>
	So there you have it &#8211; a straightforward and intuitive approach. In addition to easier implementation, this approach has another noticeable benefit. If the certificate expires, the server can renew the certificate, without changing the cryptographic public key of the certificate.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-300"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-298">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-299'
	>
	You won’t need to update the app if the certificate gets renewed. One of the downsides of this method is that it <strong>does not support</strong> self-signed certificates.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-303"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-301">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-302'
	>
	Also, in the implementation above, you probably noticed the <em>yourHostname.com</em> string. This value is used for hostname verification and we will discuss this in the next section.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-306"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-304">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-305'
	>
	Finally, keep in mind that this is only a brief introduction to certificate pinning, just enough to understand the basics and to be able to prepare your app for penetration tests. For more straightforward implementation and maintenance, certificate pinning should be agreed upon with the administrators of the web service the app is communicating with, to see whether it is a good fit.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-309"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-307">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-308'
	>
	If you decide on certificate pinning, ensure a better understanding of the entire process.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-312"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-310">
	<h2	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-311'
	>
	Hostname verification</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-315"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-313">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-314'
	>
	Finally, we’ve reached the second key part in verifying a TLS connection: <strong>hostname verification</strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-318"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-316">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-317'
	>
	A common mistake developers make is setting a permissive hostname verifier, or even worse – accepting all hostnames. This means that the attacker can issue a valid certificate with a compromised CA, choose <em>any</em> domain name for it, and execute a MITM attack.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-321"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-319">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-320'
	>
	If you use OkHttp, the default implementation of the <code>HostnameVerifier</code> will be enough to verify your connection to the host. Nevertheless, we will show you a couple of examples of how to implement <code>HostnameVerifier</code> to gain a better understanding of how it works.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-324"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-322">
	<h2	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-323'
	>
	Preparation phase in Android app penetration testing &#8211; What you’ll need to know</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-327"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-325">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-326'
	>
	If you aren’t using <code>CertificatePinner</code> for hostname verification, you can use the Java’s <code>HostnameVerifier</code>, as it is the base interface for hostname verification. OkHttp supports this interface, you just have to pass it to the <strong>hostnameVerifier</strong> builder function.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-330"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-328">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-329'
	>
	During the TLS handshake, the verification mechanism can call back to implementers of this interface to determine whether this connection should be allowed. The specific verification can be done using the <code>OkHostnameVerifier</code>, although you will stumble upon some implementations where <code>HttpsURLConnection.getDefaultHostnameVerifier()</code> is used.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-333"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-331">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-332'
	>
	Under the hood, this is still using the <code>OkHostnameVerifier</code> but from an internal Android version of the same class.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-336"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-334">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-335'
	>
	We’re ready to check a sample implementation using <code>OkHostnameVerifier.INSTANCE.verify</code>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-338"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">hostnameVerifier </span><span class="token">{ _, session </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token">
</span></span><span class="line"><span class="token">    OkHostnameVerifier.INSTANCE</span><span class="token">.verify</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">yourHostname.com</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">, session)
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-341"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-339">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-340'
	>
	The code above will check whether the entered hostname <em>yourHostname.com</em> is contained inside the certificate of the current <code>SSLSession</code>. Only if it is, the verification will succeed. In case you want to trust an entire subdomain, you can use the wildcard pattern notation, but you will have to use the <code>verifyHostname</code> method like this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-343"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">hostnameVerifier </span><span class="token">{ hostname, _ </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token">
</span></span><span class="line"><span class="token">    OkHostnameVerifier.INSTANCE</span><span class="token">.verifyHostname</span><span class="token">(hostname, </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">*.yourHostname.com</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-346"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-344">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-345'
	>
	Your chosen implementation will depend on your environment and all the services your app connects to.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-349"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-347">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-348'
	>
	Conclusion and notes</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-352"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-350">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-351'
	>
	Hopefully, you will better understand the TLS connection and how to prepare your Android app penetration testing by this point. Look for the two critical parts of a TLS connection: certificate and hostname verification. If one of these two verifications is broken, the entire TLS connection is nullified and the app becomes an easy target for MITTM attacks.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-355"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-353">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-354'
	>
	To deepen your knowledge on handling a proper TLS connection in a WebView and more, check out the <a href="https://github.com/OWASP/owasp-mstg">OWASP Mobile Security Testing Guide</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-358"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-356">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-357'
	>
	Also, if you (have) encounter(ed) any problems during the setup of a proper TLS connection, please check <a href="https://noxxi.de/howto/ssl-debugging.html">ssl-debugging</a> for answers and solutions.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-361"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-359">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-360'
	>
	One last thing – in this post we did not cover the Android <a href="https://developer.android.com/training/articles/security-config">Network security configuration</a>. This powerful tool lets apps customize their network security settings without modifying the app code.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-364"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-362">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-363'
	>
	Unfortunately, it is available only since Android 7. Still, if you are lucky enough to work on minSdk API level 24 or you are okay with having two separate pinning implementations, depending on the SDK level, then this approach should be the preferred way for handling your network configurations.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-367"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-365">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-366'
	>
	<em>If you want to look into more ways to improve the security of your digital product, explore our <a href="https://infinum.com/cybersecurity/" target="_blank" rel="noreferrer noopener">cybersecurity services</a>.</em></p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/how-to-prepare-your-android-app-for-a-pentest/">How to Prepare Your Android App for a Pentest – Networking Edition</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>