Skip to content

Commit af3c620

Browse files
authored
Merge pull request diffblue#563 from diffblue/add_test_xxe02
SEC-633: Added XXE regression test which uses XXE models library.
2 parents e9cdcca + f81878c commit af3c620

File tree

7 files changed

+188
-0
lines changed

7 files changed

+188
-0
lines changed

regression/end_to_end/xxe02/build.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<project name="Main" basedir="." default="compile">
2+
3+
<property name="root.dir" value="./"/>
4+
<property name="src.dir" value="${root.dir}/src"/>
5+
<property name="classes.dir" value="${root.dir}/build"/>
6+
7+
<target name="compile">
8+
<antcall target="clean" />
9+
<mkdir dir="${classes.dir}"/>
10+
<javac srcdir="${src.dir}" destdir="${classes.dir}" includeantruntime="false" debug="on" />
11+
</target>
12+
13+
<target name="clean">
14+
<delete dir="${classes.dir}"/>
15+
</target>
16+
17+
</project>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"namespace": "com.diffblue.security",
3+
"rules":
4+
[
5+
{
6+
"comment": "Obtaining tainted XML text.",
7+
"class": "xxe02.Main",
8+
"method": "make_tainted:(Ljava/lang/String;)Ljava/lang/String;",
9+
"result": {
10+
"location": "returns",
11+
"taint": "Tainted XML text"
12+
}
13+
},
14+
{
15+
"comment": "Obtaining tainted string reader from tainted XML text.",
16+
"class": "java.io.StringReader",
17+
"method": "<init>:(Ljava/lang/String;)V",
18+
"input": {
19+
"location": "arg1",
20+
"taint": "Tainted XML text"
21+
},
22+
"result": {
23+
"location": "this",
24+
"taint": "Tainted reader"
25+
}
26+
},
27+
{
28+
"comment": "Obtaining XML stream reader with external entities enabled for tainted XML text.",
29+
"class": "javax.xml.stream.DIFFBLUEXMLInputFactory",
30+
"method": "createXXEVulnerableXMLStreamReader:(Ljava/io/Reader;)Ljavax/xml/stream/XMLStreamReader;",
31+
"input": {
32+
"location": "arg1",
33+
"taint": "Tainted reader"
34+
},
35+
"result": {
36+
"location": "returns",
37+
"taint": "Reader of tainted XML with external entities enabled"
38+
}
39+
},
40+
{
41+
"comment": "Unmarshalling an object by reading tainted XML document with external entities enabled.",
42+
"class": "xxe02.Unmarshaller",
43+
"method": "unmarshal:(Ljavax/xml/stream/XMLStreamReader;)Ljava/lang/Object;",
44+
"sinkTarget": {
45+
"location": "arg1",
46+
"vulnerability": "Reader of tainted XML with external entities enabled"
47+
},
48+
"message": "Unmarshalling an object by reading tainted XML document with external entities enabled."
49+
}
50+
]
51+
}
52+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package xxe02;
2+
3+
4+
class JAXBContext {
5+
public static JAXBContext newInstance(String s) {
6+
return new JAXBContext();
7+
}
8+
9+
public Unmarshaller createUnmarshaller() {
10+
return new Unmarshaller();
11+
}
12+
}
13+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package xxe02;
2+
import java.io.StringReader;
3+
import javax.xml.stream.XMLInputFactory;
4+
import javax.xml.stream.XMLStreamReader;
5+
6+
7+
public class Main {
8+
9+
private static String make_tainted(String s) {
10+
return s;
11+
}
12+
13+
public static void no_xxe_issue(String input) {
14+
String xml_from_attacker = make_tainted(input);
15+
16+
try {
17+
JAXBContext jc = JAXBContext.newInstance("xxe02.MyClass");
18+
XMLInputFactory xif = XMLInputFactory.newFactory();
19+
xif.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
20+
XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(xml_from_attacker));
21+
Unmarshaller unmarshaller = jc.createUnmarshaller();
22+
MyClass myClass = (MyClass)unmarshaller.unmarshal(xsr);
23+
} catch (Exception e) {
24+
}
25+
}
26+
27+
public static void xxe_issue(String input) {
28+
String xml_from_attacker = make_tainted(input);
29+
30+
try {
31+
JAXBContext jc = JAXBContext.newInstance("xxe02.MyClass");
32+
XMLInputFactory xif = XMLInputFactory.newFactory();
33+
xif.setProperty("javax.xml.stream.isSupportingExternalEntities", true);
34+
XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(xml_from_attacker));
35+
Unmarshaller unmarshaller = jc.createUnmarshaller();
36+
MyClass myClass = (MyClass)unmarshaller.unmarshal(xsr);
37+
} catch (Exception e) {
38+
}
39+
}
40+
41+
public static void main(String[] args) {
42+
if (args.length < 1)
43+
return;
44+
45+
String xml_from_attacker = make_tainted(args[0]);
46+
47+
no_xxe_issue(xml_from_attacker);
48+
xxe_issue(xml_from_attacker);
49+
}
50+
}
51+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package xxe02;
2+
3+
4+
// This is user's class to be unmarshaled from XML data.
5+
class MyClass {
6+
}
7+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package xxe02;
2+
3+
4+
class Unmarshaller {
5+
public Object unmarshal(javax.xml.stream.XMLStreamReader xsr) {
6+
return new MyClass();
7+
}
8+
}
9+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import fasteners
2+
import os
3+
import subprocess
4+
import pytest
5+
6+
from regression.end_to_end.driver import run_security_analyser_pipeline
7+
import regression.utils as utils
8+
9+
10+
@pytest.mark.xfail(strict=True)
11+
@fasteners.interprocess_locked(os.path.join(os.path.dirname(__file__), ".build_lock"))
12+
def test_xxe02_no_xxe_issue(load_strategy):
13+
with utils.working_dir(os.path.abspath(os.path.dirname(__file__))):
14+
subprocess.call(["ant"])
15+
with run_security_analyser_pipeline(
16+
"build",
17+
"rules.json",
18+
os.path.realpath(os.path.dirname(__file__)),
19+
"xxe02.Main.no_xxe_issue",
20+
load_strategy,
21+
extra_args=["--use-xxe-models-library"]) as traces:
22+
assert traces.count_traces() == 0
23+
24+
25+
@fasteners.interprocess_locked(os.path.join(os.path.dirname(__file__), ".build_lock"))
26+
def test_xxe02_xxe_issue(load_strategy):
27+
with utils.working_dir(os.path.abspath(os.path.dirname(__file__))):
28+
subprocess.call(["ant"])
29+
with run_security_analyser_pipeline(
30+
"build",
31+
"rules.json",
32+
os.path.realpath(os.path.dirname(__file__)),
33+
"xxe02.Main.xxe_issue",
34+
load_strategy,
35+
extra_args=["--use-xxe-models-library"]) as traces:
36+
assert traces.count_traces() == 1
37+
assert traces.trace_exists(
38+
"java::xxe02.Main.xxe_issue:(Ljava/lang/String;)V", 36)
39+

0 commit comments

Comments
 (0)