I am getting Fortify issue Dynamic Code Evaluation: Unsafe Deserialization on the lines below:
@RequestMapping(value="/v2/doc", method=RequestMethod.POST)
public JsonDocVerifyResponse verify(@RequestBody JsonDocVerifyRequestV3 request)
JsonDocVerifyRequestV3 temp = (JsonDocVerifyRequestV3)SerializationUtils.clone(request);
The solution for unsafe deserialization is this https://www.ibm.com/developerworks/library/se-lookahead/ But as you can see in my codes I am not using ByteArrayOutputStream to deserialize the object.
Is this a false positive by Fortify? If not, how can I use
org.apache.commons.io.serialization.ValidatingObjectInputStream
to validate the class? Any code sample will be of great help!
These are the snippets:
@RequestMapping(value="/v2/doc", method=RequestMethod.POST)
public JsonDocVerifyResponse verify(@RequestBody JsonDocVerifyRequestV3 request) {
debugJsonRequest(request, DOC_TYPE.khIdBack);
JsonDocVerifyResponse response = new JsonDocVerifyResponse();
return response;
}
public void debugJsonRequest(JsonDocVerifyRequestV3 request, DOC_TYPE docType) {
try {
JsonDocVerifyRequestV3 temp(JsonDocVerifyRequestV3) SerializationUtils.clone(request);
LOGGER.debug("{}|{}", docType, CommonUtil.debugJsonObject(temp));
} catch(Exception e) {
LOGGER.error("Error in debug json object", e);
}
}
You can use accept
and reject
methods to safer deserialization operation.
Example:
import com.sun.xml.internal.ws.util.ByteArrayBuffer;
import org.apache.commons.io.serialization.ValidatingObjectInputStream;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Bar bar = new Bar("bar-test");
Foo foo = new Foo("test-foo", bar);
// write into an array buffer
ByteArrayBuffer buffer = new ByteArrayBuffer();
try (ObjectOutputStream serializeStream = new ObjectOutputStream(buffer)) {
serializeStream.writeObject(foo);
}
try (ValidatingObjectInputStream stream = new ValidatingObjectInputStream(buffer.newInputStream())) {
// add validated classes
stream.accept(Foo.class);
stream.accept(Bar.class);
Foo foo2 = (Foo) stream.readObject();
System.out.println(foo2);
}
}
public static class Foo implements Serializable {
private String name;
private Bar bar;
public Foo(String name, Bar bar) {
this.name = name;
this.bar = bar;
}
@Override
public String toString() {
return "Foo{" +
"name='" + name + '\'' +
", bar=" + bar +
'}';
}
}
public static class Bar implements Serializable {
private String name;
public Bar(String name) {
this.name = name;
}
@Override
public String toString() {
return "Bar{" +
"name='" + name + '\'' +
'}';
}
}
}