3
3
import java
4
4
import semmle.code.java.dataflow.DataFlow
5
5
import semmle.code.java.dataflow.ExternalFlow
6
- import semmle.code.java.security.XmlParsers
7
6
8
7
/**
9
8
* A data flow sink for unvalidated user input that is used in XSLT transformation.
@@ -51,7 +50,6 @@ private class DefaultXsltInjectionAdditionalTaintStep extends XsltInjectionAddit
51
50
staxSourceStep ( node1 , node2 ) or
52
51
documentBuilderStep ( node1 , node2 ) or
53
52
domSourceStep ( node1 , node2 ) or
54
- newTransformerOrTemplatesStep ( node1 , node2 ) or
55
53
newTransformerFromTemplatesStep ( node1 , node2 ) or
56
54
xsltCompilerStep ( node1 , node2 ) or
57
55
xsltExecutableStep ( node1 , node2 ) or
@@ -65,7 +63,10 @@ private class DefaultXsltInjectionAdditionalTaintStep extends XsltInjectionAddit
65
63
*/
66
64
private predicate xmlStreamReaderStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
67
65
exists ( XmlInputFactoryStreamReader xmlStreamReader |
68
- n1 .asExpr ( ) = xmlStreamReader .getSink ( ) and
66
+ if xmlStreamReader .getMethod ( ) .getParameterType ( 0 ) instanceof TypeString
67
+ then n1 .asExpr ( ) = xmlStreamReader .getArgument ( 1 )
68
+ else n1 .asExpr ( ) = xmlStreamReader .getArgument ( 0 )
69
+ |
69
70
n2 .asExpr ( ) = xmlStreamReader
70
71
)
71
72
}
@@ -76,7 +77,10 @@ private predicate xmlStreamReaderStep(DataFlow::Node n1, DataFlow::Node n2) {
76
77
*/
77
78
private predicate xmlEventReaderStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
78
79
exists ( XmlInputFactoryEventReader xmlEventReader |
79
- n1 .asExpr ( ) = xmlEventReader .getSink ( ) and
80
+ if xmlEventReader .getMethod ( ) .getParameterType ( 0 ) instanceof TypeString
81
+ then n1 .asExpr ( ) = xmlEventReader .getArgument ( 1 )
82
+ else n1 .asExpr ( ) = xmlEventReader .getArgument ( 0 )
83
+ |
80
84
n2 .asExpr ( ) = xmlEventReader
81
85
)
82
86
}
@@ -98,7 +102,7 @@ private predicate staxSourceStep(DataFlow::Node n1, DataFlow::Node n2) {
98
102
*/
99
103
private predicate documentBuilderStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
100
104
exists ( DocumentBuilderParse documentBuilder |
101
- n1 .asExpr ( ) = documentBuilder .getSink ( ) and
105
+ n1 .asExpr ( ) = documentBuilder .getArgument ( 0 ) and
102
106
n2 .asExpr ( ) = documentBuilder
103
107
)
104
108
}
@@ -114,60 +118,6 @@ private predicate domSourceStep(DataFlow::Node n1, DataFlow::Node n2) {
114
118
)
115
119
}
116
120
117
- /**
118
- * Holds if `n1` to `n2` is a dataflow step that converts between `Source` and `Transformer` or
119
- * `Templates`, i.e. `TransformerFactory.newTransformer(tainted)` or
120
- * `TransformerFactory.newTemplates(tainted)`.
121
- */
122
- private predicate newTransformerOrTemplatesStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
123
- exists ( MethodAccess ma , Method m | ma .getMethod ( ) = m |
124
- n1 .asExpr ( ) = ma .getAnArgument ( ) and
125
- n2 .asExpr ( ) = ma and
126
- m .getDeclaringType ( ) instanceof TransformerFactory and
127
- m .hasName ( [ "newTransformer" , "newTemplates" ] ) and
128
- not exists ( TransformerFactoryWithSecureProcessingFeatureFlowConfig conf |
129
- conf .hasFlowToExpr ( ma .getQualifier ( ) )
130
- )
131
- )
132
- }
133
-
134
- /**
135
- * A data flow configuration for secure processing feature that is enabled on `TransformerFactory`.
136
- */
137
- private class TransformerFactoryWithSecureProcessingFeatureFlowConfig extends DataFlow2:: Configuration {
138
- TransformerFactoryWithSecureProcessingFeatureFlowConfig ( ) {
139
- this = "TransformerFactoryWithSecureProcessingFeatureFlowConfig"
140
- }
141
-
142
- override predicate isSource ( DataFlow:: Node src ) {
143
- exists ( Variable v | v = src .asExpr ( ) .( VarAccess ) .getVariable ( ) |
144
- exists ( TransformerFactoryFeatureConfig config | config .getQualifier ( ) = v .getAnAccess ( ) |
145
- config .enables ( configSecureProcessing ( ) )
146
- )
147
- )
148
- }
149
-
150
- override predicate isSink ( DataFlow:: Node sink ) {
151
- exists ( MethodAccess ma |
152
- sink .asExpr ( ) = ma .getQualifier ( ) and
153
- ma .getMethod ( ) .getDeclaringType ( ) instanceof TransformerFactory
154
- )
155
- }
156
-
157
- override int fieldFlowBranchLimit ( ) { result = 0 }
158
- }
159
-
160
- /** A `ParserConfig` specific to `TransformerFactory`. */
161
- private class TransformerFactoryFeatureConfig extends ParserConfig {
162
- TransformerFactoryFeatureConfig ( ) {
163
- exists ( Method m |
164
- m = this .getMethod ( ) and
165
- m .getDeclaringType ( ) instanceof TransformerFactory and
166
- m .hasName ( "setFeature" )
167
- )
168
- }
169
- }
170
-
171
121
/**
172
122
* Holds if `n1` to `n2` is a dataflow step that converts between `Templates` and `Transformer`,
173
123
* i.e. `tainted.newTransformer()`.
@@ -252,3 +202,47 @@ private class TypeXsltExecutable extends Class {
252
202
private class TypeXsltPackage extends Class {
253
203
TypeXsltPackage ( ) { this .hasQualifiedName ( "net.sf.saxon.s9api" , "XsltPackage" ) }
254
204
}
205
+
206
+ // XmlParsers classes
207
+ /** A call to `DocumentBuilder.parse`. */
208
+ private class DocumentBuilderParse extends MethodAccess {
209
+ DocumentBuilderParse ( ) {
210
+ exists ( Method m |
211
+ this .getMethod ( ) = m and
212
+ m .getDeclaringType ( ) instanceof DocumentBuilder and
213
+ m .hasName ( "parse" )
214
+ )
215
+ }
216
+ }
217
+
218
+ /** The class `javax.xml.parsers.DocumentBuilder`. */
219
+ private class DocumentBuilder extends RefType {
220
+ DocumentBuilder ( ) { this .hasQualifiedName ( "javax.xml.parsers" , "DocumentBuilder" ) }
221
+ }
222
+
223
+ /** A call to `XMLInputFactory.createXMLStreamReader`. */
224
+ private class XmlInputFactoryStreamReader extends MethodAccess {
225
+ XmlInputFactoryStreamReader ( ) {
226
+ exists ( Method m |
227
+ this .getMethod ( ) = m and
228
+ m .getDeclaringType ( ) instanceof XmlInputFactory and
229
+ m .hasName ( "createXMLStreamReader" )
230
+ )
231
+ }
232
+ }
233
+
234
+ /** A call to `XMLInputFactory.createEventReader`. */
235
+ private class XmlInputFactoryEventReader extends MethodAccess {
236
+ XmlInputFactoryEventReader ( ) {
237
+ exists ( Method m |
238
+ this .getMethod ( ) = m and
239
+ m .getDeclaringType ( ) instanceof XmlInputFactory and
240
+ m .hasName ( "createXMLEventReader" )
241
+ )
242
+ }
243
+ }
244
+
245
+ /** The class `javax.xml.stream.XMLInputFactory`. */
246
+ private class XmlInputFactory extends RefType {
247
+ XmlInputFactory ( ) { this .hasQualifiedName ( "javax.xml.stream" , "XMLInputFactory" ) }
248
+ }
0 commit comments