mirror of
https://github.com/github/codeql.git
synced 2026-05-05 13:45:19 +02:00
Unsafe deserialization: add support for Jodd JSON library
This commit is contained in:
102
java/ql/test/query-tests/security/CWE-502/JoddJsonServlet.java
Normal file
102
java/ql/test/query-tests/security/CWE-502/JoddJsonServlet.java
Normal file
@@ -0,0 +1,102 @@
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import jodd.json.JsonParser;
|
||||
|
||||
import com.example.User;
|
||||
import com.thirdparty.Person;
|
||||
|
||||
public class JoddJsonServlet extends HttpServlet {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
// GOOD: class type specified (despite a dangerous configuration)
|
||||
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String json = req.getParameter("json");
|
||||
String clazz = req.getParameter("class");
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
parser.setClassMetadataName("class");
|
||||
Person person = parser.parse(json, Person.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
// BAD: dangerously configured parser with no class restriction passed to `parse`,
|
||||
// using a few different possible call sequences.
|
||||
public void doHead(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String json = req.getParameter("json");
|
||||
String clazz = req.getParameter("class");
|
||||
int callOrder;
|
||||
try {
|
||||
callOrder = Integer.parseInt(req.getParameter("callOrder"));
|
||||
}
|
||||
catch(NumberFormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
if(callOrder == 0) {
|
||||
parser.setClassMetadataName("class");
|
||||
User obj = parser.parse(json, null); // $unsafeDeserialization
|
||||
} else if(callOrder == 1) {
|
||||
parser.setClassMetadataName("class").parse(json, null); // $unsafeDeserialization
|
||||
} else if(callOrder == 2) {
|
||||
parser.setClassMetadataName("class").lazy(true).parse(json, null); // $unsafeDeserialization
|
||||
} else if(callOrder == 3) {
|
||||
parser.withClassMetadata(true).lazy(true).parse(json, null); // $unsafeDeserialization
|
||||
}
|
||||
}
|
||||
|
||||
@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 {
|
||||
JsonParser parser = new JsonParser();
|
||||
Object obj = parser.parse(json, Class.forName(clazz)); // $unsafeDeserialization
|
||||
} catch (ClassNotFoundException cne) {
|
||||
throw new IOException(cne.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
// GOOD: dangerously configured parser is ameliorated by setting a list of allowed classes, using various call orders,
|
||||
// or by explicitly disabling the class metadata option.
|
||||
public void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String json = req.getParameter("json");
|
||||
String clazz = req.getParameter("class");
|
||||
int callOrder;
|
||||
try {
|
||||
callOrder = Integer.parseInt(req.getParameter("callOrder"));
|
||||
}
|
||||
catch(NumberFormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
if(callOrder == 0) {
|
||||
parser.setClassMetadataName("class");
|
||||
parser.allowClass("example.Class");
|
||||
User obj = parser.parse(json, null);
|
||||
} else if(callOrder == 1) {
|
||||
parser.allowClass("example.Class");
|
||||
parser.setClassMetadataName("class");
|
||||
User obj = parser.parse(json, null);
|
||||
} else if(callOrder == 2) {
|
||||
parser.setClassMetadataName("class").allowClass("example.Class").parse(json, null);
|
||||
} else if(callOrder == 3) {
|
||||
parser.allowClass("example.Class").setClassMetadataName("class").parse(json, null);
|
||||
} else if(callOrder == 4) {
|
||||
parser.setClassMetadataName("class").withClassMetadata(false).parse(json, null);
|
||||
} else if(callOrder == 5) {
|
||||
parser.withClassMetadata(true).setClassMetadataName(null).parse(json, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
//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
|
||||
|
||||
Reference in New Issue
Block a user