C++: Support the SAX2XMLReader interface.

This commit is contained in:
Geoffrey White
2022-05-03 17:56:27 +01:00
parent c4bc7050a9
commit 6b5a1921dd
3 changed files with 86 additions and 4 deletions

View File

@@ -64,6 +64,13 @@ class SAXParserClass extends Class {
SAXParserClass() { this.hasName("SAXParser") }
}
/**
* The `SAX2XMLReader` class.
*/
class SAX2XMLReader extends Class {
SAX2XMLReader() { this.hasName("SAX2XMLReader") }
}
/**
* Gets a valid flow state for `AbstractDOMParser` or `SAXParser` flow.
*
@@ -168,12 +175,57 @@ class CreateEntityReferenceNodesTranformer extends XXEFlowStateTranformer {
}
/**
* The `AbstractDOMParser.parse` or `SAXParser.parse` method.
* The `XMLUni.fgXercesDisableDefaultEntityResolution` constant.
*/
class FeatureDisableDefaultEntityResolution extends Variable {
FeatureDisableDefaultEntityResolution() {
this.getName() = "fgXercesDisableDefaultEntityResolution" and
this.getDeclaringType().getName() = "XMLUni"
}
}
/**
* A flow state transformer for a call to `SAX2XMLReader.setFeature(XMLUni::fgXercesDisableDefaultEntityResolution, *)`. Transforms the flow
* state through the qualifier according to this setting.
*/
class SetFeatureTranformer extends XXEFlowStateTranformer {
Expr newValue;
SetFeatureTranformer() {
exists(Call call, Function f |
call.getTarget() = f and
f.getDeclaringType() instanceof SAX2XMLReader and
f.hasName("setFeature") and
this = call.getQualifier() and
globalValueNumber(call.getArgument(0)).getAnExpr().(VariableAccess).getTarget() instanceof
FeatureDisableDefaultEntityResolution and
newValue = call.getArgument(1)
)
}
final override XXEFlowState transform(XXEFlowState flowstate) {
exists(int createEntityReferenceNodes |
encodeXercesFlowState(flowstate, _, createEntityReferenceNodes) and
(
globalValueNumber(newValue).getAnExpr().getValue().toInt() = 1 and // true
encodeXercesFlowState(result, 1, createEntityReferenceNodes)
or
not globalValueNumber(newValue).getAnExpr().getValue().toInt() = 1 and // false or unknown
encodeXercesFlowState(result, 0, createEntityReferenceNodes)
)
)
}
}
/**
* The `AbstractDOMParser.parse`, `SAXParser.parse` or `SAX2XMLReader.parse`
* method.
*/
class ParseFunction extends Function {
ParseFunction() {
this.getClassAndName("parse") instanceof AbstractDOMParserClass or
this.getClassAndName("parse") instanceof SAXParserClass
this.getClassAndName("parse") instanceof SAXParserClass or
this.getClassAndName("parse") instanceof SAX2XMLReader
}
}
@@ -188,6 +240,17 @@ class CreateLSParser extends Function {
}
}
/**
* The `createXMLReader` function that returns a newly created `SAX2XMLReader`
* object.
*/
class CreateXMLReader extends Function {
CreateXMLReader() {
this.hasName("createXMLReader") and
this.getUnspecifiedType().(PointerType).getBaseType() instanceof SAX2XMLReader // returns a `SAX2XMLReader *`.
}
}
/**
* A call to a `libxml2` function that parses XML.
*/
@@ -256,6 +319,13 @@ class XXEConfiguration extends DataFlow::Configuration {
encodeXercesFlowState(flowstate, 0, 1) // default configuration
)
or
// source is the result of a call to `createXMLReader`.
exists(Call call |
call.getTarget() instanceof CreateXMLReader and
call = node.asExpr() and
encodeXercesFlowState(flowstate, 0, 1) // default configuration
)
or
// source is an `options` argument on a `libxml2` parse call that specifies
// at least one unsafe option.
//

View File

