Skip to content

Commit b2769b4

Browse files
authored
Merge pull request github#3117 from adityasharad/java/jackson-taint-steps
Java: Add taint steps through Jackson serialization methods.
2 parents 57c9277 + a6e039b commit b2769b4

File tree

10 files changed

+220
-0
lines changed

10 files changed

+220
-0
lines changed

java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ private import semmle.code.java.frameworks.Guice
1010
private import semmle.code.java.frameworks.Protobuf
1111
private import semmle.code.java.Maps
1212
private import semmle.code.java.dataflow.internal.ContainerFlow
13+
private import semmle.code.java.frameworks.jackson.JacksonSerializability
1314

1415
/**
1516
* Holds if taint can flow from `src` to `sink` in zero or more
@@ -491,6 +492,11 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) {
491492
or
492493
exists(ProtobufMessageLite m | method = m.getAParseFromMethod()) and
493494
arg = 0
495+
or
496+
// Jackson serialization methods that return the serialized data
497+
method instanceof JacksonWriteValueMethod and
498+
method.getNumberOfParameters() = 1 and
499+
arg = 0
494500
}
495501

496502
/**
@@ -537,6 +543,12 @@ private predicate taintPreservingArgToArg(Method method, int input, int output)
537543
method.hasName("arraycopy") and
538544
input = 0 and
539545
output = 2
546+
or
547+
// Jackson serialization methods that write data to the first argument
548+
method instanceof JacksonWriteValueMethod and
549+
method.getNumberOfParameters() > 1 and
550+
input = method.getNumberOfParameters() - 1 and
551+
output = 0
540552
}
541553

542554
/**
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import java.io.File;
2+
import java.io.FileOutputStream;
3+
import java.io.OutputStream;
4+
import java.io.StringWriter;
5+
import java.io.Writer;
6+
7+
import com.fasterxml.jackson.core.JsonFactory;
8+
import com.fasterxml.jackson.core.JsonGenerator;
9+
import com.fasterxml.jackson.databind.ObjectMapper;
10+
import com.fasterxml.jackson.databind.ObjectWriter;
11+
12+
class Test {
13+
public static String taint() {
14+
return "tainted";
15+
}
16+
17+
public static void jacksonObjectMapper() {
18+
String s = taint();
19+
ObjectMapper om = new ObjectMapper();
20+
File file = new File("testFile");
21+
om.writeValue(file, s);
22+
OutputStream out = new FileOutputStream(file);
23+
om.writeValue(out, s);
24+
Writer writer = new StringWriter();
25+
om.writeValue(writer, s);
26+
JsonGenerator generator = new JsonFactory().createGenerator(new StringWriter());
27+
om.writeValue(generator, s);
28+
String t = om.writeValueAsString(s);
29+
System.out.println(t);
30+
byte[] bs = om.writeValueAsBytes(s);
31+
String reconstructed = new String(bs, "utf-8");
32+
System.out.println(reconstructed);
33+
}
34+
35+
public static void jacksonObjectWriter() {
36+
String s = taint();
37+
ObjectWriter ow = new ObjectWriter();
38+
File file = new File("testFile");
39+
ow.writeValue(file, s);
40+
OutputStream out = new FileOutputStream(file);
41+
ow.writeValue(out, s);
42+
Writer writer = new StringWriter();
43+
ow.writeValue(writer, s);
44+
JsonGenerator generator = new JsonFactory().createGenerator(new StringWriter());
45+
ow.writeValue(generator, s);
46+
String t = ow.writeValueAsString(s);
47+
System.out.println(t);
48+
byte[] bs = ow.writeValueAsBytes(s);
49+
String reconstructed = new String(bs, "utf-8");
50+
System.out.println(reconstructed);
51+
}
52+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:10:43:10:54 | value |
2+
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:13:73:13:84 | value |
3+
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:16:44:16:55 | value |
4+
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:19:36:19:47 | value |
5+
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:22:35:22:46 | value |
6+
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:26:36:26:47 | value |
7+
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:10:43:10:54 | value |
8+
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:13:73:13:84 | value |
9+
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:16:44:16:55 | value |
10+
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:19:36:19:47 | value |
11+
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:22:35:22:46 | value |
12+
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:26:36:26:47 | value |
13+
| Test.java:18:14:18:20 | taint(...) |
14+
| Test.java:21:17:21:20 | file [post update] |
15+
| Test.java:21:23:21:23 | s |
16+
| Test.java:22:43:22:46 | file |
17+
| Test.java:23:17:23:19 | out [post update] |
18+
| Test.java:23:22:23:22 | s |
19+
| Test.java:25:17:25:22 | writer [post update] |
20+
| Test.java:25:25:25:25 | s |
21+
| Test.java:27:17:27:25 | generator [post update] |
22+
| Test.java:27:28:27:28 | s |
23+
| Test.java:28:14:28:37 | writeValueAsString(...) |
24+
| Test.java:28:36:28:36 | s |
25+
| Test.java:29:22:29:22 | t |
26+
| Test.java:30:15:30:37 | writeValueAsBytes(...) |
27+
| Test.java:30:36:30:36 | s |
28+
| Test.java:31:26:31:48 | new String(...) |
29+
| Test.java:31:37:31:38 | bs |
30+
| Test.java:32:22:32:34 | reconstructed |
31+
| Test.java:36:14:36:20 | taint(...) |
32+
| Test.java:39:17:39:20 | file [post update] |
33+
| Test.java:39:23:39:23 | s |
34+
| Test.java:40:43:40:46 | file |
35+
| Test.java:41:17:41:19 | out [post update] |
36+
| Test.java:41:22:41:22 | s |
37+
| Test.java:43:17:43:22 | writer [post update] |
38+
| Test.java:43:25:43:25 | s |
39+
| Test.java:45:17:45:25 | generator [post update] |
40+
| Test.java:45:28:45:28 | s |
41+
| Test.java:46:14:46:37 | writeValueAsString(...) |
42+
| Test.java:46:36:46:36 | s |
43+
| Test.java:47:22:47:22 | t |
44+
| Test.java:48:15:48:37 | writeValueAsBytes(...) |
45+
| Test.java:48:36:48:36 | s |
46+
| Test.java:49:26:49:48 | new String(...) |
47+
| Test.java:49:37:49:38 | bs |
48+
| Test.java:50:22:50:34 | reconstructed |
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import semmle.code.java.dataflow.DataFlow
2+
import semmle.code.java.dataflow.TaintTracking
3+
import semmle.code.java.dataflow.FlowSources
4+
5+
class Conf extends TaintTracking::Configuration {
6+
Conf() { this = "qltest:dataflow:jackson" }
7+
8+
override predicate isSource(DataFlow::Node source) {
9+
source.asExpr().(MethodAccess).getMethod().hasName("taint")
10+
}
11+
12+
override predicate isSink(DataFlow::Node sink) { any() }
13+
}
14+
15+
from DataFlow::Node source, DataFlow::Node sink, Conf config
16+
where config.hasFlow(source, sink)
17+
select sink
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/jackson-databind-2.10
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.fasterxml.jackson.core;
2+
3+
import java.io.Writer;
4+
5+
public class JsonFactory {
6+
public JsonFactory() {
7+
}
8+
9+
public JsonGenerator createGenerator(Writer writer) {
10+
return new JsonGenerator();
11+
}
12+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.fasterxml.jackson.core;
2+
3+
public class JsonGenerator {
4+
protected JsonGenerator() {
5+
}
6+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.fasterxml.jackson.databind;
2+
3+
import java.io.*;
4+
import java.util.*;
5+
6+
public class ObjectMapper {
7+
public ObjectMapper() {
8+
}
9+
10+
public void writeValue(File resultFile, Object value) {
11+
}
12+
13+
public void writeValue(com.fasterxml.jackson.core.JsonGenerator jgen, Object value) {
14+
}
15+
16+
public void writeValue(OutputStream out, Object value) {
17+
}
18+
19+
public void writeValue(Writer w, Object value) {
20+
}
21+
22+
public byte[] writeValueAsBytes(Object value) {
23+
return null;
24+
}
25+
26+
public String writeValueAsString(Object value) {
27+
return null;
28+
}
29+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.fasterxml.jackson.databind;
2+
3+
import java.io.*;
4+
import java.util.*;
5+
6+
public class ObjectWriter {
7+
public ObjectWriter() {
8+
}
9+
10+
public void writeValue(File resultFile, Object value) {
11+
}
12+
13+
public void writeValue(com.fasterxml.jackson.core.JsonGenerator jgen, Object value) {
14+
}
15+
16+
public void writeValue(OutputStream out, Object value) {
17+
}
18+
19+
public void writeValue(Writer w, Object value) {
20+
}
21+
22+
public byte[] writeValueAsBytes(Object value) {
23+
return null;
24+
}
25+
26+
public String writeValueAsString(Object value) {
27+
return null;
28+
}
29+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Licensed to the Apache Software Foundation (ASF) under one or more
2+
contributor license agreements. See the NOTICE file distributed with
3+
this work for additional information regarding copyright ownership.
4+
The ASF licenses this file to You under the Apache License, Version 2.0
5+
(the "License"); you may not use this file except in compliance with
6+
the License. You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.

0 commit comments

Comments
 (0)