Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 69 additions & 3 deletions cpp/ql/src/Security/CWE/CWE-611/XXE.ql
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ class XercesDOMParserClass extends Class {
XercesDOMParserClass() { this.hasName("XercesDOMParser") }
}

/**
* The `DOMLSParser` class.
*/
class DomLSParserClass extends Class {
DomLSParserClass() { this.hasName("DOMLSParser") }
}

/**
* The `SAXParser` class.
*/
Expand Down Expand Up @@ -217,12 +224,71 @@ class SetFeatureTranformer extends XXEFlowStateTranformer {
}

/**
* The `AbstractDOMParser.parse`, `SAXParser.parse` or `SAX2XMLReader.parse`
* method.
* The `DOMLSParser.getDomConfig` function.
*/
class GetDomConfig extends Function {
GetDomConfig() { this.getClassAndName("getDomConfig") instanceof DomLSParserClass }
}

/**
* The `DOMConfiguration.setParameter` function.
*/
class DomConfigurationSetParameter extends Function {
DomConfigurationSetParameter() {
this.getClassAndName("setParameter").getName() = "DOMConfiguration"
}
}

/**
* A flow state transformer for a call to `DOMConfiguration.setParameter`
* specifying the feature `XMLUni::fgXercesDisableDefaultEntityResolution`.
* This is a slightly more complex transformer because the qualifier is a
* `DOMConfiguration` pointer returned by `DOMLSParser.getDomConfig` - and it
* is *that* qualifier we want to transform the flow state of.
*/
class DomConfigurationSetParameterTranformer extends XXEFlowStateTranformer {
Expr newValue;

DomConfigurationSetParameterTranformer() {
exists(FunctionCall getDomConfigCall, FunctionCall setParameterCall |
// this is the qualifier of a call to `DOMLSParser.getDomConfig`.
getDomConfigCall.getTarget() instanceof GetDomConfig and
this = getDomConfigCall.getQualifier() and
// `setParameterCall` is a call to `setParameter` on the return value of
// the same call to `DOMLSParser.getDomConfig`.
setParameterCall.getTarget() instanceof DomConfigurationSetParameter and
globalValueNumber(setParameterCall.getQualifier()).getAnExpr() = getDomConfigCall and
// the parameter being set is
// `XMLUni::fgXercesDisableDefaultEntityResolution`.
globalValueNumber(setParameterCall.getArgument(0)).getAnExpr().(VariableAccess).getTarget()
instanceof FeatureDisableDefaultEntityResolution and
// the value being set is `newValue`.
newValue = setParameterCall.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`, `DOMLSParserClass.parse`, `SAXParser.parse`
* or `SAX2XMLReader.parse` method.
*/
class ParseFunction extends Function {
ParseFunction() {
this.getClassAndName("parse") instanceof AbstractDOMParserClass or
this.getClassAndName("parse") instanceof DomLSParserClass or
this.getClassAndName("parse") instanceof SaxParserClass or
this.getClassAndName("parse") instanceof Sax2XmlReader
}
Expand All @@ -235,7 +301,7 @@ class ParseFunction extends Function {
class CreateLSParser extends Function {
CreateLSParser() {
this.hasName("createLSParser") and
this.getUnspecifiedType().(PointerType).getBaseType().getName() = "DOMLSParser" // returns a `DOMLSParser *`.
this.getUnspecifiedType().(PointerType).getBaseType() instanceof DomLSParserClass // returns a `DOMLSParser *`.
}
}

Expand Down
27 changes: 27 additions & 0 deletions cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ edges
| 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 |
| tests5.cpp:27:25:27:38 | call to createLSParser | tests5.cpp:29:2:29:2 | p |
| tests5.cpp:40:25:40:38 | call to createLSParser | tests5.cpp:43:2:43:2 | p |
| tests5.cpp:55:25:55:38 | call to createLSParser | tests5.cpp:59:2:59:2 | p |
| tests5.cpp:81:25:81:38 | call to createLSParser | tests5.cpp:83:2:83:2 | p |
| tests5.cpp:81:25:81:38 | call to createLSParser | tests5.cpp:83:2:83:2 | p |
| tests5.cpp:83:2:83:2 | p | tests5.cpp:85:2:85:2 | p |
| tests5.cpp:85:2:85:2 | p | tests5.cpp:86:2:86:2 | p |
| tests5.cpp:86:2:86:2 | p | tests5.cpp:88:2:88:2 | p |
| tests5.cpp:88:2:88:2 | p | tests5.cpp:89:2:89: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 |
Expand Down Expand Up @@ -46,6 +55,19 @@ nodes
| tests4.cpp:46:34:46:68 | ... \| ... | semmle.label | ... \| ... |
| tests4.cpp:77:34:77:38 | flags | semmle.label | flags |
| tests4.cpp:130:39:130:55 | (int)... | semmle.label | (int)... |
| tests5.cpp:27:25:27:38 | call to createLSParser | semmle.label | call to createLSParser |
| tests5.cpp:29:2:29:2 | p | semmle.label | p |
| tests5.cpp:40:25:40:38 | call to createLSParser | semmle.label | call to createLSParser |
| tests5.cpp:43:2:43:2 | p | semmle.label | p |
| tests5.cpp:55:25:55:38 | call to createLSParser | semmle.label | call to createLSParser |
| tests5.cpp:59:2:59:2 | p | semmle.label | p |
| tests5.cpp:81:25:81:38 | call to createLSParser | semmle.label | call to createLSParser |
| tests5.cpp:83:2:83:2 | p | semmle.label | p |
| tests5.cpp:83:2:83:2 | p | semmle.label | p |
| tests5.cpp:85:2:85:2 | p | semmle.label | p |
| tests5.cpp:86:2:86:2 | p | semmle.label | p |
| tests5.cpp:88:2:88:2 | p | semmle.label | p |
| tests5.cpp:89:2:89:2 | p | semmle.label | p |
| tests.cpp:15:23:15:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:17:2:17:2 | p | semmle.label | p |
| tests.cpp:28:23:28:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
Expand Down Expand Up @@ -93,6 +115,11 @@ subpaths
| 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 |
| tests4.cpp:77:34:77:38 | flags | tests4.cpp:77:34:77:38 | flags | tests4.cpp:77:34:77:38 | flags | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:77:34:77:38 | flags | XML parser |
| tests4.cpp:130:39:130:55 | (int)... | tests4.cpp:130:39:130:55 | (int)... | tests4.cpp:130:39:130:55 | (int)... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:130:39:130:55 | (int)... | XML parser |
| tests5.cpp:29:2:29:2 | p | tests5.cpp:27:25:27:38 | call to createLSParser | tests5.cpp:29:2:29:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:27:25:27:38 | call to createLSParser | XML parser |
| tests5.cpp:43:2:43:2 | p | tests5.cpp:40:25:40:38 | call to createLSParser | tests5.cpp:43:2:43:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:40:25:40:38 | call to createLSParser | XML parser |
| tests5.cpp:59:2:59:2 | p | tests5.cpp:55:25:55:38 | call to createLSParser | tests5.cpp:59:2:59:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:55:25:55:38 | call to createLSParser | XML parser |
| tests5.cpp:83:2:83:2 | p | tests5.cpp:81:25:81:38 | call to createLSParser | tests5.cpp:83:2:83:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:81:25:81:38 | call to createLSParser | XML parser |
| tests5.cpp:89:2:89:2 | p | tests5.cpp:81:25:81:38 | call to createLSParser | tests5.cpp:89:2:89:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:81:25:81:38 | call to createLSParser | XML parser |
| tests.cpp:17:2:17:2 | p | tests.cpp:15:23:15:43 | XercesDOMParser output argument | tests.cpp:17:2:17:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:15:23:15:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:31:2:31:2 | p | tests.cpp:28:23:28:43 | XercesDOMParser output argument | tests.cpp:31:2:31:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:28:23:28:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:39:2:39:2 | p | tests.cpp:35:23:35:43 | XercesDOMParser output argument | tests.cpp:39:2:39:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:35:23:35:43 | XercesDOMParser output argument | XML parser |
Expand Down
31 changes: 28 additions & 3 deletions cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class DOMImplementationLS {
void test5_1(DOMImplementationLS *impl, InputSource &data) {
DOMLSParser *p = impl->createLSParser();

p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
p->parse(data); // BAD (parser not correctly configured)
}

void test5_2(DOMImplementationLS *impl, InputSource &data) {
Expand All @@ -40,7 +40,7 @@ void test5_3(DOMImplementationLS *impl, InputSource &data) {
DOMLSParser *p = impl->createLSParser();

p->getDomConfig()->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, false);
p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
p->parse(data); // BAD (parser not correctly configured)
}

void test5_4(DOMImplementationLS *impl, InputSource &data) {
Expand All @@ -56,7 +56,7 @@ void test5_5(DOMImplementationLS *impl, InputSource &data) {
DOMConfiguration *cfg = p->getDomConfig();

cfg->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, false);
p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
p->parse(data); // BAD (parser not correctly configured)
}

DOMImplementationLS *g_impl;
Expand All @@ -76,3 +76,28 @@ void test5_6() {
g_p1->parse(*g_data); // GOOD
g_p2->parse(*g_data); // BAD (parser not correctly configured) [NOT DETECTED]
}

void test5_7(DOMImplementationLS *impl, InputSource &data) {
DOMLSParser *p = impl->createLSParser();

p->parse(data); // BAD (parser not correctly configured)

p->getDomConfig()->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, true);
p->parse(data); // GOOD

p->getDomConfig()->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, false);
p->parse(data); // BAD (parser not correctly configured)
}

void test5_8(DOMImplementationLS *impl, InputSource &data) {
DOMLSParser *p = impl->createLSParser();
DOMConfiguration *cfg = p->getDomConfig();

p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]

cfg->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, true);
p->parse(data); // GOOD

cfg->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, false);
p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
}