Merge pull request #3117 from adityasharad/java/jackson-taint-steps

Java: Add taint steps through Jackson serialization methods.
This commit is contained in:
Anders Schack-Mulligen
2020-03-30 10:34:56 +02:00
committed by GitHub
10 changed files with 220 additions and 0 deletions

View File

@@ -10,6 +10,7 @@ private import semmle.code.java.frameworks.Guice
private import semmle.code.java.frameworks.Protobuf
private import semmle.code.java.Maps
private import semmle.code.java.dataflow.internal.ContainerFlow
private import semmle.code.java.frameworks.jackson.JacksonSerializability
/**
* Holds if taint can flow from `src` to `sink` in zero or more
@@ -491,6 +492,11 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) {
or
exists(ProtobufMessageLite m | method = m.getAParseFromMethod()) and
arg = 0
or
// Jackson serialization methods that return the serialized data
method instanceof JacksonWriteValueMethod and
method.getNumberOfParameters() = 1 and
arg = 0
}
/**
@@ -537,6 +543,12 @@ private predicate taintPreservingArgToArg(Method method, int input, int output)
method.hasName("arraycopy") and
input = 0 and
output = 2
or
// Jackson serialization methods that write data to the first argument
method instanceof JacksonWriteValueMethod and
method.getNumberOfParameters() > 1 and
input = method.getNumberOfParameters() - 1 and
output = 0
}
/**

View File

@@ -0,0 +1,52 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.io.Writer;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
class Test {
public static String taint() {
return "tainted";
}
public static void jacksonObjectMapper() {
String s = taint();
ObjectMapper om = new ObjectMapper();
File file = new File("testFile");
om.writeValue(file, s);
OutputStream out = new FileOutputStream(file);
om.writeValue(out, s);
Writer writer = new StringWriter();
om.writeValue(writer, s);
JsonGenerator generator = new JsonFactory().createGenerator(new StringWriter());
om.writeValue(generator, s);
String t = om.writeValueAsString(s);
System.out.println(t);
byte[] bs = om.writeValueAsBytes(s);
String reconstructed = new String(bs, "utf-8");
System.out.println(reconstructed);
}
public static void jacksonObjectWriter() {
String s = taint();
ObjectWriter ow = new ObjectWriter();
File file = new File("testFile");
ow.writeValue(file, s);
OutputStream out = new FileOutputStream(file);
ow.writeValue(out, s);
Writer writer = new StringWriter();
ow.writeValue(writer, s);
JsonGenerator generator = new JsonFactory().createGenerator(new StringWriter());
ow.writeValue(generator, s);
String t = ow.writeValueAsString(s);
System.out.println(t);
byte[] bs = ow.writeValueAsBytes(s);
String reconstructed = new String(bs, "utf-8");
System.out.println(reconstructed);
}
}

View File

@@ -0,0 +1,48 @@
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:10:43:10:54 | value |
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:13:73:13:84 | value |
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:16:44:16:55 | value |
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:19:36:19:47 | value |
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:22:35:22:46 | value |
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:26:36:26:47 | value |
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:10:43:10:54 | value |
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:13:73:13:84 | value |
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:16:44:16:55 | value |
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:19:36:19:47 | value |
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:22:35:22:46 | value |
| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:26:36:26:47 | value |
| Test.java:18:14:18:20 | taint(...) |
| Test.java:21:17:21:20 | file [post update] |
| Test.java:21:23:21:23 | s |
| Test.java:22:43:22:46 | file |
| Test.java:23:17:23:19 | out [post update] |
| Test.java:23:22:23:22 | s |
| Test.java:25:17:25:22 | writer [post update] |
| Test.java:25:25:25:25 | s |
| Test.java:27:17:27:25 | generator [post update] |
| Test.java:27:28:27:28 | s |
| Test.java:28:14:28:37 | writeValueAsString(...) |
| Test.java:28:36:28:36 | s |
| Test.java:29:22:29:22 | t |
| Test.java:30:15:30:37 | writeValueAsBytes(...) |
| Test.java:30:36:30:36 | s |
| Test.java:31:26:31:48 | new String(...) |
| Test.java:31:37:31:38 | bs |
| Test.java:32:22:32:34 | reconstructed |
| Test.java:36:14:36:20 | taint(...) |
| Test.java:39:17:39:20 | file [post update] |
| Test.java:39:23:39:23 | s |
| Test.java:40:43:40:46 | file |
| Test.java:41:17:41:19 | out [post update] |
| Test.java:41:22:41:22 | s |
| Test.java:43:17:43:22 | writer [post update] |
| Test.java:43:25:43:25 | s |
| Test.java:45:17:45:25 | generator [post update] |
| Test.java:45:28:45:28 | s |
| Test.java:46:14:46:37 | writeValueAsString(...) |
| Test.java:46:36:46:36 | s |
| Test.java:47:22:47:22 | t |
| Test.java:48:15:48:37 | writeValueAsBytes(...) |
| Test.java:48:36:48:36 | s |
| Test.java:49:26:49:48 | new String(...) |
| Test.java:49:37:49:38 | bs |
| Test.java:50:22:50:34 | reconstructed |

View File

@@ -0,0 +1,17 @@
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
class Conf extends TaintTracking::Configuration {
Conf() { this = "qltest:dataflow:jackson" }
override predicate isSource(DataFlow::Node source) {
source.asExpr().(MethodAccess).getMethod().hasName("taint")
}
override predicate isSink(DataFlow::Node sink) { any() }
}
from DataFlow::Node source, DataFlow::Node sink, Conf config
where config.hasFlow(source, sink)
select sink

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/jackson-databind-2.10

View File

@@ -0,0 +1,12 @@
package com.fasterxml.jackson.core;
import java.io.Writer;
public class JsonFactory {
public JsonFactory() {
}
public JsonGenerator createGenerator(Writer writer) {
return new JsonGenerator();
}
}

View File

@@ -0,0 +1,6 @@
package com.fasterxml.jackson.core;
public class JsonGenerator {
protected JsonGenerator() {
}
}

View File

@@ -0,0 +1,29 @@
package com.fasterxml.jackson.databind;
import java.io.*;
import java.util.*;
public class ObjectMapper {
public ObjectMapper() {
}
public void writeValue(File resultFile, Object value) {
}
public void writeValue(com.fasterxml.jackson.core.JsonGenerator jgen, Object value) {
}
public void writeValue(OutputStream out, Object value) {
}
public void writeValue(Writer w, Object value) {
}
public byte[] writeValueAsBytes(Object value) {
return null;
}
public String writeValueAsString(Object value) {
return null;
}
}

View File

@@ -0,0 +1,29 @@
package com.fasterxml.jackson.databind;
import java.io.*;
import java.util.*;
public class ObjectWriter {
public ObjectWriter() {
}
public void writeValue(File resultFile, Object value) {
}
public void writeValue(com.fasterxml.jackson.core.JsonGenerator jgen, Object value) {
}
public void writeValue(OutputStream out, Object value) {
}
public void writeValue(Writer w, Object value) {
}
public byte[] writeValueAsBytes(Object value) {
return null;
}
public String writeValueAsString(Object value) {
return null;
}
}

View File

@@ -0,0 +1,14 @@
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.