<?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>Author at Infinum</title>
		<atom:link href="https://infinum.com/blog/author/renato-turic/feed/" rel="self" type="application/rss+xml" />
		<link></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>51620https://infinum.com/uploads/2024/03/Mobile_Top_10_security_vulnerabilities_blogpost-hero-ig-min.webp</url>
				</image>
				<title>Secure Your App – OWASP Top 10 Mobile Risks Explained</title>
				<link>https://infinum.com/blog/owasp-top-10-mobile/</link>
				<pubDate>Wed, 06 Mar 2024 14:44:47 +0000</pubDate>
				<dc:creator>Renato Turić</dc:creator>
				<guid isPermaLink="false">https://infinum.com/?p=51620</guid>
				<description>
					<![CDATA[<p>The OWASP Top 10 Mobile provides an overview of the critical security risks mobile app providers should keep an eye on.</p>
<p>The post <a href="https://infinum.com/blog/owasp-top-10-mobile/">Secure Your App – OWASP Top 10 Mobile Risks Explained</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-356"
	 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-36-text js-typography block-typography__typography'
	data-id='es-94'
	>
	<strong>The OWASP Top 10 Mobile provides an overview of the critical security risks mobile app providers should keep an eye on. </strong></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'
	>
	Nowadays, nobody needs to explain how important mobile apps are for any business. What’s more, with the number of <a href="https://iot-analytics.com/number-connected-iot-devices/" target="_blank" rel="noreferrer noopener">connected devices in the world growing</a> practically by the minute, mobile IoT apps have an important role to play.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-101"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-99">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-100'
	>
	With such widespread use, <a href="https://www.nowsecure.com/blog/2023/12/20/the-top-5-mobile-app-security-breaches-of-2023/" target="_blank" rel="noreferrer noopener">mobile apps are very susceptible to security breaches</a>, and ignoring the security aspect of a digital product and hoping for the best is no longer a viable strategy. In the evolving digital world, safeguarding one’s business interests and maintaining customer trust is crucial for staying competitive. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-104"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-102">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-103'
	>
	Our experiment demonstrated that <a href="https://infinum.com/blog/ai-generated-code-security-risks/">even OWASP-guided prompts leave exploitable gaps</a> when the underlying code is AI-generated — the standard was applied, but system-level assumptions weren&#8217;t.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-107"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-105">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-106'
	>
	To concentrate their cybersecurity efforts, companies should first be aware of the challenges and the risks that lurk in the digital space, and <a href="https://owasp.org/www-project-mobile-top-10/" target="_blank" rel="noreferrer noopener">the OWASP Top 10 Mobile list</a> is the first step in the right direction.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-110"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-108">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-109'
	>
	How OWASP Top 10 mobile risks help companies secure their digital assets</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-113"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-111">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-112'
	>
	Mobile app security is not just about protecting technical assets. Fundamentally, it is about safeguarding a company’s reputation and customer data and possibly avoiding legal repercussions. Data breaches exposing sensitive user information or a company’s intellectual property not only result in financial losses, but severely damage customer trust.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-116"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-114">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-115'
	>
	With that in mind, it is very important that we have and nurture communities of security experts who will look into the common issues one might run into in the digital world. <a href="https://owasp.org/" target="_blank" rel="noreferrer noopener">The OWASP Foundation</a> is one of those communities. Through freely available resources like articles, methodologies, community-led projects, and conferences, the foundation actively works on enhancing digital security. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-119"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-117">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-118'
	>
	To help you digest the biggest mobile dangers of today, we provide a simplified overview of OWASP’s risks and their implications for businesses.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-126"
	 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-120"
	 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-121'
	>
	Securing your business from cyberattacks requires a holistic approach. While understanding risks like those in the OWASP Top 10 is essential, penetration testing uncovers vulnerabilities specific to your digital product. Explore our pentesting services to fortify your defenses.</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-123"
	 tabindex='-1'>
		<div class="btn__inner">
					<div	class='typography typography--size-none js-typography btn__label'
	data-id='es-124'
	>
	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-125'>
	<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-129"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-127">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-128'
	>
	OWASP Top 10 Mobile ranking overview</h2></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'
	>
	The OWASP Top 10 mobile risks list presents a refined perspective on the evolving landscape of mobile security threats. Each entry on the list is focused on a specific area of concern, emphasizing the importance of a proactive security mindset. </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">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-134'
	>
	However, security breaches in real life typically don’t happen on account of a company’s susceptibility to a single risk from OWASP’s list. Often, attackers will exploit multiple weaknesses and leverage <a href="https://infinum.com/social-engineering-testing-services/">social engineering attacks</a> to reach their malicious goals. The examples we provide indicate that a specific risk was acted upon, but we should note that interpretations may vary and that often, only the affected company knows the true cause of a breach.</p></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">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-137'
	>
	M1: Improper credential usage</h2></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'
	>
	A new entry on the OWASP list, improper credential usage is such a critical issue that it immediately earned the status of the number one security risk for this year. Hardcoded or poorly managed credentials that are not encrypted are very common and very easy to take advantage of.&nbsp;</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'
	>
	A famous example of this type of exploit happened to Uber in 2017 when the company reported that the personal information of 57 million users and 600,000 drivers was exposed because hackers discovered a hardcoded Amazon S3 Datastore key in a private GitHub repository used by Uber developers.&nbsp;</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">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-146'
	>
	Dangers</h3></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-20-text-roman js-typography block-typography__typography'
	data-id='es-149'
	>
	By gaining unauthorized access to a person’s credentials (i.e. mobile banking PINs, Token OTPs, email passwords, etc.), malicious actors can employ automated attacks or other methods that result in data breaches, privacy loss, and various fraudulent activities. Businesses face severe repercussions, such as reputation damage, fraud, information theft, and unauthorized access to data. </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'
	>
	<strong>Mitigation strategies</strong> </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'
	>
	Avoiding hardcoded credentials in the app source or any configuration file, encrypting data transmission, and handling storage securely, together with regular updates of API keys and tokens. There are plenty of static and dynamic code analysis tools for mobile platforms that can help you detect some of the issues. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-159"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-157">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-158'
	>
	It is also very important to employ strong authentication protocols to protect against unauthorized access and ensure data integrity. If you want to look into this further, <a href="https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md#authentication-general-guidelines">OWASP has a cheat sheet</a> on how to implement proper authentication, including different protocols.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-162"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-160">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-161'
	>
	M2: Inadequate supply chain security</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-165"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-163">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-164'
	>
	Another new entry on the list and also a very common issue is inadequate <a href="https://infinum.com/blog/software-supply-chain-security/">supply chain security</a>. According to OWASP, supply chain security refers to the entire ecosystem used for developing and distributing mobile apps. This includes third-party libraries, SDKs, vendors, and processes like coding, testing, and distributing. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-168"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-166">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-167'
	>
	Failing to implement security measures throughout the process and in some of the mentioned components, we can easily risk serious vulnerabilities in mobile applications, allowing attackers to insert malicious code or exploit third-party libraries. For example, this happened with the <a href="https://www.cybereason.com/blog/research/eventbot-a-new-mobile-banking-trojan-is-born" target="_blank" rel="noreferrer noopener">EventBot malware</a> discovered in 2020. The malware bypassed security measures by exploiting third-party libraries and SDKs within Android apps to steal user data and financial information.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-171"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-169">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-170'
	>
	Dangers</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-174"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-172">
	<p	class='typography typography--size-20-text-roman js-typography block-typography__typography'
	data-id='es-173'
	>
	These kinds of attacks can potentially lead to data breaches, malware infections, and in some cases, complete control of the device. Businesses may face financial losses, reputational damage, legal consequences, and interruptions in the delivery of goods or services. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-177"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-175">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-176'
	>
	<strong>Mitigation strategies</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-180"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-178">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-179'
	>
	To prevent such scenarios, it&#8217;s crucial to implement secure coding practices and conduct thorough testing and code reviews. Also, when picking third-party libraries and components, focus on the community around it, the proactiveness of the maintainers, and the quality of the support. Employing all of this will form a certain level of protection that is crucial in battling this risk. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-183"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-181">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-182'
	>
	<a href="https://infinum.com/blog/open-source-dependency-upgrade-process/" target="_blank" rel="noreferrer noopener">Keeping your dependencies up to date</a> is also a must, or even better, automating the update process with the available tools. Last but not least, establish robust and secure app signing processes that protect your app signing keys and certificates.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-186"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-184">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-185'
	>
	M3: Insecure authentication/authorization</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-189"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-187">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-188'
	>
	What used to be two separate entries on the list is now one merged entry that is higher on the security risk ranking. Insecure authentication and authorization expose mobile applications to unauthorized access and data breaches.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-192"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-190">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-191'
	>
	<strong>Dangers</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-195"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-193">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-194'
	>
	Attackers can exploit these vulnerabilities to perform actions posing as legitimate users or access sensitive data. This can seriously impact a business’s reputation, leading to information theft and financial losses. From a technical perspective, in worst-case scenarios, this can also lead to destroying an entire system. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-198"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-196">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-197'
	>
	This is one of the most consistent findings in AI-generated code. Our <a href="https://infinum.com/blog/security-gaps-in-vibe-coded-applications/">vibe-coded application security experiment</a> found role-assignment vulnerabilities in every app tested,  with no explicit security guidance.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-201"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-199">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-200'
	>
	<strong><strong>Mitigation strategies</strong></strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-204"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-202">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-203'
	>
	Prevention includes avoiding weak authentication patterns, avoiding offline authentication, and relying on server-side security. Integrating robust authentication mechanisms like multi-factor authentication to ensure data integrity and protect sensitive user information is also a must. In some cases, improper usage of features like biometric authentication can also make for insecure authentication.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-207"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-205">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-206'
	>
	M4: Insufficient Input/Output Validation</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-210"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-208">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-209'
	>
	Another new entry on the list, insufficient input/output validation occurs when an app fails to properly validate data from untrusted sources, leading to the execution of malicious input. This common risk in mobile apps can lead to severe security issues, such as data breaches, SQL and command injection attacks, and unauthorized data manipulation. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-213"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-211">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-212'
	>
	<strong>Dangers</strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-216"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-214">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-215'
	>
	Exploiting these risks can severely impact an organization&#8217;s reputation through data breaches and system failures, eating away at customer trust. It can also lead to legal issues and financial penalties for not adhering to data protection laws.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-219"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-217">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-218'
	>
	<strong><strong>Mitigation strategies</strong></strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-222"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-220">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-221'
	>
	The necessary thing to do is implement the required validation on both the client and the server side, employing whitelisting approaches and sanitizing data to prevent the execution of harmful input. Also, it’s important to conduct regular security assessments like <a href="https://infinum.com/blog/code-audit/">code reviews</a> and <a href="https://infinum.com/blog/why-penetration-testing-is-important/">penetration tests</a>.</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-typography" data-id="es-223">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-224'
	>
	M5: Insecure Communication</h2></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'
	>
	This is one of the rare entries ranked lower than in the last year’s release. This is a good sign because it means that the risk is being addressed to some capacity. Nonetheless, insecure communication remains a serious issue. It poses a risk by allowing attackers to intercept or alter data transmitted by mobile applications.</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">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-230'
	>
	Dangers</h3></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'
	>
	Exploiting insecure communication and leaking sensitive data can result in a privacy violation, which compromises the user’s confidentiality and has legal repercussions for businesses.</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">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-236'
	>
	<strong><strong>Mitigation strategies</strong></strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-240"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-238">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-239'
	>
	Implementing end-to-end encryption, using secure protocols like TLS, and regularly updating security certificates are effective strategies. The OWASP web page provides a short list of very concrete <a href="https://owasp.org/www-project-mobile-top-10/2023-risks/m5-insecure-communication.html" target="_blank" rel="noreferrer noopener">best practices</a> for iOS and Android that you can follow to make your app more secure. </p></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'
	>
	If you are interested in a more technical approach, you can check out our article on <a href="https://infinum.com/blog/how-to-prepare-your-android-app-for-a-pentest/" target="_blank" rel="noreferrer noopener">preparing your Android app networking for a penetration test</a> or the one about <a href="https://infinum.com/blog/ssl-pinning-revisited/" target="_blank" rel="noreferrer noopener">SSL pinning on iOS</a>.</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">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-245'
	>
	M6: Inadequate Privacy Controls</h2></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'
	>
	Inadequate privacy controls are another new addition to OWASP’s list of mobile risks to keep an eye on. Privacy controls protect Personally Identifiable Information (PII) such as names, addresses, financial data, and sensitive personal details from unauthorized access.</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">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-251'
	>
	Dangers</h3></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'
	>
	Attackers target this information to commit fraud, steal funds, blackmail, or damage critical data. All of this can have a negative impact on user trust and potentially result in regulatory fines, which depend on the number of affected users. The technical impact of this risk is low but not ignorable. </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">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-257'
	>
	<strong><strong>Mitigation strategies</strong></strong></h3></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">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-260'
	>
	Businesses can mitigate this risk by implementing robust data access controls, conducting regular privacy assessments, and ensuring compliance with privacy laws and regulations.</p></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">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-263'
	>
	M7: Insufficient Binary Protection</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-267"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-265">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-266'
	>
	Previous entries known as M8: Code Tampering and M9: Reverse Engineering are now one combined entry. We can see that the risk itself moved up in the ranking, which makes it even more important to be aware of.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-270"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-268">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-269'
	>
	Insufficient binary protection makes mobile applications vulnerable to reverse engineering and tampering. While somewhat similar, there are important differences between the two. Reverse engineering involves analyzing a system to understand its operation without accessing its documentation or designs. Tampering, on the other hand, refers to unauthorized alterations or manipulations of a system or software to change its behavior or outcomes. Both can lead to intellectual property theft and compromise app integrity.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-273"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-271">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-272'
	>
	Dangers</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-276"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-274">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-275'
	>
	What makes these kinds of exploits dangerous is the fact that attackers may alter app binaries to unlock paid features or simply evade security layers in specific parts of the application. Businesses face significant risk if intellectual property, such as algorithms or AI models, is leaked or stolen by competitors. It is also important to note that all apps are vulnerable to binary attacks.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-279"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-277">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-278'
	>
	<strong><strong>Mitigation strategies</strong></strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-282"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-280">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-281'
	>
	Protection involves using code obfuscation techniques, implementing tamper-detection mechanisms and root detection, and securing application code against unauthorized modifications. Some useful libraries and tools that can help with this are <a href="https://developer.android.com/google/play/integrity/overview" target="_blank" rel="noreferrer noopener">Google Play Integrity API</a> for Android and the <a href="https://mas.owasp.org/MASTG/0x06a-Platform-Overview/" target="_blank" rel="noreferrer noopener">detailed OWASP documentation for iOS</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-285"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-283">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-284'
	>
	M8: Security Misconfiguration</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-288"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-286">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-287'
	>
	Previously known as M10: Extraneous Functionality, this entry has jumped from number ten to number eight in the risks list. While perhaps it is not so easy to exploit, it is a risk we should nonetheless be aware of, especially considering the move in its ranking.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-291"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-289">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-290'
	>
	To illustrate, in 2022 Microsoft discovered a high-severity vulnerability in the TikTok Android application, which could have allowed attackers to compromise user accounts with a single click. Luckily, TikTok responded promptly to Microsoft&#8217;s notification by releasing a fix. This example shows how improper security configuration (M8) (in this case, of Android’s WebView) and DeepLink validation (M4) can cause significant harm in the authentication/authorization flow (M3).</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-typography" data-id="es-292">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-293'
	>
	Dangers</h3></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'
	>
	Security misconfiguration can expose mobile apps to various attacks, leading to unauthorized access and data breaches. This can also cause some application downtime and disrupt a business, which can have a negative effect on the finances and cause brand damage.</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">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-299'
	>
	<strong><strong>Mitigation strategies</strong></strong></h3></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'
	>
	Regular security audits, adherence to secure coding practices, and ensuring proper configuration of security settings can help mitigate these risks. A common pitfall is failing to review default configurations of tools and frameworks.</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">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-305'
	>
	M9: Insecure Data Storage</h2></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'
	>
	This entry demonstrates some general improvement in app development, as it dropped from number two to number nine. However, insecure data storage practices can still bring forth significant security risks. For example, this happened to UnderArmour’s MyFitnessPal app in 2018. The breach involved unauthorized access due to insecure data storage and affected 150 million users, exposing their usernames, email addresses, and hashed passwords.&nbsp;</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">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-311'
	>
	Dangers</h3></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'
	>
	Unauthorized access to the device&#8217;s file system and interception of data transmission can compromise user privacy and data integrity.&nbsp;</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">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-317'
	>
	<strong><strong>Mitigation strategies</strong></strong></h3></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'
	>
	Encrypting stored data, ensuring secure data handling practices, and conducting thorough security testing are key ways of handling these risks. These tactics will also give a boost to your business because organizations that have experienced data breaches or have become known for practicing insecure data storage have a competitive disadvantage in today&#8217;s market. Customers will always prioritize and favor competitors with stronger data security records. This is another instance where <a href="https://infinum.com/blog/why-penetration-testing-is-important/" target="_blank" rel="noreferrer noopener">penetration tests</a> can be a valuable asset. </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-52-default js-typography block-typography__typography'
	data-id='es-323'
	>
	M10: Insufficient Cryptography</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'
	>
	The last entry on the list and another one that fell in the rankings. Insufficient cryptography in mobile applications involves exploitations by various threat agents who take advantage of the fact that many mobile application developers don&#8217;t have the proper know-how on how to implement and use cryptography and hash functions the way they are intended. Or, even worse, try to implement it from scratch.</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">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-329'
	>
	Dangers</h3></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'
	>
	These agents target weak encryption, lack of HTTPS, key management flaws, and cryptographic vulnerabilities to decrypt data, manipulate cryptographic processes, or gain unauthorized access.&nbsp;</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">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-335'
	>
	<strong><strong>Mitigation strategies</strong></strong></h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-339"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-337">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-338'
	>
	To address these risks, it&#8217;s essential to use strong encryption algorithms and implement secure cryptographic practices. Regular updates and security audits can also help mitigate vulnerabilities and strengthen the overall security layer around your business. On the OWASP web page, you can find <a href="https://mas.owasp.org/MASVS/06-MASVS-CRYPTO/" target="_blank" rel="noreferrer noopener">best practices</a> about industry-standard processes of handling keys, hash functions, validation and authentication, and more. </p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-342"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-340">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-341'
	>
	A security mindset changes everything</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-345"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-343">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-344'
	>
	The OWASP Top 10 mobile risk ranking is just one of many open-source tools that businesses can use to improve their digital security. However, no tool or framework can be a cure-all without embracing a proper security mindset.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-348"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-346">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-347'
	>
	When we foster a culture of security, it impacts every aspect of a business. We build this culture by recognizing that security is a continuous journey that requires ongoing vigilance, adaptation, and commitment to best practices. The OWASP list and other tools and best practices serve as a vital compass here, guiding us through the complexities of the digital world toward a future where security and business objectives are tightly linked.&nbsp;</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-351"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-349">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-350'
	>
	Each of these vulnerabilities presents unique challenges but also opportunities for businesses to enhance their security measures, protect sensitive data, and reinforce their commitment to being a trusted service provider for their user base.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-354"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-352">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-353'
	>
	<em>If you need help boosting your security posture, check out 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/owasp-top-10-mobile/">Secure Your App – OWASP Top 10 Mobile Risks Explained</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>8145https://infinum.com/uploads/2021/08/pentesting-misc-cases-0.webp</url>
				</image>
				<title>How to Prepare Your Android App for a Pentest: The Bits and Pieces</title>
				<link>https://infinum.com/blog/pentesting-misc-cases/</link>
				<pubDate>Wed, 22 Sep 2021 15:40:00 +0000</pubDate>
				<dc:creator>Renato Turić</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/pentesting-misc-cases/</guid>
				<description>
					<![CDATA[<p>Various cases to consider when preparing your Android app for a pentest.</p>
<p>The post <a href="https://infinum.com/blog/pentesting-misc-cases/">How to Prepare Your Android App for a Pentest: The Bits and Pieces</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-610"
	 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-357">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-360"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-358">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-359'
	>
	Android app pentesting is an invaluable tactic for identifying the weaknesses and possible penetration points in your apps. In the age of constantly evolving sophisticated cyber-attacks and data breaches <a href="https://infinum.com/cybersecurity/penetration-testing/">penetration testing</a> is mandatory.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-363"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-361">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-362'
	>
	We’ve spoken about networking and data storage issues in our previous blog posts, so this final installment in the series can wrap up the story by covering the “miscellaneous” category, the remaining common cases in a pentest.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-366"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-364">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-365'
	>
	You’ll find the previous posts here:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-369"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-367">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-368'
	>
	<li><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></li><li><a href="https://infinum.com/blog/securing-data-storage-in-preparation-for-pentesting/">Securing Data Storage in Preparation for Pentesting</a></li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-372"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-370">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-371'
	>
	Let’s jump right into the cases in no specific order.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-375"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-373">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-374'
	>
	Root detection</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-378"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-376">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-377'
	>
	The Android operating system on our phones is a commercial version of the OS provided by the manufacturer. This means that the end-user doesn’t have full control over their device due to system-level restrictions and safeguards.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-381"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-379">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-380'
	>
	To bypass these, it’s possible to perform rooting, which grants the user root access. With a rooted device, the access control imposed by the operating system is compromised and we can’t guarantee the application sandbox features will securely protect our app’s private data.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-384"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-382">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-383'
	>
	In the worst-case scenario, the data can become exposed to malicious software that manages to elevate its privileges to root access.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-387"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-385">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-386'
	>
	Preparation phase – What you’ll need to know</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-390"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-388">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-389'
	>
	To protect apps on rooted devices, we first need to detect whether a device is rooted. We do this by performing root detection.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-393"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-391">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-392'
	>
	It is important to know that no solution will give you a 100% accurate result. If the result indicates that the device is in fact rooted, we should follow the best practice recommended by OWASP in their Mobile Security Testing Guide book (<a href="https://github.com/OWASP/owasp-mstg">page 84</a>). We should notify the user that the app runs on a rooted device and that certain high-risk actions will carry additional risk due to its status, or just completely block our app’s usage.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-396"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-394">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-395'
	>
	For detecting rooted devices we recommend using an existing implementation rather than doing it from scratch. Google provides <a href="https://developer.android.com/training/safetynet">SafetyNet</a> which has a set of API-s that help protect your app against security threats altogether.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-399"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-397">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-398'
	>
	SafetyNet has no specific API that can tell us if a device is rooted, it’s not a part of its design. However, we can use it to check the flags that we receive from the SafetyNet backend. The flags that we are looking for are <code>ctsProfileMatch</code> and <code>basicIntegrity</code>. If these two flags turn out false, it implies that the system integrity has been compromised, and rooting is a potential cause.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-402"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-400">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-401'
	>
	There is no need to get into implementation details because the official documentation site offers good descriptions. You can also find some code examples in <a href="https://github.com/googlesamples/android-play-safetynet">this repo</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-405"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-403">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-404'
	>
	However, you might have noticed that SafetyNet has a limit of 10,000 requests per day across your user base. This is a problem for most apps that are actually interested in that kind of a service but fortunately, there are ways to handle this limitation. The official way to handle it is described in the <a href="https://developer.android.com/training/safetynet/attestation#quota-monitoring">official documentation</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-408"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-406">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-407'
	>
	If this option doesn’t work for you, you can implement a workaround that could cover most of your cases. It includes using the <code>RECEIVE_BOOT_COMPLETED</code> permission and running the SafetyNet request only when your application receives the mentioned system reboot event. This will keep your API quota limit under control, but it’s not a future-proof solution. The official way is always the preferred one.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-411"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-409">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-410'
	>
	A good alternative to SafetyNet is <a href="https://github.com/scottyab/rootbeer">RootBeer</a> written by Scott Alexander-Bown who also wrote the Android Security Cookbook. You can also use it in combination with safetyNet to control your API quota limit.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-418"
	 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-412"
	 target='_blank' rel='noopener noreferrer' href='https://infinum.com/cybersecurity/penetration-testing/'>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h2	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-413'
	>
	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.</h2>		</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-415"
	 tabindex='-1'>
		<div class="btn__inner">
					<div	class='typography typography--size-none js-typography btn__label'
	data-id='es-416'
	>
	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-417'>
	<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-421"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-419">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-420'
	>
	Logs</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-424"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-422">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-423'
	>
	Logging is very common in every application. We usually use it to pinpoint an undesired behavior, but we can also use it to track fatal and non-fatal crashes on our crashlytics tools.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-427"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-425">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-426'
	>
	Logs can be valuable during the development process. In most cases, we treat them as harmless pieces of characters. Unfortunately, that approach can sometimes put us in an undesirable situation where we can leak sensitive data through our logs.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-430"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-428">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-429'
	>
	As Android developers, we use <a href="https://developer.android.com/studio/command-line/logcat">Logcat</a> for inspecting our application’s logs. We only need a couple of command lines and we get a live dump of all the logs, not just from an individual app, but the entire system. A potential attacker could easily do the same and if they found some useful info, they could use it to exploit our application or the entire system.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-433"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-431">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-432'
	>
	Preparation phase – What you’ll need to know</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-436"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-434">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-435'
	>
	To prevent data leakage through logs, it’s best to remove logs from production builds. Luckily, there are some handy tools to handle this task for us.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-439"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-437">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-438'
	>
	For example, we can use <a href="https://github.com/JakeWharton/timber">Timber</a> for logging information and use the <code>Tree</code> feature to separate logging implementations for different application variants. We can use the default <code>DebugTree</code> from Timber to log information through Logcat in debug builds. For release builds we can create our own implementation that we will use to send information to our analytics or crashlytics tools. To implement your own tree, you can extend the <code>Timber.Tree</code> class and add your logic inside the log method:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-441"
	 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 ReleaseTree</span><span class="token">() </span><span class="token">: </span><span class="token" style="color: #6f42c1;">Timber</span><span class="token">.Tree</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 log</span><span class="token">(priority</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Int</span><span class="token">, tag</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">?</span><span class="token">, message</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">, t</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Throwable</span><span class="token">?</span><span class="token">) {
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> handle received logs</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-444"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-442">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-443'
	>
	After you have your custom tree implementation you can set it inside the application class depending on the desired buildconfig, something like this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-446"
	 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">Timber</span><span class="token">.plant</span><span class="token">(</span><span class="token" style="color: #d73a49;">if</span><span class="token"> (BuildConfig.DEBUG) Timber.DebugTree </span><span class="token" style="color: #d73a49;">else</span><span class="token"> </span><span class="token">ReleaseTree</span><span class="token">())
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-449"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-447">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-448'
	>
	In case you don’t use Timber you might stumble upon a ProGuard option to remove all log messages using this proguard rule:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-451"
	 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><span class="line"><span class="token" style="color: #d73a49;">-</span><span class="token">assumenosideeffects </span><span class="token">class android</span><span class="token">.util</span><span class="token">.Log </span><span class="token">{
</span></span><span class="line"><span class="token" style="color: #d73a49;">public</span><span class="token"> static boolean </span><span class="token">isLoggable</span><span class="token">(java.lang.String, int);
</span></span><span class="line"><span class="token" style="color: #d73a49;">public</span><span class="token"> static int </span><span class="token">v</span><span class="token">(</span><span class="token" style="color: #d73a49;">..</span><span class="token">.);
</span></span><span class="line"><span class="token" style="color: #d73a49;">public</span><span class="token"> static int </span><span class="token">i</span><span class="token">(</span><span class="token" style="color: #d73a49;">..</span><span class="token">.);
</span></span><span class="line"><span class="token" style="color: #d73a49;">public</span><span class="token"> static int </span><span class="token">w</span><span class="token">(</span><span class="token" style="color: #d73a49;">..</span><span class="token">.);
</span></span><span class="line"><span class="token" style="color: #d73a49;">public</span><span class="token"> static int </span><span class="token">d</span><span class="token">(</span><span class="token" style="color: #d73a49;">..</span><span class="token">.);
</span></span><span class="line"><span class="token" style="color: #d73a49;">public</span><span class="token"> static int </span><span class="token">e</span><span class="token">(</span><span class="token" style="color: #d73a49;">..</span><span class="token">.);
</span></span><span class="line"><span class="token" style="color: #d73a49;">public</span><span class="token"> static int </span><span class="token">wtf</span><span class="token">(</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-454"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-452">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-453'
	>
	Keep in mind that the rule above will not help you with dynamically constructed strings used to log the data using the Log methods later on. This is due to the fact that dynamically constructed strings (i.e using StringBuilder) can still be seen in the bytecode. For more details about this particular issue, you can check the <a href="https://mobile-security.gitbook.io/mobile-security-testing-guide/android-testing-guide/0x05d-testing-data-storage#static-analysis-2">MSTG source</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-457"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-455">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-456'
	>
	Also, be careful about the above proguard rule because you can find a lot of similar rules on the Internet that can break your application. Check this article <a href="https://medium.com/yazio-engineering/how-to-break-your-android-app-with-proguard-r8-6566bc387b63">for more information</a>. Always double-check your source when it comes to security!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-460"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-458">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-459'
	>
	Tapjack</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-463"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-461">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-462'
	>
	Tapjacking is an old security issue that was well known on devices running Android versions 4.0.3. However, it can still be dangerous today if a user is unaware of it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-466"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-464">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-465'
	>
	The exploit is based on the Android permission <code>SYSTEM_ALERT_WINDOW</code> which allows an app to draw an overlay over other apps. Attackers can use this option to create an overlay that would essentially hijack user taps and use it to obtain sensitive user information, hence the name tapjack.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-469"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-467">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-468'
	>
	The Android runtime permission introduced in Android API level 23 is a good measure of protection against tapjacking attacks because the users have to manually grant the permission to draw over other apps. Before API level 23 any developer could just add the permission in the manifest file and they would be able to use the feature immediately when the app is installed.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-472"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-470">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-471'
	>
	On some devices that run Android API level 23, there is a system-level security issue with the <code>SYSTEM_ALERT_WINDOW</code>. An app could use the exploit to draw an overlay over the system permission dialog. That would make it possible for the attacker to change the text of the permission dialog to make the user think the permission they are about to grant is not dangerous, while in reality, it could be the opposite.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-475"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-473">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-474'
	>
	In the worst-case scenario, this would allow the attacker to obtain user information from the device. Here you can find <a href="https://www.xda-developers.com/how-tapjacking-made-a-return-with-android-marshmallow-and-nobody-noticed/">more information about that specific case</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-478"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-476">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-477'
	>
	Another very popular attack class involving the <code>SYSTEM_ALERT_WINDOW</code> permission is the <a href="https://cloak-and-dagger.org/">cloak-and-dagger</a> which also enables some advanced tapjacking attacks.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-481"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-479">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-480'
	>
	Preparation phase – What you’ll need to know</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-484"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-482">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-483'
	>
	Let’s imagine a situation where your app has a login screen and the user has to enter their login credentials. Let’s say that the user also has an app on their device that they trust, but is unaware that the app has malicious intent. That kind of an app can use the <code>SYSTEM_ALERT_WINDOW</code> to draw a transparent overlay over any other app and is specifically designed to track keyboard inputs.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-487"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-485">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-486'
	>
	With some additional effort, the attacker could obtain our user’s login credentials for our app. To take it another step further, the attacker could literally obtain anything that the user enters on the keyboard.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-490"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-488">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-489'
	>
	To protect your app from these kinds of attacks, Android offers a built-in solution to detect overlays over specific UI elements that we think are exploitable. You can do this by using the following XML tag:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-492"
	 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">android</span><span class="token">:</span><span class="token" style="color: #6f42c1;">filterTouchesWhenObscured</span><span class="token" style="color: #d73a49;">=</span><span class="token">”[</span><span class="token" style="color: #005cc5;">true</span><span class="token">|</span><span class="token" style="color: #005cc5;">false</span><span class="token">]” 
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-495"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-493">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-494'
	>
	Keep in mind that by setting this flag to true, the view will not receive touches whenever a toast, dialog, or other window appears above the view’s window. This will get the job done, but it is not recommended to leave it that way because the users will have a terrible time using your app. Imagine you want to press a button and nothing happens, that’s just bad user experience.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-498"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-496">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-497'
	>
	Luckily, we have a way of detecting when exactly this happens. We can override the <code>onFilterTouchEventForSecurity</code> method in a compound view used to place it above other views. That way it can intercept obscured touch events and react to them.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-500"
	 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;">override</span><span class="token"> </span><span class="token">fun onFilterTouchEventForSecurity</span><span class="token">(event</span><span class="token">: </span><span class="token" style="color: #6f42c1;">MotionEvent</span><span class="token">)</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Boolean</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"> (event.flags and MotionEvent.FLAG_WINDOW_IS_OBSCURED </span><span class="token" style="color: #d73a49;">==</span><span class="token"> MotionEvent.FLAG_WINDOW_IS_OBSCURED) {
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> React to obscured events</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;">false</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;">return</span><span class="token"> </span><span class="token" style="color: #005cc5;">super</span><span class="token">.onFilterTouchEventForSecurity</span><span class="token">(event)
</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-503"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-501">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-502'
	>
	Fortunately, tapjacking, even though potentially very dangerous, is easy to handle. You should make sure your users are aware of the problem because the lack of awareness itself might be the biggest problem with this exploit.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-506"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-504">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-505'
	>
	There are signs that Google might deprecate the permission entirely. Android Go versions are already not allowed to use that feature. Also, features like Facebook Chat bubbles, which rely on the <code>SYSTEM_ALERT_WINDOW</code> permission , are receiving <a href="https://developer.android.com/guide/topics/ui/bubbles">alternate API solutions</a> to cover their use cases. It could be taken as an indication that the long-term plan is permission removal. We will have to wait and see.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-509"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-507">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-508'
	>
	Clipboard manager</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-512"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-510">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-511'
	>
	Clipboard is one of Android’s system components. It is exposed to developers through a class called <a href="https://developer.android.com/reference/android/content/ClipboardManager">ClipboardManager</a> which grants copying, monitoring, and paste operations for specified data.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-515"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-513">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-514'
	>
	One of the clipboard component’s main characteristics is globally accessible to any app running on the device and no additional permission is needed. This leaves users vulnerable in case there is a malicious app on their device that could sniff out its clipboard and obtain passwords, credit card details, and other sensitive user information. This article shows <a href="https://arstechnica.com/information-technology/2014/11/using-a-password-manager-on-android-it-may-be-wide-open-to-sniffing-attacks/">how Android’s clipboard could be exploited</a> in a password manager app.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-518"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-516">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-517'
	>
	Preparation phase – What you’ll need to know</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-521"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-519">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-520'
	>
	Sadly, there is no good way to mitigate attacks on data contained in the clipboard from within our app, so it should be handled on a system level. There are some mitigation tactics but they strongly depend on the use case you want to achieve. One of the most common and safest approaches is to disable the copying of sensitive data altogether. This better-safe-than-sorry scenario can leave your users with a bad UX, but it protects those less technically savvy.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-524"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-522">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-523'
	>
	Screenshots</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-527"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-525">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-526'
	>
	When you think about it, taking screenshots is very similar to copying plain text. The vulnerability area is very similar to the one from the previous chapter. The only difference, except the data type, is the location of the saved data. Screenshots are usually saved in the device’s internal storage in a folder named Screenshots, but this may slightly vary depending on the manufacturer.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-530"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-528">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-529'
	>
	Preparation phase – What you’ll need to know</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-533"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-531">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-532'
	>
	The mitigation process is also very similar to the one for Clipboard manager. Luckily, we can use the Android built-in API to determine which screens can be screenshotted and which are prohibited. We do this by using the window flag <a href="https://developer.android.com/reference/android/view/WindowManager.LayoutParams#FLAG_SECURE">FLAG_SECURED</a>. The snippet below shows how to set the flag in a fragment.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-535"
	 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">requireActivity</span><span class="token">().window</span><span class="token">.setFlags</span><span class="token">(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-538"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-536">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-537'
	>
	This will also protect your app from screen-recording apps.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-541"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-539">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-540'
	>
	Inter-process communication (IPC)</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-544"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-542">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-543'
	>
	When we install our apps on the Android OS they run in their own secure sandbox. However, like any other system, Android also gives us IPC capabilities to communicate with the rest of the system or with other apps.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-547"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-545">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-546'
	>
	We can use more traditional ways like using shared files to communicate, but this is not recommended since we have more evolved solutions provided by the Android OS. One of those solutions is <a href="https://developer.android.com/guide/components/services.html">Services</a>. They are components used for long-running operations in the background, but they can also be used for IPC with bound services where other components can bind to a service and interact with it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-550"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-548">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-549'
	>
	Further, there is <a href="https://developer.android.com/reference/android/content/ContentProvider.html">ContentProviders</a> or a more advanced mechanism like <a href="https://developer.android.com/guide/components/aidl.html">AIDL</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-553"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-551">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-552'
	>
	Probably the most common way we use for communication between different Android components is <a href="https://developer.android.com/reference/android/content/Intent">Intents</a>. An Intent is an abstract description of an operation that we can use to communicate with Activities, BroadcastReceivers, and Services. This is a broad subject so we will try to focus on the main techniques for protecting your application components from unwanted interactions.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-556"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-554">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-555'
	>
	Preparation phase – What you’ll need to know</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-559"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-557">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-558'
	>
	There are several tools at your disposal for making your app safe for IPC. If your app does not handle IPC, make sure that your main components don’t have the exported flag set to true in the manifest. It is false by default, but sometimes we set it to true in case we want to start a specific activity from Android Studio for faster development. Just ensure you don’t forget to check that flag before release or create a custom lint rule if you already don’t have it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-562"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-560">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-561'
	>
	Suppose your components need to be exported for IPC. In that case, you should make it restrictive because sniffing broadcasted Intents is as simple as writing a terminal command using tools like <a href="https://github.com/FSecureLABS/drozer">Drozer</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-565"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-563">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-564'
	>
	What you want to do is set the corresponding <a href="https://developer.android.com/guide/topics/manifest/permission-element">permissions</a> for your components so that you indicate to targets that want to communicate with your application that they need to follow the rules you set. Together with that tag and the protection level you can control the restriction level for your components.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-568"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-566">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-567'
	>
	For example, suppose your company has multiple applications in production and you want to make sure that only your applications can communicate with each other in order to avoid impersonated intents from potential attackers. In that case, we can define a custom permission inside our manifest like this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-570"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-xml github-light" data-language="xml" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">&lt;</span><span class="token" style="color: #22863a;">manifest</span><span class="token">  </span><span class="token" style="color: #6f42c1;">package</span><span class="token">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">com.example.myapp</span><span class="token" style="color: #032f62;">&quot;</span><span class="token"> </span><span class="token">&gt;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">&lt;</span><span class="token" style="color: #22863a;">permission</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #6f42c1;">android</span><span class="token" style="color: #6f42c1;">:</span><span class="token" style="color: #6f42c1;">name</span><span class="token">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">com.example.myapp.permission.READ_USER_DATA</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #6f42c1;">android</span><span class="token" style="color: #6f42c1;">:</span><span class="token" style="color: #6f42c1;">label</span><span class="token">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Read user data</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #6f42c1;">android</span><span class="token" style="color: #6f42c1;">:</span><span class="token" style="color: #6f42c1;">description</span><span class="token">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Can access user data like email, username, password, ...</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #6f42c1;">android</span><span class="token" style="color: #6f42c1;">:</span><span class="token" style="color: #6f42c1;">protectionLevel</span><span class="token">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">signature</span><span class="token" style="color: #032f62;">&quot;</span><span class="token"> </span><span class="token">/&gt;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">&lt;/</span><span class="token" style="color: #22863a;">manifest</span><span class="token">&gt;</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-573"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-571">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-572'
	>
	You’ll notice that protectionLevel is set to signature mode, which gives us the desired effect described above. In other words, this is automatically granted to a requesting app if that application is signed by the same certificate. For more information about other protection levels, check the <a href="https://developer.android.com/reference/android/R.attr#protectionLevel">protectionLevel</a> documentation. With our custom permission defined, we can use it in our components. For example, if we want to protect our service with this permission, we would write the following code in our manifest:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-575"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-xml github-light" data-language="xml" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">&lt;</span><span class="token" style="color: #22863a;">service</span><span class="token"> 
</span></span><span class="line"><span class="token" style="color: #6f42c1;">android</span><span class="token" style="color: #6f42c1;">:</span><span class="token" style="color: #6f42c1;">name</span><span class="token">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">.data.session.SessionService</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #6f42c1;">android</span><span class="token" style="color: #6f42c1;">:</span><span class="token" style="color: #6f42c1;">permission</span><span class="token">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">com.example.myapp.permission.READ_USER_DATA</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">/&gt;</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-578"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-576">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-577'
	>
	We can add this to the application tag in our manifest to protect our entire application with this permission.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-581"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-579">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-580'
	>
	Alongside the exported flag and custom permissions we also have <a href="https://developer.android.com/guide/topics/manifest/intent-filter-element">intent filters</a> in our arsenal to protect our applications from malicious and undesired IPC.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-584"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-582">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-583'
	>
	Intent filters can be used to specify the types of intents that an activity, service, or broadcast receiver can respond to. That way we can anticipate the input in our components. Whatever you decide to use, it is always good practice to check the data you receive programmatically to see if it is something that you expect.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-587"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-585">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-586'
	>
	Conclusion</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-590"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-588">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-589'
	>
	Pentesting is an ever-evolving subject, so this is by no means an exhaustive guide. Some important topics were left out due to their complexity, such as WebView vulnerabilities, reverse engineering, and dependency control.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-593"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-591">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-592'
	>
	Protecting your applications from attacks is challenging and sometimes even impossible because more sophisticated attacks are constantly evolving and these won’t be easily withstood using standard tweaks and tricks. Protection against them requires tedious manual analysis, coding, and probably lots of frustration.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-596"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-594">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-595'
	>
	One thing is certain though, to prepare your applications in the best possible way it is important to stay in the loop. Keep in touch with the community and experiment with attacks on your own. If you know how malicious code works, it is easier to get the know-how to mitigate it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-599"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-597">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-598'
	>
	Testing tools</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-602"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-600">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-601'
	>
	As a final note, here is a list of useful tools that can help you analyze your applications and hopefully make them a bit more secure:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-605"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-603">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-604'
	>
	<li><a href="https://github.com/MobSF/Mobile-Security-Framework-MobSF">MobSF</a></li><li><a href="https://frida.re/">Frida</a></li><li><a href="https://docs.angr.io/">Angr</a></li><li><a href="https://mobile-security.gitbook.io/mobile-security-testing-guide/appendix/0x08-testing-tools">many more</a></li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-608"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-606">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-607'
	>
	<em><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></em></p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/pentesting-misc-cases/">How to Prepare Your Android App for a Pentest: The Bits and Pieces</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>7965https://infinum.com/uploads/2020/03/securing-data-storage-in-preparation-for-pentesting-0.webp</url>
				</image>
				<title>Securing Data Storage in Preparation for Pentesting</title>
				<link>https://infinum.com/blog/securing-data-storage-in-preparation-for-pentesting/</link>
				<pubDate>Fri, 13 Mar 2020 11:15:00 +0000</pubDate>
				<dc:creator>Renato Turić</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/securing-data-storage-in-preparation-for-pentesting/</guid>
				<description>
					<![CDATA[<p>Insecure data storage is among top security risks in mobile apps, second only to improper platform usage. How to secure data efficiently?</p>
<p>The post <a href="https://infinum.com/blog/securing-data-storage-in-preparation-for-pentesting/">Securing Data Storage in Preparation for Pentesting</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-899"
	 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-611">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-614"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-612">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-613'
	>
	Securing the data stored within an app is just as important as it is often ignored.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-617"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-615">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-616'
	>
	Because data is commonly not dealt with properly, it ends up being exploited and exposed to unintended leakage a lot more than it should.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-620"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-618">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-619'
	>
	Data storage security among top concerns</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-623"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-621">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-622'
	>
	According to <a href="https://www.owasp.org/index.php/Mobile_Top_10_2016-Top_10">this 2016 research</a> by The Open Web Application Security Project, insecure data storage is among top security concerns in mobile apps, second only to improper platform usage.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-626"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-624">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-625'
	>
	Luckily, Android provides us with various ways to keep data safe.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-629"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-627">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-628'
	>
	The first post from our <a href="https://infinum.com/blog/how-to-prepare-your-android-app-for-a-pentest/">Pentesting Series</a> covered some key concepts of a TLS connection and showed how to achieve a secure network layer in an app which would pass a pentest.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-632"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-630">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-631'
	>
	This edition will focus on <strong>securing user data in the app storage</strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-639"
	 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-633"
	 target='_blank' rel='noopener noreferrer' href='https://infinum.com/cybersecurity/penetration-testing/'>

	
	
	<div class="card-simple__content">
		<div class="card-simple__heading-wrap">
			<h2	class='typography typography--size-24-text js-typography card-simple__heading'
	data-id='es-634'
	>
	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.</h2>		</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-636"
	 tabindex='-1'>
		<div class="btn__inner">
					<div	class='typography typography--size-none js-typography btn__label'
	data-id='es-637'
	>
	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-638'>
	<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-642"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-640">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-641'
	>
	Shared preferences – a security risk</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-645"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-643">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-644'
	>
	Shared preferences are probably the most used Android API for storing small amounts of data. It is based on a <em>key-value</em> pair model, and there’s a very simple process evolving in the background.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-648"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-646">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-647'
	>
	It saves the key-value pairs into an .xml file, which is located in the app data directory in a directory called <code>shared_prefs</code>. Since the data is saved in a plain .xml file, the sensitive data we save in there is a security risk – especially if our <code>AndroidManifest.xml</code> configuration states that app backups are allowed:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-650"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-xml github-light" data-language="xml" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">&lt;</span><span class="token" style="color: #22863a;">application</span><span class="token"> </span><span class="token" style="color: #6f42c1;">android</span><span class="token" style="color: #6f42c1;">:</span><span class="token" style="color: #6f42c1;">allowBackup</span><span class="token">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">true</span><span class="token" style="color: #032f62;">&quot;</span><span class="token"> </span><span class="token">/&gt;</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-653"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-651">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-652'
	>
	The <code>allowBackup</code> attribute is set to <em>true</em> by default when a new project is created, as confirmed in Android Studio 3.5.2. Taking that into account, let’s see how easy it is to <strong>extract shared preferences data from an app</strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-656"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-654">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-655'
	>
	To exploit the <code>allowBackup</code> flag we need <code>adb</code> connection to the device that is running our app. Afterwards, it is enough to run the following command:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-659"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-657">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-658'
	>
	<code>$ adb backup com.example.app</code></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-662"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-660">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-661'
	>
	This command will result in the entire application backup file, <code>backup.ab</code>. This file contains all the information needed to restore the application in case we want to migrate our system settings and app settings to another device.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-665"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-663">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-664'
	>
	To see the contents of the <code>.ab</code> file, use any file-unpacking tool. This example uses <a href="https://github.com/nelenkov/android-backup-extractor">Android Backup Extractor</a>. This tool allows us to create a .tar file with the following command:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-668"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-666">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-667'
	>
	<code>$ abe unpack backup.ab backup.tar</code></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-671"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-669">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-670'
	>
	After acquiring the <code>.tar</code> file and unpacking it, all the contents from the original <code>backup.ab</code> file become available. One of those files is the shared preferences .xml file. By opening the file, we can see all the key-value pairs used in the app.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-674"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-672">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-673'
	>
	For example, let’s say the extracted .xml file looked like this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-676"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-xml github-light" data-language="xml" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">&lt;?</span><span class="token" style="color: #22863a;">xml</span><span class="token" style="color: #6f42c1;"> version</span><span class="token">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">1.0</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #6f42c1;"> encoding</span><span class="token">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">utf-8</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">?</span><span class="token" style="color: #6f42c1;"> standalone</span><span class="token">=”yes” </span><span class="token">?&gt;</span><span class="token">
</span></span><span class="line"><span class="token">&lt;</span><span class="token" style="color: #22863a;">map</span><span class="token">&gt;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">&lt;</span><span class="token" style="color: #22863a;">string</span><span class="token"> </span><span class="token" style="color: #6f42c1;">name</span><span class="token">=</span><span class="token">”AUTH_TOKEN”</span><span class="token">&gt;</span><span class="token">89239d28328dj2398do1320942</span><span class="token" style="color: #22863a;">&lt;/stri</span><span class="token">ng</span><span class="token">&gt;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">&lt;</span><span class="token" style="color: #22863a;">string</span><span class="token"> </span><span class="token" style="color: #6f42c1;">name</span><span class="token">=</span><span class="token">”USER_ID”</span><span class="token">&gt;</span><span class="token">qwr3131c</span><span class="token" style="color: #22863a;">&lt;/stri</span><span class="token">ng</span><span class="token">&gt;</span><span class="token">
</span></span><span class="line"><span class="token">&lt;/</span><span class="token" style="color: #22863a;">map</span><span class="token">&gt;</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-679"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-677">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-678'
	>
	Even when using the shared preferences in private mode, <strong>it is simple to extract and read sensitive data</strong> from the app, as these are in plain text.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-682"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-680">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-681'
	>
	What can we do to improve it?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-685"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-683">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-684'
	>
	Preparation phase – What you’ll need to know</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-688"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-686">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-687'
	>
	The first thing that comes to mind is to simply set the <code>allowBackup</code> to false. This is a good first step, but we need to go one step further to really complicate things for attackers.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-691"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-689">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-690'
	>
	The above exploit is very simple and can be done by any attacker, so we should expect that extracting this file is always possible to a more experienced attacker, even with backup disabled.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-694"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-692">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-693'
	>
	As we don’t have control over the entire Android framework, we have to rely on Google to make it difficult for attackers to access the file. What we can and <em>should</em> do is to focus on the issue of plain text data inside that file.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-697"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-695">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-696'
	>
	One way of solving this issue is by <strong>using an encryption algorithm</strong>. Assuming you already know the basics of cryptography, we will not delve into specifics.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-700"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-698">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-699'
	>
	This example will show using a symmetric-key algorithm called <a href="https://www.nist.gov/publications/advanced-encryption-standard-aes">AES</a>. This essentially means that there will be one secret key for encryption and decryption.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-703"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-701">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-702'
	>
	The general idea is to use that secret key to encrypt the values we store in shared preferences and end up with an .xml file that has only encrypted data.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-706"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-704">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-705'
	>
	A cleaner approach is <strong>having a separate shared preference file just for sensitive data</strong> we want to encrypt and not mixing everything with other data.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-709"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-707">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-708'
	>
	Since we use a secret key, we have to secure it doesn’t get in the hands of the attacker – otherwise our efforts would be wasted.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-712"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-710">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-711'
	>
	There are several ways to tackle this problem. The first approach is to create a secret key every time we need it. The second is to create it only once and store it somewhere safe.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-715"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-713">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-714'
	>
	Recreate a key when needed</h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-718"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-716">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-717'
	>
	Recreating a secret key every time could be based on something only the user knows, like a password. After we acquire the password, we can use a key derivation function, like <a href="https://tools.ietf.org/html/rfc2898#section-5.2">PBKDF2</a> to create the secret key.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-721"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-719">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-720'
	>
	Keeping in mind that user passwords are usually of low entropy, we should <strong>make sure that we have a large number of iterations</strong> when deriving the key in order to avoid easy brute-force attacks.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-724"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-722">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-723'
	>
	Iteration count is just one of the parameters for PBKDF2. To see other parameters for a more secure key, check out <a href="https://cryptosense.com/blog/parameter-choice-for-pbkdf2/">this amazing article</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-727"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-725">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-726'
	>
	One of the main cons in this approach is from the app’s UX side.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-730"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-728">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-729'
	>
	It is often very hard to incorporate this in the app without annoying the user, especially if we talk about saving and retrieving data from shared preferences, which occurs very often. Also, it could have a negative impact on the app’s performance.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-733"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-731">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-732'
	>
	These cons are definitely fixable problems, but the correct solution depends on the particular use cases of the app which we will not go into.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-736"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-734">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-735'
	>
	Creating a permanent key</h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-739"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-737">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-738'
	>
	The second approach is creating the key once and securely saving it somewhere for later use. This approach is is easier to integrate seamlessly in our application flow.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-742"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-740">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-741'
	>
	But where to store the secret key? The preferred way is using the <a href="https://developer.android.com/training/articles/keystore">Android keystore system</a>, available since Android 4.3, API level 18.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-745"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-743">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-744'
	>
	Unfortunately, due to some <a href="https://doridori.github.io/android-security-the-forgetful-keystore/">issues</a>, it is advised to use it only from Android 6, API level 23 and up, meaning succeeding gets a bit complicated when supporting lower API levels.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-748"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-746">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-747'
	>
	One option is to have the key saved on a server and fetch it when needed.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-751"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-749">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-750'
	>
	An alternative is to save the created secret key in shared preferences. In that case, it’s <strong>important to use some sort of obfuscation when storing the secret key</strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-754"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-752">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-753'
	>
	When developing for API level 23+ and not wanting to create custom secure shared preferences, it is highly recommended to use the <a href="https://developer.android.com/jetpack/androidx/releases/security">Security</a> dependency from Jetpack for a complete secure shared preferences solution, called EncryptedSharedPreferences.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-757"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-755">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-756'
	>
	Under the hood, it uses the Android keystore system in combination with <a href="https://github.com/google/tink">tink</a>. The Android security team is working together with the tink team to <a href="https://youtu.be/W3mwSnF1n50?t=847">provide support</a> for API level 19 and above, which would be awesome!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-760"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-758">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-759'
	>
	That’s a lot of information to take in, so let’s recap it in a table to help you get a better feel of which solution is more suitable for the app in regards of implementation effort and maintenance, security and API level.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-763"
	 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-761"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-762">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2020/03/securing-data-storage-in-preparation-for-pentesting-1-1400x635.webp				media='(max-width: 699px)'
				type=image/webp								height="635"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2020/03/securing-data-storage-in-preparation-for-pentesting-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="652"
															width="1437"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Choosing the most suitable app solution		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-766"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-764">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-765'
	>
	File storage – two main locations to save files</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-769"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-767">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-768'
	>
	Before we go into the specifics of file storage, it’s important to know what kind of encryption method is used on the device level in the context of user data.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-772"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-770">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-771'
	>
	Ever since Android 7, users have been given the benefit of file-based encryption. This means that encryption is run on file level instead of the block level. It isolates and protects files for individual users on their device.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-775"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-773">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-774'
	>
	For older OS versions, specifically versions Android 4 through 9, a full-disk encryption is used. Recent changes in the OS makes file-based encryption mandatory for devices that run Android 10. To read more about this classification, check out the official <a href="https://source.android.com/security/encryption">documentation</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-778"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-776">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-777'
	>
	Regarding file storage on the application level, Android offers two main locations to save files – the external and internal storages. In case of sensitive data in files, avoid using external storage because every app can gain access to it with the appropriate permission.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-781"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-779">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-780'
	>
	In addition, external storage can be removed. For example, when using a removable SD card it is highly advised to encrypt the files. Also, when working with files from external storage, make sure to perform <a href="https://developer.android.com/training/articles/security-tips#InputValidation">input validation</a> to <strong>be sure you are working with the expected file</strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-784"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-782">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-783'
	>
	Internal storage, on the other hand, is a private sandbox area accessible only to your app. This makes it a more suitable place to save files that contain sensitive data and app’s cache data.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-787"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-785">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-786'
	>
	Furthermore, when it comes to internal storage, all data related to the app will be deleted when a user deletes the app, and no permissions will be needed to read/write files in the app’s dedicated directory.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-790"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-788">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-789'
	>
	Preparation phase – What you’ll need to know</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-793"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-791">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-792'
	>
	When saving a file containing sensitive data in the external storage, the file should definitely be encrypted. Depending on the API level supported in the app, there will be different options.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-796"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-794">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-795'
	>
	In the case when the minSdk is API level 23, it is highly recommended to use the already mentioned <a href="https://developer.android.com/jetpack/androidx/releases/security">security</a> dependency. From there, you will be able to find a class named <code>EncryptedFile</code> which will allow easy creation and reading of encrypted files.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-799"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-797">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-798'
	>
	The creation of an encrypted file is very simple:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-801"
	 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">val </span><span class="token">encryptedFile </span><span class="token" style="color: #d73a49;">=</span><span class="token"> EncryptedFile</span><span class="token">.Builder</span><span class="token">(
</span></span><span class="line"><span class="token">    </span><span class="token">File</span><span class="token">(</span><span class="token" style="color: #d73a49;">*</span><span class="token">directory</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;">my_file.txt</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">),
</span></span><span class="line"><span class="token">    context,
</span></span><span class="line"><span class="token">    MasterKeys</span><span class="token">.getOrCreate</span><span class="token">(MasterKeys.AES256_GCM_SPEC),
</span></span><span class="line"><span class="token">    EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
</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-804"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-802">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-803'
	>
	After obtaining the <code>EncryptedFile</code> instance, we can either <a href="https://developer.android.com/topic/security/data#read-files">read</a> or <a href="https://developer.android.com/topic/security/data#write-files">write</a> to it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-807"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-805">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-806'
	>
	At the time of writing this post, the above masterKeyAlias parameter is the configuration recommended by the Android security team. Under the hood, the file encryption uses tink to encrypt the contents of the file as segments.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-810"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-808">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-809'
	>
	Before API level 23, there is really no out-of-the-box solution provided by the Android framework. One alternative is to use the <code>CipherOutputStream</code> available in javax.crypto.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-813"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-811">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-812'
	>
	One of the parameters to create an instance of <code>CipherOutputStream</code> is <code>Cipher</code>, which provides the functionality of a cryptographic cipher for encryption and decryption. The configuration of the cipher depends on the algorithms that are available on the API level your app supports and the app’s use cases.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-816"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-814">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-815'
	>
	Both methods for external storage described above can also be applied to saving files in the internal storage. To avoid double encryption of the files, keep in mind that <strong>all files in the internal storage are encrypted by default</strong> starting from Android 10.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-819"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-817">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-818'
	>
	If you want to delete the files, note that the method <code>delete</code> from the <code>File</code> class only removes the file’s reference from the file system table, whereas the file will still exist on the disk until other data overwrites it, leaving it vulnerable to <a href="https://www.youtube.com/watch?v=tGw1fxUD-uY">recovery</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-822"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-820">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-821'
	>
	In most cases, we won’t need to handle this, but it’s advised to overwrite the data with other random data before deleting the file but as an extra security measure.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-825"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-823">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-824'
	>
	Databases – stored in a private directory</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-828"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-826">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-827'
	>
	Time to focus on SQLite databases on Android.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-831"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-829">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-830'
	>
	The SQLite database uses <code>.db</code> files to store data. The <code>.db</code> are stored in the private directory of your application, but the file can easily be extracted using the adb backup command.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-834"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-832">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-833'
	>
	Make sure to disable backups, in case there’s sensitive information stored in your SQLite database, similar to the case described in the shared preferences section above.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-837"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-835">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-836'
	>
	In addition, note that these databases are not encrypted and that it’s generally not advised to store sensitive data inside an unencrypted SQLlite database.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-840"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-838">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-839'
	>
	When doing operations on SQLite databases which contain sensitive information, <strong>it’s important to have proper input validation</strong>. Otherwise, SQL injection is a viable attack vector.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-843"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-841">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-842'
	>
	In other words, an attacker can manipulate an SQL query that will be interpreted as a part of the command or query, and as a result might retrieve arbitrary database records or manipulate database content.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-846"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-844">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-845'
	>
	Those kinds of attacks are much more common in the server-side web services, but exploitable instances also exist within mobile apps.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-849"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-847">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-848'
	>
	Preparation phase – What you’ll need to know</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-852"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-850">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-851'
	>
	As mentioned earlier, SQLite does not provide an out-of-the-box solution for encrypting the database. Therefore, it is <strong>not recommended to save sensitive information</strong>, especially if that data is not encrypted beforehand.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-855"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-853">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-854'
	>
	One way to solve this problem is by using <a href="https://github.com/sqlcipher/android-database-sqlcipher">SQLCipher</a>, a popular SQLite extension that offers a password-encrypted database.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-858"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-856">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-857'
	>
	Other than a small performance hit, the most noticeable negative side of using SQLCipher is its relatively big footprint on the APK size of around 7MB, unless you are using app bundles.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-861"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-859">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-860'
	>
	To use SQLCipher with Room, a persistence library that provides an abstraction layer over SQLite, follow the official instructions on the <a href="https://github.com/sqlcipher/android-database-sqlcipher#using-sqlcipher-for-android-with-room">Github page</a>. Another alternative is to use <a href="https://github.com/commonsguy/cwac-saferoom">cwac-saferoom</a> and reap the benefits from SQLCipher.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-864"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-862">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-863'
	>
	Regarding SQL injection attacks, it is advised to use parameterized query methods (query, delete, and update). To understand the exploit, check this very common example of a custom SQL query prone to an SQL injection attack:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-866"
	 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">String sql </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;">SELECT * FROM users WHERE username = ’</span><span class="token" style="color: #032f62;">&quot;</span><span class="token"> </span><span class="token" style="color: #d73a49;">+</span><span class="token"> username </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;">’ AND password = ’</span><span class="token" style="color: #032f62;">&quot;</span><span class="token"> </span><span class="token" style="color: #d73a49;">+</span><span class="token"> password </span><span class="token" style="color: #d73a49;">+</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">’</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">;
</span></span><span class="line"><span class="token">Cursor c </span><span class="token" style="color: #d73a49;">=</span><span class="token"> db</span><span class="token">.rawQuery</span><span class="token">( sql, </span><span class="token" style="color: #005cc5;">null</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-869"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-867">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-868'
	>
	Now imagine that the user enters this in the input fields:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-871"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-php github-light" data-language="php" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">username</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">1</span><span class="token" style="color: #005cc5;">’</span><span class="token"> </span><span class="token" style="color: #d73a49;">or</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"> </span><span class="token" style="color: #005cc5;">’1</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">password</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">1</span><span class="token" style="color: #005cc5;">’</span><span class="token"> </span><span class="token" style="color: #d73a49;">or</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"> </span><span class="token" style="color: #005cc5;">’1</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-874"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-872">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-873'
	>
	This would result in the following query:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-876"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-sql github-light" data-language="sql" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">SELECT</span><span class="token"> </span><span class="token" style="color: #d73a49;">*</span><span class="token"> </span><span class="token" style="color: #d73a49;">FROM</span><span class="token"> users </span><span class="token" style="color: #d73a49;">WHERE</span><span class="token"> username</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;">OR</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"> ’</span><span class="token" style="color: #005cc5;">1</span><span class="token">’ </span><span class="token" style="color: #d73a49;">AND</span><span class="token"> </span><span class="token" style="color: #d73a49;">Password</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;">OR</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"> ’</span><span class="token" style="color: #005cc5;">1</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-879"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-877">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-878'
	>
	The above query will return all records in the <code>users</code> table due to the condition ‘1’ = ‘1’ being evaluated as true. This can have some negative impact on the apps logic but could be easily avoided by using input validation.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-882"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-880">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-881'
	>
	For more information on this topic and how to avoid these exploits, check this <a href="https://www.owasp.org/index.php/SQL_Injection">OWASP resource</a> or consult this <a href="https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html">cheat sheet</a> as guidance on preventing SQL Injection flaws.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-885"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-883">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-884'
	>
	No excuse to keep data unprotected</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-888"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-886">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-887'
	>
	Dealing with sensitive information can be tricky.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-891"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-889">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-890'
	>
	Luckily, Android offers many data protection tools. In most cases, a standard encryption algorithm will be enough to secure your data but researching alternative options is advisable.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-894"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-892">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-893'
	>
	Finally, remember to always <strong>check the proven and stable methods</strong> when working with encryption algorithms. And unless you are an expert, don’t try to invent an encryption algorithm (at home).</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-897"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-895">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-896'
	>
	<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/securing-data-storage-in-preparation-for-pentesting/">Securing Data Storage in Preparation for Pentesting</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<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-1177"
	 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-900">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-903"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-901">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-902'
	>
	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-906"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-904">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-905'
	>
	<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-913"
	 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-907"
	 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-908'
	>
	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-910"
	 tabindex='-1'>
		<div class="btn__inner">
					<div	class='typography typography--size-none js-typography btn__label'
	data-id='es-911'
	>
	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-912'>
	<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-916"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-914">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-915'
	>
	The comprehensive guide to Android app penetration testing</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-919"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-917">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-918'
	>
	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-922"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-920">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-921'
	>
	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-925"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-923">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-924'
	>
	<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-928"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-926">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-927'
	>
	TLS connection</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-931"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-929">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-930'
	>
	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-934"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-932">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-933'
	>
	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-937"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-935">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-936'
	>
	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-940"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-938">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-939'
	>
	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-943"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-941">
	<h2	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-942'
	>
	What does Android OS offer, with regard to TLS?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-946"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-944">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-945'
	>
	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-949"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-947">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-948'
	>
	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-952"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-950">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-951'
	>
	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-955"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-953">
	<h2	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-954'
	>
	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-958"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-956">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-957'
	>
	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-961"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-959">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-960'
	>
	MinSdk between API levels 16 and 19</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-964"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-962">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-963'
	>
	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-966"
	 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-969"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-967">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-968'
	>
	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-972"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-970">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-971'
	>
	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-974"
	 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-977"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-975">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-976'
	>
	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-980"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-978">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-979'
	>
	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-983"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-981">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-982'
	>
	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-986"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-984">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-985'
	>
	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-989"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-987">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-988'
	>
	MinSdk API level 21+</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-992"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-990">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-991'
	>
	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-995"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-993">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-994'
	>
	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-998"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-996">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-997'
	>
	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-1001"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-999">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1000'
	>
	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-1004"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1002">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-1003'
	>
	Verifying a TLS connection</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1007"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1005">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1006'
	>
	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-1010"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-1008">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-1009'
	>
	<li>Certificate verification (Certificate pinning)</li><li>Hostname verification</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1013"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1011">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1012'
	>
	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-1016"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1014">
	<h2	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-1015'
	>
	Certificate verification (Certificate pinning)</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1019"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1017">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1018'
	>
	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-1022"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1020">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1021'
	>
	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-1025"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1023">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1024'
	>
	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-1028"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1026">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1027'
	>
	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-1031"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1029">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1030'
	>
	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-1033"
	 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-1036"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1034">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1035'
	>
	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-1039"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1037">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1038'
	>
	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-1042"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1040">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1041'
	>
	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-1045"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1043">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1044'
	>
	Check out the image below to clarify this confusion a bit:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1048"
	 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-1046"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-1047">
	<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-1051"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1049">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1050'
	>
	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-1054"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1052">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1053'
	>
	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-1057"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1055">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1056'
	>
	<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-1060"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1058">
	<h2	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-1059'
	>
	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-1063"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1061">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1062'
	>
	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-1066"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1064">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1065'
	>
	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-1069"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1067">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-1068'
	>
	Self-signed certificates</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1072"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1070">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1071'
	>
	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-1074"
	 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-1077"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1075">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1076'
	>
	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-1080"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1078">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1079'
	>
	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-1082"
	 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-1085"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1083">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1084'
	>
	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-1088"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1086">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1087'
	>
	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-1091"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1089">
	<h3	class='typography typography--size-24-text js-typography block-typography__typography'
	data-id='es-1090'
	>
	Certificates signed by a trusted CA</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1094"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1092">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1093'
	>
	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-1097"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1095">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1096'
	>
	<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-1100"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1098">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1099'
	>
	The implementation is much more straightforward:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1102"
	 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-1105"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1103">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1104'
	>
	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-1108"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1106">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1107'
	>
	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-1111"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1109">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1110'
	>
	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-1114"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1112">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1113'
	>
	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-1117"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1115">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1116'
	>
	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-1120"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1118">
	<h2	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-1119'
	>
	Hostname verification</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1123"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1121">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1122'
	>
	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-1126"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1124">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1125'
	>
	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-1129"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1127">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1128'
	>
	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-1132"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1130">
	<h2	class='typography typography--size-36-text js-typography block-typography__typography'
	data-id='es-1131'
	>
	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-1135"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1133">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1134'
	>
	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-1138"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1136">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1137'
	>
	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-1141"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1139">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1140'
	>
	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-1144"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1142">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1143'
	>
	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-1146"
	 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-1149"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1147">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1148'
	>
	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-1151"
	 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-1154"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1152">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1153'
	>
	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-1157"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1155">
	<h2	class='typography typography--size-52-default js-typography block-typography__typography'
	data-id='es-1156'
	>
	Conclusion and notes</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-1160"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1158">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1159'
	>
	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-1163"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1161">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1162'
	>
	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-1166"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1164">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1165'
	>
	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-1169"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1167">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1168'
	>
	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-1172"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1170">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1171'
	>
	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-1175"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-typography" data-id="es-1173">
	<p	class='typography typography--size-16-text-roman js-typography block-typography__typography'
	data-id='es-1174'
	>
	<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>