Skip to content

Commit 10a6362

Browse files
committed
Java: Introduce an abstract class RemoteFlowSource to ease customization.
1 parent ceda0d5 commit 10a6362

File tree

1 file changed

+90
-26
lines changed

1 file changed

+90
-26
lines changed

java/ql/src/semmle/code/java/dataflow/FlowSources.qll

Lines changed: 90 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,68 +21,132 @@ import semmle.code.java.frameworks.Guice
2121
import semmle.code.java.frameworks.struts.StrutsActions
2222
import semmle.code.java.frameworks.Thrift
2323

24-
/** Class for `tainted` user input. */
25-
abstract class UserInput extends DataFlow::Node { }
26-
27-
private predicate variableStep(Expr tracked, VarAccess sink) {
28-
exists(VariableAssign def |
29-
def.getSource() = tracked and
30-
defUsePair(def, sink)
31-
)
24+
/** A data flow source of remote user input. */
25+
abstract class RemoteFlowSource extends DataFlow::Node {
26+
/** Gets a string that describes the type of this remote flow source. */
27+
abstract string getSourceType();
3228
}
3329

34-
/** Input that may be controlled by a remote user. */
35-
class RemoteUserInput extends UserInput {
36-
RemoteUserInput() {
30+
private class RemoteTaintedMethodAccessSource extends RemoteFlowSource {
31+
RemoteTaintedMethodAccessSource() {
3732
this.asExpr().(MethodAccess).getMethod() instanceof RemoteTaintedMethod
38-
or
39-
// Parameters to RMI methods.
33+
}
34+
35+
override string getSourceType() { result = "network data source" }
36+
}
37+
38+
private class RmiMethodParameterSource extends RemoteFlowSource {
39+
RmiMethodParameterSource() {
4040
exists(RemoteCallableMethod method |
4141
method.getAParameter() = this.asParameter() and
4242
(
4343
getType() instanceof PrimitiveType or
4444
getType() instanceof TypeString
4545
)
4646
)
47-
or
48-
// Parameters to Jax WS methods.
47+
}
48+
49+
override string getSourceType() { result = "RMI method parameter" }
50+
}
51+
52+
private class JaxWsMethodParameterSource extends RemoteFlowSource {
53+
JaxWsMethodParameterSource() {
4954
exists(JaxWsEndpoint endpoint |
5055
endpoint.getARemoteMethod().getAParameter() = this.asParameter()
5156
)
52-
or
53-
// Parameters to Jax Rs methods.
57+
}
58+
59+
override string getSourceType() { result = "Jax WS method parameter" }
60+
}
61+
62+
private class JaxRsMethodParameterSource extends RemoteFlowSource {
63+
JaxRsMethodParameterSource() {
5464
exists(JaxRsResourceClass service |
5565
service.getAnInjectableCallable().getAParameter() = this.asParameter() or
5666
service.getAnInjectableField().getAnAccess() = this.asExpr()
5767
)
58-
or
59-
// Reverse DNS. Try not to trigger on `localhost`.
68+
}
69+
70+
override string getSourceType() { result = "Jax Rs method parameter" }
71+
}
72+
73+
private predicate variableStep(Expr tracked, VarAccess sink) {
74+
exists(VariableAssign def |
75+
def.getSource() = tracked and
76+
defUsePair(def, sink)
77+
)
78+
}
79+
80+
private class ReverseDnsSource extends RemoteFlowSource {
81+
ReverseDnsSource() {
82+
// Try not to trigger on `localhost`.
6083
exists(MethodAccess m | m = this.asExpr() |
6184
m.getMethod() instanceof ReverseDNSMethod and
6285
not exists(MethodAccess l |
6386
(variableStep(l, m.getQualifier()) or l = m.getQualifier()) and
6487
l.getMethod().getName() = "getLocalHost"
6588
)
6689
)
67-
or
68-
//MessageBodyReader
90+
}
91+
92+
override string getSourceType() { result = "reverse DNS lookup" }
93+
}
94+
95+
private class MessageBodyReaderParameterSource extends RemoteFlowSource {
96+
MessageBodyReaderParameterSource() {
6997
exists(MessageBodyReaderRead m |
7098
m.getParameter(4) = this.asParameter() or
7199
m.getParameter(5) = this.asParameter()
72100
)
73-
or
101+
}
102+
103+
override string getSourceType() { result = "MessageBodyReader parameter" }
104+
}
105+
106+
private class SpringServletInputParameterSource extends RemoteFlowSource {
107+
SpringServletInputParameterSource() {
74108
this.asParameter().getAnAnnotation() instanceof SpringServletInputAnnotation
75-
or
109+
}
110+
111+
override string getSourceType() { result = "Spring servlet input parameter" }
112+
}
113+
114+
private class GuiceRequestParameterSource extends RemoteFlowSource {
115+
GuiceRequestParameterSource() {
76116
exists(GuiceRequestParametersAnnotation a |
77117
a = this.asParameter().getAnAnnotation() or
78118
a = this.asExpr().(FieldRead).getField().getAnAnnotation()
79119
)
80-
or
81-
exists(Struts2ActionSupportClass c | c.getASetterMethod().getField() = this.asExpr().(FieldRead).getField())
82-
or
120+
}
121+
122+
override string getSourceType() { result = "Guice request parameter" }
123+
}
124+
125+
private class Struts2ActionSupportClassFieldReadSource extends RemoteFlowSource {
126+
Struts2ActionSupportClassFieldReadSource() {
127+
exists(Struts2ActionSupportClass c |
128+
c.getASetterMethod().getField() = this.asExpr().(FieldRead).getField()
129+
)
130+
}
131+
132+
override string getSourceType() { result = "Struts2 ActionSupport field" }
133+
}
134+
135+
private class ThriftIfaceParameterSource extends RemoteFlowSource {
136+
ThriftIfaceParameterSource() {
83137
exists(ThriftIface i | i.getAnImplementingMethod().getAParameter() = this.asParameter())
84138
}
85139

140+
override string getSourceType() { result = "Thrift Iface parameter" }
141+
}
142+
143+
/** Class for `tainted` user input. */
144+
abstract class UserInput extends DataFlow::Node { }
145+
146+
/** Input that may be controlled by a remote user. */
147+
class RemoteUserInput extends UserInput {
148+
RemoteUserInput() { this instanceof RemoteFlowSource }
149+
86150
/**
87151
* DEPRECATED: Use a configuration with a defined sink instead.
88152
*

0 commit comments

Comments
 (0)