<?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>Securing Data Storage in Preparation for Pentesting | Infinum</title>
		<atom:link href="https://infinum.com/blog/securing-data-storage-in-preparation-for-pentesting/feed/" rel="self" type="application/rss+xml" />
		<link>https://infinum.com/blog/securing-data-storage-in-preparation-for-pentesting/</link>
		<description>Building digital products</description>
		<lastBuildDate>Thu, 16 Apr 2026 15:26:52 +0000</lastBuildDate>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>

					<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-380"
	 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-paragraph" data-id="es-93">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-94'
	>
	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-98"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-96">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-97'
	>
	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-101"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-99">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-100'
	>
	Data storage security among top concerns</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-104"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-102">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-103'
	>
	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-107"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-105">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-106'
	>
	Luckily, Android provides us with various ways to keep data safe.</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-paragraph" data-id="es-108">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-109'
	>
	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-113"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-111">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-112'
	>
	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-120"
	 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-114"
	 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-115'
	>
	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-117"
	 tabindex='-1'>
		<div class="btn__inner">
					<div	class='typography typography--size-none js-typography btn__label'
	data-id='es-118'
	>
	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-119'>
	<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-123"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-121">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-122'
	>
	Shared preferences – a security risk</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-126"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-124">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-125'
	>
	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-129"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-127">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-128'
	>
	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-131"
	 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-134"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-132">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-133'
	>
	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-137"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-135">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-136'
	>
	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-140"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-138">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-139'
	>
	<code>$ adb backup com.example.app</code></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-143"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-141">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-142'
	>
	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-146"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-144">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-145'
	>
	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-149"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-147">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-148'
	>
	<code>$ abe unpack backup.ab backup.tar</code></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-152"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-150">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-151'
	>
	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-155"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-153">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-154'
	>
	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-157"
	 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-160"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-158">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-159'
	>
	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-163"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-161">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-162'
	>
	What can we do to improve it?</p></div>	</div>

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

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-169"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-167">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-168'
	>
	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-172"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-170">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-171'
	>
	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-175"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-173">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-174'
	>
	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-178"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-176">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-177'
	>
	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-181"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-179">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-180'
	>
	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-184"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-182">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-183'
	>
	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-187"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-185">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-186'
	>
	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-190"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-188">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-189'
	>
	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-193"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-191">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-192'
	>
	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-196"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-194">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-195'
	>
	Recreate a key when needed</h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-199"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-197">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-198'
	>
	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-202"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-200">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-201'
	>
	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-205"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-203">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-204'
	>
	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-208"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-206">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-207'
	>
	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-211"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-209">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-210'
	>
	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-214"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-212">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-213'
	>
	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-217"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-215">
	<h4	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-216'
	>
	Creating a permanent key</h4></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-220"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-218">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-219'
	>
	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-223"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-221">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-222'
	>
	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-226"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-224">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-225'
	>
	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-229"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-227">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-228'
	>
	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-232"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-230">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-231'
	>
	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-235"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-233">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-234'
	>
	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-238"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-236">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-237'
	>
	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-241"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-239">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-240'
	>
	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-244"
	 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-242"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-243">
	<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-247"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-245">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-246'
	>
	File storage – two main locations to save files</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-250"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-248">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-249'
	>
	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-253"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-251">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-252'
	>
	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-256"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-254">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-255'
	>
	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-259"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-257">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-258'
	>
	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-262"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-260">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-261'
	>
	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-265"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-263">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-264'
	>
	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-268"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-266">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-267'
	>
	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-271"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-269">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-270'
	>
	Preparation phase – What you’ll need to know</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-274"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-272">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-273'
	>
	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-277"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-275">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-276'
	>
	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-280"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-278">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-279'
	>
	The creation of an encrypted file is very simple:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-282"
	 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-285"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-283">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-284'
	>
	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-288"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-286">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-287'
	>
	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-291"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-289">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-290'
	>
	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-294"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-292">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-293'
	>
	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-297"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-295">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-296'
	>
	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-300"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-298">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-299'
	>
	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-303"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-301">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-302'
	>
	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-306"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-304">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-305'
	>
	Databases – stored in a private directory</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-paragraph" data-id="es-307">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-308'
	>
	Time to focus on SQLite databases on Android.</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-paragraph" data-id="es-310">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-311'
	>
	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-315"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-313">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-314'
	>
	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-318"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-316">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-317'
	>
	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-321"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-319">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-320'
	>
	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-324"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-322">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-323'
	>
	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-327"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-325">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-326'
	>
	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-330"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-328">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-329'
	>
	Preparation phase – What you’ll need to know</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-paragraph" data-id="es-331">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-332'
	>
	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-336"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-334">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-335'
	>
	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-339"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-337">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-338'
	>
	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-342"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-340">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-341'
	>
	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-345"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-343">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-344'
	>
	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-347"
	 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-350"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-348">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-349'
	>
	Now imagine that the user enters this in the input fields:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-352"
	 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-355"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-353">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-354'
	>
	This would result in the following query:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-357"
	 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-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'
	>
	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-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'
	>
	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-366"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-364">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-365'
	>
	No excuse to keep data unprotected</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-369"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-367">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-368'
	>
	Dealing with sensitive information can be tricky.</p></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'
	>
	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-375"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-373">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-374'
	>
	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-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'
	>
	<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>
		
	</channel>
</rss>