|
14 | 14 | */
|
15 | 15 |
|
16 | 16 | import java
|
17 |
| -import semmle.code.java.dataflow.DataFlow |
18 |
| -import semmle.code.java.dataflow.TaintTracking |
19 |
| -import semmle.code.java.security.InformationLeak |
20 |
| - |
21 |
| -/** |
22 |
| - * One of the `printStackTrace()` overloads on `Throwable`. |
23 |
| - */ |
24 |
| -class PrintStackTraceMethod extends Method { |
25 |
| - PrintStackTraceMethod() { |
26 |
| - this.getDeclaringType() |
27 |
| - .getSourceDeclaration() |
28 |
| - .getASourceSupertype*() |
29 |
| - .hasQualifiedName("java.lang", "Throwable") and |
30 |
| - this.getName() = "printStackTrace" |
31 |
| - } |
32 |
| -} |
33 |
| - |
34 |
| -module ServletWriterSourceToPrintStackTraceMethodFlowConfig implements DataFlow::ConfigSig { |
35 |
| - predicate isSource(DataFlow::Node src) { src.asExpr() instanceof XssVulnerableWriterSource } |
36 |
| - |
37 |
| - predicate isSink(DataFlow::Node sink) { |
38 |
| - exists(MethodAccess ma | |
39 |
| - sink.asExpr() = ma.getAnArgument() and ma.getMethod() instanceof PrintStackTraceMethod |
40 |
| - ) |
41 |
| - } |
42 |
| -} |
43 |
| - |
44 |
| -module ServletWriterSourceToPrintStackTraceMethodFlow = |
45 |
| - TaintTracking::Global<ServletWriterSourceToPrintStackTraceMethodFlowConfig>; |
46 |
| - |
47 |
| -/** |
48 |
| - * A call that uses `Throwable.printStackTrace()` on a stream that is connected |
49 |
| - * to external output. |
50 |
| - */ |
51 |
| -predicate printsStackToWriter(MethodAccess call) { |
52 |
| - exists(PrintStackTraceMethod printStackTrace | |
53 |
| - call.getMethod() = printStackTrace and |
54 |
| - ServletWriterSourceToPrintStackTraceMethodFlow::flowToExpr(call.getAnArgument()) |
55 |
| - ) |
56 |
| -} |
57 |
| - |
58 |
| -/** |
59 |
| - * A `PrintWriter` that wraps a given string writer. This pattern is used |
60 |
| - * in the most common idiom for converting a `Throwable` to a string. |
61 |
| - */ |
62 |
| -predicate printWriterOnStringWriter(Expr printWriter, Variable stringWriterVar) { |
63 |
| - printWriter.getType().(Class).hasQualifiedName("java.io", "PrintWriter") and |
64 |
| - stringWriterVar.getType().(Class).hasQualifiedName("java.io", "StringWriter") and |
65 |
| - ( |
66 |
| - printWriter.(ClassInstanceExpr).getAnArgument() = stringWriterVar.getAnAccess() or |
67 |
| - printWriterOnStringWriter(printWriter.(VarAccess).getVariable().getInitializer(), |
68 |
| - stringWriterVar) |
69 |
| - ) |
70 |
| -} |
71 |
| - |
72 |
| -predicate stackTraceExpr(Expr exception, MethodAccess stackTraceString) { |
73 |
| - exists(Expr printWriter, Variable stringWriterVar, MethodAccess printStackCall | |
74 |
| - printWriterOnStringWriter(printWriter, stringWriterVar) and |
75 |
| - printStackCall.getMethod() instanceof PrintStackTraceMethod and |
76 |
| - printStackCall.getAnArgument() = printWriter and |
77 |
| - printStackCall.getQualifier() = exception and |
78 |
| - stackTraceString.getQualifier() = stringWriterVar.getAnAccess() and |
79 |
| - stackTraceString.getMethod() instanceof ToStringMethod |
80 |
| - ) |
81 |
| -} |
82 |
| - |
83 |
| -module StackTraceStringToHttpResponseSinkFlowConfig implements DataFlow::ConfigSig { |
84 |
| - predicate isSource(DataFlow::Node src) { stackTraceExpr(_, src.asExpr()) } |
85 |
| - |
86 |
| - predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink } |
87 |
| -} |
88 |
| - |
89 |
| -module StackTraceStringToHttpResponseSinkFlow = |
90 |
| - TaintTracking::Global<StackTraceStringToHttpResponseSinkFlowConfig>; |
91 |
| - |
92 |
| -/** |
93 |
| - * A write of stack trace data to an external stream. |
94 |
| - */ |
95 |
| -predicate printsStackExternally(MethodAccess call, Expr stackTrace) { |
96 |
| - printsStackToWriter(call) and |
97 |
| - call.getQualifier() = stackTrace and |
98 |
| - not call.getQualifier() instanceof SuperAccess |
99 |
| -} |
100 |
| - |
101 |
| -/** |
102 |
| - * A stringified stack trace flows to an external sink. |
103 |
| - */ |
104 |
| -predicate stringifiedStackFlowsExternally(DataFlow::Node externalExpr, Expr stackTrace) { |
105 |
| - exists(MethodAccess stackTraceString | |
106 |
| - stackTraceExpr(stackTrace, stackTraceString) and |
107 |
| - StackTraceStringToHttpResponseSinkFlow::flow(DataFlow::exprNode(stackTraceString), externalExpr) |
108 |
| - ) |
109 |
| -} |
110 |
| - |
111 |
| -class GetMessageFlowSource extends MethodAccess { |
112 |
| - GetMessageFlowSource() { |
113 |
| - exists(Method method | |
114 |
| - method = this.getMethod() and |
115 |
| - method.hasName("getMessage") and |
116 |
| - method.hasNoParameters() and |
117 |
| - method.getDeclaringType().hasQualifiedName("java.lang", "Throwable") |
118 |
| - ) |
119 |
| - } |
120 |
| -} |
121 |
| - |
122 |
| -module GetMessageFlowSourceToHttpResponseSinkFlowConfig implements DataFlow::ConfigSig { |
123 |
| - predicate isSource(DataFlow::Node src) { src.asExpr() instanceof GetMessageFlowSource } |
124 |
| - |
125 |
| - predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink } |
126 |
| -} |
127 |
| - |
128 |
| -module GetMessageFlowSourceToHttpResponseSinkFlow = |
129 |
| - TaintTracking::Global<GetMessageFlowSourceToHttpResponseSinkFlowConfig>; |
130 |
| - |
131 |
| -/** |
132 |
| - * A call to `getMessage()` that then flows to a servlet response. |
133 |
| - */ |
134 |
| -predicate getMessageFlowsExternally(DataFlow::Node externalExpr, GetMessageFlowSource getMessage) { |
135 |
| - GetMessageFlowSourceToHttpResponseSinkFlow::flow(DataFlow::exprNode(getMessage), externalExpr) |
136 |
| -} |
| 17 | +import semmle.code.java.security.StackTraceExposureQuery |
137 | 18 |
|
138 | 19 | from Expr externalExpr, Expr errorInformation
|
139 | 20 | where
|
140 | 21 | printsStackExternally(externalExpr, errorInformation) or
|
141 | 22 | stringifiedStackFlowsExternally(DataFlow::exprNode(externalExpr), errorInformation) or
|
142 |
| - getMessageFlowsExternally(DataFlow::exprNode(externalExpr), errorInformation) |
| 23 | + getMessageFlowsExternally(DataFlow::exprNode(externalExpr), DataFlow::exprNode(errorInformation)) |
143 | 24 | select externalExpr, "$@ can be exposed to an external user.", errorInformation, "Error information"
|
0 commit comments