mirror of
https://github.com/github/codeql.git
synced 2026-04-26 17:25:19 +02:00
XXE query
This commit is contained in:
55
ql/src/queries/security/cwe-611/Xxe.qhelp
Normal file
55
ql/src/queries/security/cwe-611/Xxe.qhelp
Normal file
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Parsing untrusted XML files with a weakly configured XML parser may lead to an
|
||||
XML External Entity (XXE) attack. This type of attack uses external entity references
|
||||
to access arbitrary files on a system, carry out denial-of-service (DoS) attacks, or server-side
|
||||
request forgery. Even when the result of parsing is not returned to the user, DoS attacks are still possible
|
||||
and out-of-band data retrieval techniques may allow attackers to steal sensitive data.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
The easiest way to prevent XXE attacks is to disable external entity handling when
|
||||
parsing untrusted data. How this is done depends on the library being used. Note that some
|
||||
libraries, such as <code>rexml</code>, <code>nokogiri</code> and <code>libxml-ruby</code>,
|
||||
disable entity expansion by default, so unless you have explicitly enabled entity expansion,
|
||||
no further action needs to be taken.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example uses the <code>nokogiri</code> XML parser to parse a string <code>xmlSrc</code>.
|
||||
If that string is from an untrusted source, this code may be vulnerable to an XXE attack, since
|
||||
the parser is invoked with the <code>noent</code> option set:
|
||||
</p>
|
||||
<sample src="examples/Xxe.rb"/>
|
||||
|
||||
<p>
|
||||
To guard against XXE attacks, the <code>noent</code> option should be omitted or cleared
|
||||
(e.g. using <code>nonoent</code>). This means that no entity expansion is undertaken at all,
|
||||
not even for standard internal entities such as <code>&amp;</code> or <code>&gt;</code>.
|
||||
If desired, these entities can be expanded in a separate step using utility functions.
|
||||
</p>
|
||||
<sample src="examples/XxeGood.rb"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing">XML External Entity (XXE) Processing</a>.
|
||||
</li>
|
||||
<li>
|
||||
Timothy Morgen:
|
||||
<a href="https://research.nccgroup.com/2014/05/19/xml-schema-dtd-and-entity-attacks-a-compendium-of-known-techniques/">XML Schema, DTD, and Entity Attacks</a>.
|
||||
</li>
|
||||
<li>
|
||||
Timur Yunusov, Alexey Osipov:
|
||||
<a href="https://www.slideshare.net/qqlan/bh-ready-v4">XML Out-Of-Band Data Retrieval</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
43
ql/src/queries/security/cwe-611/Xxe.ql
Normal file
43
ql/src/queries/security/cwe-611/Xxe.ql
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @name XML external entity expansion
|
||||
* @description Parsing user input as an XML document with external
|
||||
* entity expansion is vulnerable to XXE attacks.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.1
|
||||
* @precision high
|
||||
* @id rb/xxe
|
||||
* @tags security
|
||||
* external/cwe/cwe-611
|
||||
* external/cwe/cwe-776
|
||||
* external/cwe/cwe-827
|
||||
*/
|
||||
|
||||
import ruby
|
||||
import codeql.ruby.dataflow.RemoteFlowSources
|
||||
import codeql.ruby.TaintTracking
|
||||
import codeql.ruby.Concepts
|
||||
import codeql.ruby.DataFlow
|
||||
import DataFlow::PathGraph
|
||||
|
||||
class UnsafeXxeSink extends DataFlow::ExprNode {
|
||||
UnsafeXxeSink() {
|
||||
exists(XmlParserCall parse |
|
||||
parse.getInput() = this and
|
||||
parse.externalEntitiesEnabled()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class XxeConfig extends TaintTracking::Configuration {
|
||||
XxeConfig() { this = "XXE.ql::XxeConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeXxeSink }
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, XxeConfig conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "Unsafe parsing of XML file from $@.", source.getNode(),
|
||||
"user input"
|
||||
12
ql/src/queries/security/cwe-611/examples/Xxe.rb
Normal file
12
ql/src/queries/security/cwe-611/examples/Xxe.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
require "nokogiri"
|
||||
|
||||
def process_data1
|
||||
xmlSrc = request.body
|
||||
doc = Nokogiri::XML.parse(xmlSrc, nil, nil, Nokogiri::XML::ParseOptions::NOENT) # BAD
|
||||
end
|
||||
|
||||
def process_data2
|
||||
xmlSrc = request.body
|
||||
doc = Nokogiri::XML.parse(xmlSrc) { |config| config.noent } # BAD
|
||||
end
|
||||
|
||||
12
ql/src/queries/security/cwe-611/examples/XxeGood.rb
Normal file
12
ql/src/queries/security/cwe-611/examples/XxeGood.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
require "nokogiri"
|
||||
|
||||
def process_data1
|
||||
xmlSrc = request.body
|
||||
doc = Nokogiri::XML.parse(xmlSrc) # GOOD
|
||||
end
|
||||
|
||||
def process_data2
|
||||
xmlSrc = request.body
|
||||
doc = Nokogiri::XML.parse(xmlSrc) { |config| config.nonoent } # GOOD
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user