Skip to content

Commit fdcc517

Browse files
committed
UseOfLessTrustedSource -> ClientSuppliedIpUsedInSecurityCheck"
1 parent f41301f commit fdcc517

9 files changed

+52
-50
lines changed

java/ql/src/experimental/Security/CWE/CWE-348/UseOfLessTrustedSource.java renamed to java/ql/src/experimental/Security/CWE/CWE-348/ClientSuppliedIpUsedInSecurityCheck.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import org.springframework.web.bind.annotation.ResponseBody;
77

88
@Controller
9-
public class UseOfLessTrustedSource {
9+
public class ClientSuppliedIpUsedInSecurityCheck {
1010

1111
@Autowired
1212
private HttpServletRequest request;
@@ -31,12 +31,12 @@ public void bad2(HttpServletRequest request) {
3131
@ResponseBody
3232
public String good1(HttpServletRequest request) {
3333
String ip = request.getHeader("X-FORWARDED-FOR");
34-
String[] parts = ip.split(",");
3534
// Good: if this application runs behind a reverse proxy it may append the real remote IP to the end of any client-supplied X-Forwarded-For header.
36-
ip = parts[parts.length - 1];
35+
ip = ip.split(",")[ip.split(",").length - 1];
3736
if (!StringUtils.startsWith(ip, "192.168.")) {
3837
new Exception("ip illegal");
3938
}
39+
return ip;
4040
}
4141

4242
protected String getClientIP() {

java/ql/src/experimental/Security/CWE/CWE-348/UseOfLessTrustedSource.qhelp renamed to java/ql/src/experimental/Security/CWE/CWE-348/ClientSuppliedIpUsedInSecurityCheck.qhelp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ bypass a ban-list, for example.</p>
1919
In <code>bad1</code> method and <code>bad2</code> method, the client ip the <code>X-Forwarded-For</code> is split into comma-separated values, but the less-trustworthy first one is used. Both of these examples could be deceived by providing a forged HTTP header. The method
2020
<code>good1</code> similarly splits an <code>X-Forwarded-For</code> value, but uses the last, more-trustworthy entry.</p>
2121

22-
<sample src="UseOfLessTrustedSource.java" />
22+
<sample src="ClientSuppliedIpUsedInSecurityCheck.java" />
2323

2424
</example>
2525
<references>

java/ql/src/experimental/Security/CWE/CWE-348/UseOfLessTrustedSource.ql renamed to java/ql/src/experimental/Security/CWE/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,23 @@
1111
*/
1212

1313
import java
14-
import UseOfLessTrustedSourceLib
14+
import ClientSuppliedIpUsedInSecurityCheckLib
1515
import semmle.code.java.dataflow.FlowSources
1616
import DataFlow::PathGraph
1717

1818
/**
1919
* Taint-tracking configuration tracing flow from obtaining a client ip from an HTTP header to a sensitive use.
2020
*/
21-
class UseOfLessTrustedSourceConfig extends TaintTracking::Configuration {
22-
UseOfLessTrustedSourceConfig() { this = "UseOfLessTrustedSourceConfig" }
21+
class ClientSuppliedIpUsedInSecurityCheckConfig extends TaintTracking::Configuration {
22+
ClientSuppliedIpUsedInSecurityCheckConfig() { this = "ClientSuppliedIpUsedInSecurityCheckConfig" }
2323

24-
override predicate isSource(DataFlow::Node source) { source instanceof UseOfLessTrustedSource }
24+
override predicate isSource(DataFlow::Node source) {
25+
source instanceof ClientSuppliedIpUsedInSecurityCheck
26+
}
2527

26-
override predicate isSink(DataFlow::Node sink) { sink instanceof UseOfLessTrustedSink }
28+
override predicate isSink(DataFlow::Node sink) {
29+
sink instanceof ClientSuppliedIpUsedInSecurityCheckSink
30+
}
2731

2832
/**
2933
* Splitting a header value by `,` and taking an entry other than the first is sanitizing, because
@@ -42,7 +46,8 @@ class UseOfLessTrustedSourceConfig extends TaintTracking::Configuration {
4246
}
4347
}
4448

45-
from DataFlow::PathNode source, DataFlow::PathNode sink, UseOfLessTrustedSourceConfig conf
49+
from
50+
DataFlow::PathNode source, DataFlow::PathNode sink, ClientSuppliedIpUsedInSecurityCheckConfig conf
4651
where conf.hasFlowPath(source, sink)
4752
select sink.getNode(), source, sink, "IP address spoofing might include code from $@.",
4853
source.getNode(), "this user input"

java/ql/src/experimental/Security/CWE/CWE-348/UseOfLessTrustedSourceLib.qll renamed to java/ql/src/experimental/Security/CWE/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import experimental.semmle.code.java.Logging
1010
*
1111
* For example: `ServletRequest.getHeader("X-Forwarded-For")`.
1212
*/
13-
class UseOfLessTrustedSource extends DataFlow::Node {
14-
UseOfLessTrustedSource() {
13+
class ClientSuppliedIpUsedInSecurityCheck extends DataFlow::Node {
14+
ClientSuppliedIpUsedInSecurityCheck() {
1515
exists(MethodAccess ma |
1616
ma.getMethod().hasName("getHeader") and
1717
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue().toLowerCase() in [
@@ -25,15 +25,15 @@ class UseOfLessTrustedSource extends DataFlow::Node {
2525
}
2626

2727
/** A data flow sink for ip address forgery vulnerabilities. */
28-
abstract class UseOfLessTrustedSink extends DataFlow::Node { }
28+
abstract class ClientSuppliedIpUsedInSecurityCheckSink extends DataFlow::Node { }
2929

3030
/**
3131
* A data flow sink for remote client ip comparison.
3232
*
3333
* For example: `if (!StringUtils.startsWith(ipAddr, "192.168.")){...` determine whether the client ip starts
3434
* with `192.168.`, and the program can be deceived by forging the ip address.
3535
*/
36-
private class CompareSink extends UseOfLessTrustedSink {
36+
private class CompareSink extends ClientSuppliedIpUsedInSecurityCheckSink {
3737
CompareSink() {
3838
exists(MethodAccess ma |
3939
ma.getMethod().getName() in ["equals", "equalsIgnoreCase"] and
@@ -55,10 +55,7 @@ private class CompareSink extends UseOfLessTrustedSink {
5555
ma.getMethod().getDeclaringType() instanceof TypeString and
5656
ma.getMethod().getNumberOfParameters() = 1 and
5757
ma.getQualifier() = this.asExpr() and
58-
ma.getAnArgument()
59-
.(CompileTimeConstantExpr)
60-
.getStringValue()
61-
.regexpMatch("^((10\\.((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)(\\.)?)|(192\\.168\\.)|172\\.(1[6789]|2[0-9]|3[01])\\.)((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)(\\.)?((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)$") // Matches IP-address-like strings
58+
ma.getAnArgument().(CompileTimeConstantExpr).getStringValue().regexpMatch(getIpAddressRegex()) // Matches IP-address-like strings
6259
)
6360
or
6461
exists(MethodAccess ma |
@@ -68,10 +65,7 @@ private class CompareSink extends UseOfLessTrustedSink {
6865
.hasQualifiedName(["org.apache.commons.lang3", "org.apache.commons.lang"], "StringUtils") and
6966
ma.getMethod().getNumberOfParameters() = 2 and
7067
ma.getAnArgument() = this.asExpr() and
71-
ma.getAnArgument()
72-
.(CompileTimeConstantExpr)
73-
.getStringValue()
74-
.regexpMatch("^((10\\.((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)(\\.)?)|(192\\.168\\.)|172\\.(1[6789]|2[0-9]|3[01])\\.)((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)(\\.)?((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)$")
68+
ma.getAnArgument().(CompileTimeConstantExpr).getStringValue().regexpMatch(getIpAddressRegex())
7569
)
7670
or
7771
exists(MethodAccess ma |
@@ -88,7 +82,7 @@ private class CompareSink extends UseOfLessTrustedSink {
8882
}
8983

9084
/** A data flow sink for sql operation. */
91-
private class SqlOperationSink extends UseOfLessTrustedSink {
85+
private class SqlOperationSink extends ClientSuppliedIpUsedInSecurityCheckSink {
9286
SqlOperationSink() { this instanceof QueryInjectionSink }
9387
}
9488

@@ -99,3 +93,8 @@ class SplitMethod extends Method {
9993
this.hasQualifiedName("java.lang", "String", "split")
10094
}
10195
}
96+
97+
string getIpAddressRegex() {
98+
result =
99+
"^((10\\.((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)(\\.)?)|(192\\.168\\.)|172\\.(1[6789]|2[0-9]|3[01])\\.)((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)(\\.)?((1\\d{2})?|(2[0-4]\\d)?|(25[0-5])?|([1-9]\\d|[0-9])?)$"
100+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
edges
2+
| ClientSuppliedIpUsedInSecurityCheck.java:16:21:16:33 | getClientIP(...) : String | ClientSuppliedIpUsedInSecurityCheck.java:17:37:17:38 | ip |
3+
| ClientSuppliedIpUsedInSecurityCheck.java:24:21:24:33 | getClientIP(...) : String | ClientSuppliedIpUsedInSecurityCheck.java:25:33:25:34 | ip |
4+
| ClientSuppliedIpUsedInSecurityCheck.java:43:27:43:62 | getHeader(...) : String | ClientSuppliedIpUsedInSecurityCheck.java:47:16:47:37 | ...[...] : String |
5+
| ClientSuppliedIpUsedInSecurityCheck.java:47:16:47:37 | ...[...] : String | ClientSuppliedIpUsedInSecurityCheck.java:16:21:16:33 | getClientIP(...) : String |
6+
| ClientSuppliedIpUsedInSecurityCheck.java:47:16:47:37 | ...[...] : String | ClientSuppliedIpUsedInSecurityCheck.java:24:21:24:33 | getClientIP(...) : String |
7+
nodes
8+
| ClientSuppliedIpUsedInSecurityCheck.java:16:21:16:33 | getClientIP(...) : String | semmle.label | getClientIP(...) : String |
9+
| ClientSuppliedIpUsedInSecurityCheck.java:17:37:17:38 | ip | semmle.label | ip |
10+
| ClientSuppliedIpUsedInSecurityCheck.java:24:21:24:33 | getClientIP(...) : String | semmle.label | getClientIP(...) : String |
11+
| ClientSuppliedIpUsedInSecurityCheck.java:25:33:25:34 | ip | semmle.label | ip |
12+
| ClientSuppliedIpUsedInSecurityCheck.java:43:27:43:62 | getHeader(...) : String | semmle.label | getHeader(...) : String |
13+
| ClientSuppliedIpUsedInSecurityCheck.java:47:16:47:37 | ...[...] : String | semmle.label | ...[...] : String |
14+
#select
15+
| ClientSuppliedIpUsedInSecurityCheck.java:17:37:17:38 | ip | ClientSuppliedIpUsedInSecurityCheck.java:43:27:43:62 | getHeader(...) : String | ClientSuppliedIpUsedInSecurityCheck.java:17:37:17:38 | ip | IP address spoofing might include code from $@. | ClientSuppliedIpUsedInSecurityCheck.java:43:27:43:62 | getHeader(...) | this user input |
16+
| ClientSuppliedIpUsedInSecurityCheck.java:25:33:25:34 | ip | ClientSuppliedIpUsedInSecurityCheck.java:43:27:43:62 | getHeader(...) : String | ClientSuppliedIpUsedInSecurityCheck.java:25:33:25:34 | ip | IP address spoofing might include code from $@. | ClientSuppliedIpUsedInSecurityCheck.java:43:27:43:62 | getHeader(...) | this user input |

java/ql/test/experimental/query-tests/security/CWE-348/UseOfLessTrustedSource.java renamed to java/ql/test/experimental/query-tests/security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import org.springframework.web.bind.annotation.ResponseBody;
77

88
@Controller
9-
public class UseOfLessTrustedSource {
9+
public class ClientSuppliedIpUsedInSecurityCheck {
1010

1111
@Autowired
1212
private HttpServletRequest request;
@@ -30,15 +30,13 @@ public void bad2(HttpServletRequest request) {
3030
@GetMapping(value = "good1")
3131
@ResponseBody
3232
public String good1(HttpServletRequest request) {
33-
String remoteAddr = "";
34-
if (request != null) {
35-
remoteAddr = request.getHeader("X-FORWARDED-FOR");
36-
remoteAddr = remoteAddr.split(",")[remoteAddr.split(",").length - 1]; // good
37-
if (remoteAddr == null || "".equals(remoteAddr)) {
38-
remoteAddr = request.getRemoteAddr();
39-
}
33+
String ip = request.getHeader("X-FORWARDED-FOR");
34+
// Good: if this application runs behind a reverse proxy it may append the real remote IP to the end of any client-supplied X-Forwarded-For header.
35+
ip = ip.split(",")[ip.split(",").length - 1];
36+
if (!StringUtils.startsWith(ip, "192.168.")) {
37+
new Exception("ip illegal");
4038
}
41-
return remoteAddr;
39+
return ip;
4240
}
4341

4442
protected String getClientIP() {
@@ -48,4 +46,4 @@ protected String getClientIP() {
4846
}
4947
return xfHeader.split(",")[0];
5048
}
51-
}
49+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
experimental/Security/CWE/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql

java/ql/test/experimental/query-tests/security/CWE-348/UseOfLessTrustedSource.expected

Lines changed: 0 additions & 16 deletions
This file was deleted.

java/ql/test/experimental/query-tests/security/CWE-348/UseOfLessTrustedSource.qlref

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)