Add Gson support to unsafe deserialization query

This commit is contained in:
Chris Smowton
2021-08-10 15:20:11 +01:00
parent 6b4ca31783
commit cd2c9e9ca3
21 changed files with 929 additions and 3 deletions

View File

@@ -0,0 +1,24 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app"
android:installLocation="auto"
android:versionCode="1"
android:versionName="0.1" >
<uses-permission android:name="android.permission.INTERNET" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".GsonActivity"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,17 @@
package com.example.app;
import android.app.Activity;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.Gson;
public class GsonActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(-1);
ParcelableEntity entity = (ParcelableEntity) getIntent().getParcelableExtra("jsonEntity");
}
}

View File

@@ -0,0 +1,77 @@
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.typeadapters.RuntimeTypeAdapterFactory;
import com.example.User;
import com.thirdparty.Person;
public class GsonServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
// GOOD: concrete class type specified
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String json = req.getParameter("json");
Gson gson = new Gson();
Object obj = gson.fromJson(json, User.class);
}
@Override
// GOOD: concrete class type specified
public void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String json = req.getParameter("json");
Gson gson = new Gson();
Object obj = gson.fromJson(json, Person.class);
}
@Override
// BAD: allow class name to be controlled by remote source
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String json = req.getParameter("json");
String clazz = req.getParameter("class");
try {
Gson gson = new Gson();
Object obj = gson.fromJson(json, Class.forName(clazz)); // $unsafeDeserialization
} catch (ClassNotFoundException cne) {
throw new IOException(cne.getMessage());
}
}
@Override
// BAD: allow class name to be controlled by remote source even with a type adapter factory
public void doHead(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String json = req.getParameter("json");
String clazz = req.getParameter("class");
try {
RuntimeTypeAdapterFactory<User> runtimeTypeAdapterFactory = RuntimeTypeAdapterFactory
.of(User.class, "type");
Gson gson = new GsonBuilder().registerTypeAdapterFactory(runtimeTypeAdapterFactory).create();
Object obj = gson.fromJson(json, Class.forName(clazz)); // $unsafeDeserialization
} catch (ClassNotFoundException cne) {
throw new IOException(cne.getMessage());
}
}
@Override
// GOOD: specify allowed class types without explicitly configured vulnerable subclass types
public void doTrace(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String json = req.getParameter("json");
String clazz = req.getParameter("class");
RuntimeTypeAdapterFactory<Person> runtimeTypeAdapterFactory = RuntimeTypeAdapterFactory
.of(Person.class, "type");
Gson gson = new GsonBuilder().registerTypeAdapterFactory(runtimeTypeAdapterFactory).create();
Person obj = gson.fromJson(json, Person.class);
}
}

View File

@@ -0,0 +1,42 @@
package com.example.app;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class ParcelableEntity implements Parcelable {
private static final Gson GSON = new GsonBuilder().create();
public ParcelableEntity(Object obj) {
this.obj = obj;
}
private Object obj;
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(obj.getClass().getName());
parcel.writeString(GSON.toJson(obj));
}
public static final Parcelable.Creator CREATOR = new Creator<ParcelableEntity>() {
@Override
public ParcelableEntity createFromParcel(Parcel parcel) {
try {
Class clazz = Class.forName(parcel.readString());
Object obj = GSON.fromJson(parcel.readString(), clazz); // $unsafeDeserialization
return new ParcelableEntity(obj);
}
catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@Override
public ParcelableEntity[] newArray(int size) {
return new ParcelableEntity[size];
}
};
}

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12:${testdir}/../../../stubs/jabsorb-1.3.2:${testdir}/../../../stubs/json-java-20210307:${testdir}/../../../stubs/joddjson-6.0.3:${testdir}/../../../stubs/flexjson-2.1
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12:${testdir}/../../../stubs/jabsorb-1.3.2:${testdir}/../../../stubs/json-java-20210307:${testdir}/../../../stubs/joddjson-6.0.3:${testdir}/../../../stubs/flexjson-2.1:${testdir}/../../../stubs/gson-2.8.6:${testdir}/../../../stubs/google-android-9.0.0