2019-10-31 20:43:47 -05:00
|
|
|
package com.baeldung.rce;
|
|
|
|
|
|
|
|
import org.junit.After;
|
|
|
|
import org.junit.Before;
|
|
|
|
import org.junit.Test;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.OutputStream;
|
|
|
|
import java.net.HttpURLConnection;
|
|
|
|
import java.net.SocketException;
|
2025-04-30 14:18:30 -04:00
|
|
|
import java.net.URI;
|
2019-10-31 20:43:47 -05:00
|
|
|
import java.net.URL;
|
|
|
|
|
|
|
|
import static org.junit.Assert.assertTrue;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unit test which demonstrates a remote code exploit against the {@link App}
|
|
|
|
* server. Sends an XML request containing an attack payload to the {@code POST}
|
|
|
|
* endpoint.
|
|
|
|
*/
|
|
|
|
public final class AppUnitTest {
|
|
|
|
|
|
|
|
private App app;
|
|
|
|
|
|
|
|
/** start a new web server */
|
|
|
|
@Before
|
|
|
|
public void before() throws IOException {
|
|
|
|
app = App.createVulnerable(0);
|
|
|
|
app.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** stop the web server */
|
|
|
|
@After
|
|
|
|
public void after() {
|
|
|
|
if (app != null)
|
|
|
|
app.stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test passes when an {@link IOException} is thrown because this indicates that
|
|
|
|
* the attacker caused the application to fail in some way. This does not
|
|
|
|
* actually confirm that the exploit took place, because the RCE is a
|
|
|
|
* side-effect that is difficult to observe.
|
|
|
|
*/
|
|
|
|
@Test(expected = SocketException.class)
|
2025-04-30 14:18:30 -04:00
|
|
|
public void givenAppIsVulneable_whenExecuteRemoteCodeWhichThrowsException_thenThrowsException() throws Exception {
|
2019-10-31 20:43:47 -05:00
|
|
|
// POST the attack.xml to the application's /persons endpoint
|
2025-04-30 14:18:30 -04:00
|
|
|
final URL url = new URI("http://localhost:" + app.port() + "/persons").toURL();
|
2019-10-31 20:43:47 -05:00
|
|
|
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
|
|
connection.setRequestMethod("POST");
|
|
|
|
connection.setDoOutput(true);
|
|
|
|
connection.setUseCaches(false);
|
|
|
|
connection.setRequestProperty("Content-Type", "application/xml");
|
|
|
|
connection.connect();
|
|
|
|
try (OutputStream os = connection.getOutputStream(); InputStream is = AppUnitTest.class.getResourceAsStream("/attack.xml")) {
|
|
|
|
byte[] buffer = new byte[1024];
|
|
|
|
while (is.read(buffer) > 0) {
|
|
|
|
os.write(buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
final int rc = connection.getResponseCode();
|
|
|
|
connection.disconnect();
|
|
|
|
assertTrue(rc >= 400);
|
|
|
|
}
|
|
|
|
}
|