Skip to content

Commit e1a680c

Browse files
committed
Address improper URL authorization
1 parent 9a0b2b1 commit e1a680c

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
public boolean shouldOverrideUrlLoading(WebView view, String url) {
2+
{
3+
Uri uri = Uri.parse(url);
4+
// BAD: partial domain match, which allows an attacker to register a domain like myexample.com to circumvent the verification
5+
if (uri.getHost() != null && uri.getHost().endsWith("example.com")) {
6+
return false;
7+
}
8+
}
9+
10+
{
11+
Uri uri = Uri.parse(url);
12+
// GOOD: full domain match
13+
if (uri.getHost() != null && uri.getHost().endsWith(".example.com")) {
14+
return false;
15+
}
16+
}
17+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
<overview>
7+
<p>Apps that rely on URL Parsing to verify that a given URL is pointing to a trust server may be susceptible to many different ways to get URL parsing and verification wrong, which allows an attacker to register a fake site to break the access control.</p>
8+
</overview>
9+
10+
<recommendation>
11+
<p>Verify the whole host and domain (FQDN) or check endsWith dot+domain.</p>
12+
</recommendation>
13+
14+
<example>
15+
<p>The following example shows two ways of verify host domain. In the 'BAD' case,
16+
verification is implemented as partial domain match. In the 'GOOD' case, full domain is verified.</p>
17+
<sample src="IncorrectURLVerification.java" />
18+
</example>
19+
20+
<references>
21+
<li>
22+
<a href="https://drive.google.com/file/d/0BwMN49Gzo3x6T1N5WGQ4TTNlMHBOb1ZRQTVEWnVBZjFUaE5N/view">Common Android app vulnerabilities from Sebastian Porst of Google</a>
23+
</li>
24+
<li>
25+
<a href="https://www.bugcrowd.com/resources/webinars/overview-of-common-android-app-vulnerabilities/">Common Android app vulnerabilities from bugcrowd</a>
26+
<li>
27+
<a href="https://cwe.mitre.org/data/definitions/939.html">CWE 939</a>
28+
</li>
29+
</references>
30+
</qhelp>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* @id java/incorrect-url-verification
3+
* @name Insertion of sensitive information into log files
4+
* @description Apps that rely on URL parsing to verify that a given URL is pointing to a trusted server are susceptible to wrong ways of URL parsing and verification.
5+
* @kind problem
6+
* @tags security
7+
* external/cwe-939
8+
*/
9+
10+
import java
11+
import semmle.code.java.dataflow.FlowSources
12+
import semmle.code.java.dataflow.TaintTracking
13+
import DataFlow
14+
import PathGraph
15+
16+
17+
/**
18+
* The Java class `android.net.Uri` and `java.net.URL`.
19+
*/
20+
class Uri extends RefType {
21+
Uri() {
22+
hasQualifiedName("android.net", "Uri") or
23+
hasQualifiedName("java.net", "URL")
24+
}
25+
}
26+
27+
/**
28+
* The method `getHost()` declared in `android.net.Uri` and `java.net.URL`.
29+
*/
30+
class UriGetHostMethod extends Method {
31+
UriGetHostMethod() {
32+
getDeclaringType() instanceof Uri and
33+
hasName("getHost") and
34+
getNumberOfParameters() = 0
35+
}
36+
}
37+
38+
/**
39+
* A library method that acts like `String.format` by formatting a number of
40+
* its arguments according to a format string.
41+
*/
42+
class HostVerificationMethodAccess extends MethodAccess {
43+
HostVerificationMethodAccess() {
44+
(
45+
46+
this.getMethod().hasName("endsWith") or
47+
this.getMethod().hasName("contains") or
48+
this.getMethod().hasName("indexOf")
49+
) and
50+
this.getMethod().getNumberOfParameters() = 1 and
51+
(
52+
this.getArgument(0).(StringLiteral).getRepresentedString().charAt(0) != "." or //string constant comparison
53+
this.getArgument(0).(AddExpr).getLeftOperand().(VarAccess).getVariable().getAnAssignedValue().(StringLiteral).getRepresentedString().charAt(0) != "." or //var1+var2, check var1 starts with "."
54+
this.getArgument(0).(AddExpr).getLeftOperand().(StringLiteral).getRepresentedString().charAt(0) != "." or //"."+var2, check string constant "."
55+
exists (MethodAccess ma | this.getArgument(0) = ma and ma.getMethod().hasName("getString") and ma.getArgument(0).toString().indexOf("R.string") = 0) or //res.getString(R.string.key)
56+
this.getArgument(0).(VarAccess).getVariable().getAnAssignedValue().(StringLiteral).getRepresentedString().charAt(0) != "." //check variable starts with "."
57+
)
58+
}
59+
}
60+
61+
from UriGetHostMethod um, MethodAccess uma, HostVerificationMethodAccess hma
62+
where hma.getQualifier() = uma and uma.getMethod() = um
63+
select "Potentially improper URL verification with $@ in $@ having $@.",
64+
hma, hma.getFile(), hma.getArgument(0), "user-provided value"

0 commit comments

Comments
 (0)