Skip to content

Commit 482bb94

Browse files
authored
Merge pull request github#13179 from pwntester/java_gson
[Java] Add basic support for Google's Gson library
2 parents 6f302a4 + fe26aca commit 482bb94

33 files changed

+1118
-379
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Added dataflow models for the Gson deserialization library.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
extensions:
2+
- addsTo:
3+
pack: codeql/java-all
4+
extensible: summaryModel
5+
data:
6+
- ["com.google.gson", "Gson", False, "fromJson", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
7+
- ["com.google.gson", "Gson", False, "toJson", "(JsonElement)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
8+
- ["com.google.gson", "Gson", False, "toJson", "(JsonElement,JsonWriter)", "", "Argument[0]", "Argument[1]", "taint", "manual"]
9+
- ["com.google.gson", "Gson", False, "toJson", "(JsonElement,Appendable)", "", "Argument[0]", "Argument[1]", "taint", "manual"]
10+
- ["com.google.gson", "Gson", False, "toJson", "(Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
11+
- ["com.google.gson", "Gson", False, "toJson", "(Object,Appendable)", "", "Argument[0]", "Argument[1]", "taint", "manual"]
12+
- ["com.google.gson", "Gson", False, "toJson", "(Object,Type)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
13+
- ["com.google.gson", "Gson", False, "toJson", "(Object,Type,Appendable)", "", "Argument[0]", "Argument[2]", "taint", "manual"]
14+
- ["com.google.gson", "Gson", False, "toJson", "(Object,Type,JsonWriter)", "", "Argument[0]", "Argument[2]", "taint", "manual"]
15+
- ["com.google.gson", "Gson", False, "toJsonTree", "(Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
16+
- ["com.google.gson", "Gson", False, "toJsonTree", "(Object,Type)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
17+
- ["com.google.gson", "Gson", False, "toString", "()", "", "Argument[0]", "ReturnValue", "taint", "manual"]
18+
- ["com.google.gson", "Gson", False, "newJsonReader", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
19+
- ["com.google.gson", "Gson", False, "newJsonWriter", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
20+
- ["com.google.gson.stream", "JsonReader", False, "nextName", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
21+
- ["com.google.gson.stream", "JsonReader", False, "nextString", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
22+
- ["com.google.gson", "JsonElement", True, "getAsByte", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
23+
- ["com.google.gson", "JsonElement", True, "getAsCharacter", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
24+
- ["com.google.gson", "JsonElement", True, "getAsJsonArray", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
25+
- ["com.google.gson", "JsonElement", True, "getAsJsonObject", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
26+
- ["com.google.gson", "JsonElement", True, "getAsJsonPrimitive", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
27+
- ["com.google.gson", "JsonElement", True, "getAsString", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
28+
- ["com.google.gson", "JsonElement", True, "toString", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
29+
- ["com.google.gson", "JsonArray", True, "add", "", "", "Argument[0]", "Argument[this].Element", "value", "manual"]
30+
- ["com.google.gson", "JsonArray", True, "asList", "", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
31+
- ["com.google.gson", "JsonArray", True, "get", "", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
32+
- ["com.google.gson", "JsonArray", True, "set", "", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
33+
- ["com.google.gson", "JsonObject", True, "add", "", "", "Argument[0]", "Argument[this].MapKey", "value", "manual"]
34+
- ["com.google.gson", "JsonObject", True, "add", "", "", "Argument[1]", "Argument[this].MapValue", "value", "manual"]
35+
- ["com.google.gson", "JsonObject", True, "addProperty", "(String,String)", "", "Argument[0]", "Argument[this].MapKey", "value", "manual"]
36+
- ["com.google.gson", "JsonObject", True, "addProperty", "(String,String)", "", "Argument[1]", "Argument[this].MapValue", "value", "manual"]
37+
- ["com.google.gson", "JsonObject", True, "asMap", "", "", "Argument[this].MapKey", "ReturnValue.MapKey", "value", "manual"]
38+
- ["com.google.gson", "JsonObject", True, "asMap", "", "", "Argument[this].MapValue", "ReturnValue.MapValue", "value", "manual"]
39+
- ["com.google.gson", "JsonObject", True, "entrySet", "", "", "Argument[this].MapKey", "ReturnValue.Element.MapKey", "value", "manual"]
40+
- ["com.google.gson", "JsonObject", True, "entrySet", "", "", "Argument[this].MapKey", "ReturnValue.Element.MapValue", "value", "manual"]
41+
- ["com.google.gson", "JsonObject", True, "get", "", "", "Argument[this].MapValue", "ReturnValue", "value", "manual"]
42+
- ["com.google.gson", "JsonObject", True, "keySet", "", "", "Argument[this].MapKey", "ReturnValue.Element", "value", "manual"]
43+
- ["com.google.gson", "JsonPrimitive", True, "JsonPrimitive", "(Character)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
44+
- ["com.google.gson", "JsonPrimitive", True, "JsonPrimitive", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]

java/ql/lib/semmle/code/java/Serializability.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import java
66
private import frameworks.jackson.JacksonSerializability
7+
private import frameworks.google.GsonSerializability
78
private import frameworks.google.GoogleHttpClientApi
89

910
/**
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Provides classes and predicates for working with Java Serialization in the context of
3+
* the `com.google.gson` JSON processing framework.
4+
*/
5+
6+
import java
7+
private import semmle.code.java.Serializability
8+
private import semmle.code.java.dataflow.DataFlow
9+
private import semmle.code.java.dataflow.FlowSteps
10+
11+
/**
12+
* A method used for deserializing objects using Gson. The first parameter is the object to be
13+
* deserialized.
14+
*/
15+
private class GsonReadValueMethod extends Method {
16+
GsonReadValueMethod() { this.hasQualifiedName("com.google.gson", "Gson", "fromJson") }
17+
}
18+
19+
/** A type whose values may be deserialized by the Gson JSON framework. */
20+
abstract class GsonDeserializableType extends Type { }
21+
22+
/** A type whose values are explicitly deserialized in a call to a Gson method. */
23+
private class ExplicitlyReadGsonDeserializableType extends GsonDeserializableType {
24+
ExplicitlyReadGsonDeserializableType() {
25+
exists(MethodAccess ma |
26+
// A call to a Gson read method...
27+
ma.getMethod() instanceof GsonReadValueMethod and
28+
// ...where `this` is used in the final argument, indicating that this type will be deserialized.
29+
// TODO: find a way to get the type represented by java.lang.reflect.Type and com.google.gson.reflect.TypeToken
30+
// fromJson(String json, TypeToken<T> typeOfT)
31+
// fromJson(String json, Type typeOfT)
32+
usesType(ma.getArgument(1).getType(), this) and
33+
not this instanceof TypeClass and
34+
not this instanceof TypeObject
35+
)
36+
}
37+
}
38+
39+
/** A type used in a `GsonDeserializableField` declaration. */
40+
private class FieldReferencedGsonDeserializableType extends GsonDeserializableType {
41+
FieldReferencedGsonDeserializableType() {
42+
exists(GsonDeserializableField f | usesType(f.getType(), this))
43+
}
44+
}
45+
46+
/** A field that may be deserialized using the Gson JSON framework. */
47+
private class GsonDeserializableField extends DeserializableField {
48+
pragma[assume_small_delta]
49+
GsonDeserializableField() {
50+
exists(GsonDeserializableType superType |
51+
superType = this.getDeclaringType().getAnAncestor() and
52+
not superType instanceof TypeObject and
53+
//superType.fromSource()
54+
not superType.(RefType).getPackage().getName().matches("java%")
55+
)
56+
}
57+
}
58+
59+
private class GsonInheritTaint extends DataFlow::FieldContent, TaintInheritingContent {
60+
GsonInheritTaint() { this.getField() instanceof GsonDeserializableField }
61+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import com.google.gson.Gson;
2+
3+
public class Test {
4+
public static class Potato {
5+
private String name;
6+
private Potato inner;
7+
private Object object;
8+
9+
private String getName() {
10+
return name;
11+
}
12+
13+
private Potato getInner() {
14+
return inner;
15+
}
16+
17+
private Object getObject() {
18+
return object;
19+
}
20+
21+
}
22+
23+
public static String source() {
24+
return "";
25+
}
26+
27+
public static void sink(Object any) {}
28+
29+
public static void gsonfromJson() throws Exception {
30+
String s = source();
31+
Potato tainted = new Gson().fromJson(s, Potato.class);
32+
sink(tainted); // $ hasTaintFlow
33+
sink(tainted.getName()); // $ hasTaintFlow
34+
sink(tainted.getInner()); // $ hasTaintFlow
35+
sink(tainted.getInner().getName()); // $ hasTaintFlow
36+
sink(tainted.getObject()); // $ hasTaintFlow
37+
}
38+
}

java/ql/test/library-tests/dataflow/taint-gson/dataFlow.expected

Whitespace-only changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import java
2+
import TestUtilities.InlineFlowTest
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/gson-2.8.6

0 commit comments

Comments
 (0)