Add XMLDocument sinks

This commit is contained in:
Tony Torralba
2022-11-04 12:31:59 +01:00
parent a21db3b3c2
commit c03eab2410
3 changed files with 111 additions and 2 deletions

View File

@@ -20,8 +20,8 @@ class XxeAdditionalTaintStep extends Unit {
}
/** The XML argument of a `XMLParser` vulnerable to XXE. */
private class DefaultXxeSink extends XxeSink {
DefaultXxeSink() {
private class XmlParserXxeSink extends XxeSink {
XmlParserXxeSink() {
this.asExpr() = any(Argument a | a.getApplyExpr() instanceof VulnerableParser).getExpr()
}
}
@@ -67,3 +67,26 @@ private class XmlParserRef extends Expr {
private class XmlParserType extends NominalType {
XmlParserType() { this.getFullName() = "XMLParser" }
}
/** The XML argument of a `XMLDocument` vulnerable to XXE. */
private class XmlDocumentXxeSink extends XxeSink {
XmlDocumentXxeSink() { this.asExpr() = any(VulnerableXmlDocument d).getArgument(0).getExpr() }
}
/** An `XMLDocument` that sets `nodeLoadExternalEntitiesAlways` in its options. */
private class VulnerableXmlDocument extends ApplyExpr {
VulnerableXmlDocument() {
this.getStaticTarget().(ConstructorDecl).getEnclosingDecl().(NominalTypeDecl).getFullName() =
"XMLDocument" and
this.getArgument(1).getExpr().(ArrayExpr).getAnElement().(MemberRefExpr).getMember() instanceof
NodeLoadExternalEntitiesAlways
}
}
/** The option `XMLNode.Options.nodeLoadExternalEntitiesAlways`. */
private class NodeLoadExternalEntitiesAlways extends VarDecl {
NodeLoadExternalEntitiesAlways() {
this.getName() = "nodeLoadExternalEntitiesAlways" and
this.getEnclosingDecl().(StructDecl).getFullName() = "XMLNode.Options"
}
}

View File

@@ -0,0 +1,86 @@
// --- stubs ---
class Data {
init<S>(_ elements: S) {}
}
struct URL {
init?(string: String) {}
}
extension String {
init(contentsOf: URL) {
let data = ""
self.init(data)
}
}
class XMLNode {
struct Options : OptionSet {
let rawValue: Int
static let nodeLoadExternalEntitiesAlways = XMLNode.Options(rawValue: 1 << 0)
static let nodeLoadExternalEntitiesNever = XMLNode.Options(rawValue: 1 << 1)
}
}
class XMLElement {}
class XMLDocument {
init(contentsOf: URL, options: XMLNode.Options = []) {}
init(data: Data, options: XMLNode.Options = []) {}
init(rootElement: XMLElement?) {}
init(xmlString: String, options: XMLNode.Options = []) {}
}
// --- tests ---
func testUrl() {
let remoteString = String(contentsOf: URL(string: "http://example.com/")!)
let remoteUrl = URL(string: remoteString)!
let _ = XMLDocument(contentsOf: remoteUrl, options: [.nodeLoadExternalEntitiesAlways]) // $ hasXXE=39
}
func testUrlSafeImplicit() {
let remoteString = String(contentsOf: URL(string: "http://example.com/")!)
let remoteUrl = URL(string: remoteString)!
let _ = XMLDocument(contentsOf: remoteUrl, options: []) // NO XXE: document doesn't enable external entities
}
func testUrlSafeExplicit() {
let remoteString = String(contentsOf: URL(string: "http://example.com/")!)
let remoteUrl = URL(string: remoteString)!
let _ = XMLDocument(contentsOf: remoteUrl, options: [.nodeLoadExternalEntitiesNever]) // NO XXE: document disables external entities
}
func testData() {
let remoteString = String(contentsOf: URL(string: "http://example.com/")!)
let remoteData = Data(remoteString)
let _ = XMLDocument(data: remoteData, options: [.nodeLoadExternalEntitiesAlways]) // $ hasXXE=57
}
func testDataSafeImplicit() {
let remoteString = String(contentsOf: URL(string: "http://example.com/")!)
let remoteData = Data(remoteString)
let _ = XMLDocument(data: remoteData, options: []) // NO XXE: document doesn't enable external entities
}
func testDataSafeExplicit() {
let remoteString = String(contentsOf: URL(string: "http://example.com/")!)
let remoteData = Data(remoteString)
let _ = XMLDocument(data: remoteData, options: [.nodeLoadExternalEntitiesNever]) // NO XXE: document disables external entities
}
func testString() {
let remoteString = String(contentsOf: URL(string: "http://example.com/")!)
let _ = XMLDocument(xmlString: remoteString, options: [.nodeLoadExternalEntitiesAlways]) // $ hasXXE=75
}
func testStringSafeImplicit() {
let remoteString = String(contentsOf: URL(string: "http://example.com/")!)
let _ = XMLDocument(xmlString: remoteString, options: []) // NO XXE: document doesn't enable external entities
}
func testStringSafeExplicit() {
let remoteString = String(contentsOf: URL(string: "http://example.com/")!)
let _ = XMLDocument(xmlString: remoteString, options: [.nodeLoadExternalEntitiesNever]) // NO XXE: document disables external entities
}