@@ -1,6 +1,9 @@
edges
| tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p |
| tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p |
| tests3.cpp:23:21:23:53 | call to createXMLReader | tests3.cpp:25:2:25:2 | p |
| tests3.cpp:60:21:60:53 | call to createXMLReader | tests3.cpp:63:2:63:2 | p |
| tests3.cpp:67:21:67:53 | call to createXMLReader | tests3.cpp:70:2:70:2 | p |
| tests.cpp:15:23:15:43 | XercesDOMParser output argument | tests.cpp:17:2:17:2 | p |
| tests.cpp:28:23:28:43 | XercesDOMParser output argument | tests.cpp:31:2:31:2 | p |
| tests.cpp:35:19:35:19 | VariableAddress [post update] | tests.cpp:37:2:37:2 | p |
@@ -32,6 +35,12 @@ nodes
| tests2.cpp:22:2:22:2 | p | semmle.label | p |
| tests2.cpp:33:17:33:31 | SAXParser output argument | semmle.label | SAXParser output argument |
| tests2.cpp:37:2:37:2 | p | semmle.label | p |
| tests3.cpp:23:21:23:53 | call to createXMLReader | semmle.label | call to createXMLReader |
| tests3.cpp:25:2:25:2 | p | semmle.label | p |
| tests3.cpp:60:21:60:53 | call to createXMLReader | semmle.label | call to createXMLReader |
| tests3.cpp:63:2:63:2 | p | semmle.label | p |
| tests3.cpp:67:21:67:53 | call to createXMLReader | semmle.label | call to createXMLReader |
| tests3.cpp:70:2:70:2 | p | semmle.label | p |
| tests4.cpp:26:34:26:48 | (int)... | semmle.label | (int)... |
| tests4.cpp:36:34:36:50 | (int)... | semmle.label | (int)... |
| tests4.cpp:46:34:46:68 | ... \| ... | semmle.label | ... \| ... |
@@ -76,6 +85,9 @@ subpaths
#select
| tests2.cpp:22:2:22:2 | p | tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:20:17:20:31 | SAXParser output argument | XML parser |
| tests2.cpp:37:2:37:2 | p | tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:33:17:33:31 | SAXParser output argument | XML parser |
| tests3.cpp:25:2:25:2 | p | tests3.cpp:23:21:23:53 | call to createXMLReader | tests3.cpp:25:2:25:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:23:21:23:53 | call to createXMLReader | XML parser |
| tests3.cpp:63:2:63:2 | p | tests3.cpp:60:21:60:53 | call to createXMLReader | tests3.cpp:63:2:63:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:60:21:60:53 | call to createXMLReader | XML parser |
| tests3.cpp:70:2:70:2 | p | tests3.cpp:67:21:67:53 | call to createXMLReader | tests3.cpp:70:2:70:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:67:21:67:53 | call to createXMLReader | XML parser |
| tests4.cpp:26:34:26:48 | (int)... | tests4.cpp:26:34:26:48 | (int)... | tests4.cpp:26:34:26:48 | (int)... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:26:34:26:48 | (int)... | XML parser |
| tests4.cpp:36:34:36:50 | (int)... | tests4.cpp:36:34:36:50 | (int)... | tests4.cpp:36:34:36:50 | (int)... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:36:34:36:50 | (int)... | XML parser |
| tests4.cpp:46:34:46:68 | ... \| ... | tests4.cpp:46:34:46:68 | ... \| ... | tests4.cpp:46:34:46:68 | ... \| ... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:46:34:46:68 | ... \| ... | XML parser |

View File

@@ -60,14 +60,14 @@ void test3_6(InputSource &data) {
SAX2XMLReader *p = XMLReaderFactory::createXMLReader();
p->setFeature(XMLUni::fgXercesDisableDefaultEntityResolution, false);
p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
p->parse(data); // BAD (parser not correctly configured)
}
void test3_7(InputSource &data) {
SAX2XMLReader *p = XMLReaderFactory::createXMLReader();
p->setFeature(XMLUni::fgXercesHarmlessOption, true);
p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
p->parse(data); // BAD (parser not correctly configured)
}
void test3_8(InputSource &data) {