|
13 | 13 | */
|
14 | 14 |
|
15 | 15 | import java
|
16 |
| -import semmle.code.java.dataflow.FlowSources |
17 |
| -import semmle.code.java.dataflow.TaintTracking |
| 16 | +import semmle.code.java.security.RegexInjectionQuery |
18 | 17 | import DataFlow::PathGraph
|
19 | 18 |
|
20 |
| -/** |
21 |
| - * A data flow sink for untrusted user input used to construct regular expressions. |
22 |
| - */ |
23 |
| -class RegexSink extends DataFlow::ExprNode { |
24 |
| - RegexSink() { |
25 |
| - exists(MethodAccess ma, Method m | m = ma.getMethod() | |
26 |
| - ( |
27 |
| - m.getDeclaringType() instanceof TypeString and |
28 |
| - ( |
29 |
| - ma.getArgument(0) = this.asExpr() and |
30 |
| - // TODO: confirm if more/less than the below need to be handled |
31 |
| - m.hasName(["matches", "split", "replaceFirst", "replaceAll"]) |
32 |
| - ) |
33 |
| - or |
34 |
| - // TODO: review Java Pattern API |
35 |
| - m.getDeclaringType().hasQualifiedName("java.util.regex", "Pattern") and |
36 |
| - ( |
37 |
| - ma.getArgument(0) = this.asExpr() and |
38 |
| - // TODO: confirm if more/less than the below need to be handled |
39 |
| - m.hasName(["compile", "matches"]) |
40 |
| - ) |
41 |
| - or |
42 |
| - // TODO: read docs about regex APIs in Java |
43 |
| - m.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "RegExUtils") and |
44 |
| - ( |
45 |
| - ma.getArgument(1) = this.asExpr() and |
46 |
| - m.getParameterType(1) instanceof TypeString and |
47 |
| - // TODO: confirm if more/less than the below need to be handled |
48 |
| - m.hasName([ |
49 |
| - "removeAll", "removeFirst", "removePattern", "replaceAll", "replaceFirst", |
50 |
| - "replacePattern" |
51 |
| - ]) |
52 |
| - ) |
53 |
| - ) |
54 |
| - ) |
55 |
| - } |
56 |
| -} |
57 |
| - |
58 |
| -// TODO: is this abstract class needed? Are there pre-existing sanitizer classes that can be used instead? |
59 |
| -abstract class Sanitizer extends DataFlow::ExprNode { } |
60 |
| - |
61 |
| -/** |
62 |
| - * A call to a function whose name suggests that it escapes regular |
63 |
| - * expression meta-characters. |
64 |
| - */ |
65 |
| -class RegExpSanitizationCall extends Sanitizer { |
66 |
| - RegExpSanitizationCall() { |
67 |
| - exists(string calleeName, string sanitize, string regexp | |
68 |
| - calleeName = this.asExpr().(Call).getCallee().getName() and |
69 |
| - sanitize = "(?:escape|saniti[sz]e)" and // TODO: confirm this is sufficient |
70 |
| - regexp = "regexp?" // TODO: confirm this is sufficient |
71 |
| - | |
72 |
| - calleeName |
73 |
| - .regexpMatch("(?i)(" + sanitize + ".*" + regexp + ".*)" + "|(" + regexp + ".*" + sanitize + |
74 |
| - ".*)") // TODO: confirm this is sufficient |
75 |
| - ) |
76 |
| - } |
77 |
| -} |
78 |
| - |
79 |
| -/** |
80 |
| - * A taint-tracking configuration for untrusted user input used to construct regular expressions. |
81 |
| - */ |
82 |
| -class RegexInjectionConfiguration extends TaintTracking::Configuration { |
83 |
| - RegexInjectionConfiguration() { this = "RegexInjectionConfiguration" } |
84 |
| - |
85 |
| - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } |
86 |
| - |
87 |
| - override predicate isSink(DataFlow::Node sink) { sink instanceof RegexSink } |
88 |
| - |
89 |
| - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } |
90 |
| -} |
91 |
| - |
92 | 19 | from DataFlow::PathNode source, DataFlow::PathNode sink, RegexInjectionConfiguration c
|
93 | 20 | where c.hasFlowPath(source, sink)
|
94 | 21 | select sink.getNode(), source, sink, "This regular expression is constructed from a $@.",
|
95 | 22 | source.getNode(), "user-provided value"
|
96 |
| -// from MethodAccess ma |
97 |
| -// where |
98 |
| -// // ma.getMethod().hasName("startsWith") and // graphhopper |
99 |
| -// // ma.getFile().getBaseName() = "NavigateResource.java" // graphhopper |
100 |
| -// // ma.getMethod().hasName("substring") and // jfinal |
101 |
| -// // ma.getFile().getBaseName() = "FileManager.java" // jfinal |
102 |
| -// ma.getMethod().hasName("startsWith") and // roller |
103 |
| -// ma.getFile().getBaseName() = "PageServlet.java" // roller (or RegexUtil.java) |
104 |
| -// ProteinArraySignificanceTestJSON.java or MockRKeys.java for cbioportal |
105 |
| -// select ma, "method access" |
0 commit comments