Skip to content

Commit 76438f1

Browse files
committed
Trust Boundary Query
1 parent 41a527c commit 76438f1

3 files changed

Lines changed: 94 additions & 0 deletions

File tree

java/ql/lib/ext/javax.servlet.http.model.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ extensions:
2626
- ["javax.servlet.http", "HttpServletResponse", False, "addHeader", "", "", "Argument[0..1]", "response-splitting", "manual"]
2727
- ["javax.servlet.http", "HttpServletResponse", False, "sendError", "(int,String)", "", "Argument[1]", "information-leak", "manual"]
2828
- ["javax.servlet.http", "HttpServletResponse", False, "setHeader", "", "", "Argument[0..1]", "response-splitting", "manual"]
29+
- ["javax.servlet.http", "HttpSession", True, "putValue", "", "", "Argument[0..1]", "trust-boundary", "manual"]
30+
- ["javax.servlet.http", "HttpSession", True, "setAttribute", "", "", "Argument[0..1]", "trust-boundary", "manual"]
2931
- addsTo:
3032
pack: codeql/java-all
3133
extensible: summaryModel
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/** Provides classes and predicates to reason about trust boundary violations */
2+
3+
import java
4+
private import semmle.code.java.dataflow.DataFlow
5+
private import semmle.code.java.dataflow.ExternalFlow
6+
private import semmle.code.java.dataflow.FlowSources
7+
private import semmle.code.java.frameworks.Servlets
8+
9+
class TrustBoundaryViolationSource extends DataFlow::Node {
10+
TrustBoundaryViolationSource() {
11+
this instanceof RemoteFlowSource and this.asExpr().getType() instanceof HttpServletRequest
12+
}
13+
}
14+
15+
class TrustBoundaryViolationSink extends DataFlow::Node {
16+
TrustBoundaryViolationSink() { sinkNode(this, "trust-boundary") }
17+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* @id java/trust-boundary-violation
3+
* @name Trust boundary violation
4+
* @description A user-provided value is used to set a session attribute.
5+
* @kind path-problem
6+
* @problem.severity error
7+
* @precision medium
8+
* @tags security
9+
* external/cwe/cwe-501
10+
*/
11+
12+
import java
13+
import semmle.code.java.dataflow.DataFlow
14+
import semmle.code.java.dataflow.FlowSources
15+
import semmle.code.java.dataflow.TaintTracking
16+
import semmle.code.java.security.TrustBoundaryViolationQuery
17+
18+
/**
19+
* The `setAttribute` method of the `HttpSession` interface.
20+
*/
21+
abstract class SessionSetAttributeMethod extends Method {
22+
abstract int getArgumentIndex();
23+
}
24+
25+
private class PlayMvcResultAddingToSessionMethod extends SessionSetAttributeMethod {
26+
PlayMvcResultAddingToSessionMethod() {
27+
this.getDeclaringType().hasQualifiedName("play.mvc", "Result") and
28+
this.hasName("addingToSession")
29+
}
30+
31+
override int getArgumentIndex() { result = [1, 2] }
32+
}
33+
34+
private class Struts2SessionMapPutMethod extends SessionSetAttributeMethod {
35+
Struts2SessionMapPutMethod() {
36+
this.getDeclaringType().hasQualifiedName("org.apache.struts2.dispatcher", "SessionMap") and
37+
this.hasName("put")
38+
}
39+
40+
override int getArgumentIndex() { result = 1 }
41+
}
42+
43+
private class Struts2SessionSetMethod extends SessionSetAttributeMethod {
44+
Struts2SessionSetMethod() {
45+
this.getDeclaringType().hasQualifiedName("org.apache.struts2.interceptor", "SessionAware") and
46+
this.hasName(["setSession", "withSession"])
47+
}
48+
49+
override int getArgumentIndex() { result = 0 }
50+
}
51+
52+
module TrustBoundaryConfig implements DataFlow::ConfigSig {
53+
predicate isSource(DataFlow::Node source) {
54+
source instanceof RemoteFlowSource and
55+
source.asExpr().(MethodAccess).getQualifier().getType() instanceof HttpServletRequest
56+
}
57+
58+
predicate isSink(DataFlow::Node sink) {
59+
exists(MethodAccess ma, SessionSetAttributeMethod m | m = ma.getMethod() |
60+
sink.asExpr() = ma.getArgument(m.getArgumentIndex())
61+
)
62+
or
63+
sink instanceof TrustBoundaryViolationSink
64+
}
65+
}
66+
67+
module TrustBoundaryFlow = TaintTracking::Global<TrustBoundaryConfig>;
68+
69+
import TrustBoundaryFlow::PathGraph
70+
71+
from TrustBoundaryFlow::PathNode source, TrustBoundaryFlow::PathNode sink
72+
where TrustBoundaryFlow::flowPath(source, sink)
73+
select sink.getNode(), sink, source,
74+
"This servlet reads data from a remote source and writes it to a $@.", sink.getNode(),
75+
"session variable"

0 commit comments

Comments
 (0)