Digest is secure!
.pcapファイル
添付されているファイルで追跡してみると、Digest認証に成功している情報が出てきました。
これらの変数にどのような役割があるか、以下を参考にしました。
Digest認証
A1 = username ":" realm ":" password
A2 = HTTPメソッド ":" URI
response = MD5(MD5(A1) ":" nonce ":" nc ":" cnonce ":" qop ":" MD5(A2))
これらが必要な情報です。唯一わからないのがpassword
です。
これはブルートフォース攻撃かな?と思ったので、暗号結果が一致するようなpassword
を調べる方針でコードを書きました。
import hashlib
# 要素
username = "q9"
realm = "secret"
method = "GET"
URI = "/q9/"
nonce = "HHj57RG8BQA=4714c627c5195786fc112b67eca599d675d5454b"
qop = "auth"
nc = "00000002"
cnonce="656335d78cef6e86"
# 暗号結果
response = "26c8019eb6f7f41b9c14b4cbda48ab2e"
# ワードリストのインプット
wordlist = []
with open('rockyou.txt', encoding='latin-1') as f:
wordlist = [line.strip() for line in f]
# 暗号計算
A2 = method + ":" + URI
A2_MD5 = hashlib.md5(A2.encode()).hexdigest()
## ブルートフォース
index = 0
while True :
A1 =username + ":" + realm + ":" + wordlist[index]
A1_MD5 = hashlib.md5(A1.encode()).hexdigest()
r = A1_MD5 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + A2_MD5
r_MD5 = hashlib.md5(r.encode()).hexdigest()
if r_MD5 == response :
print(f'nice password:{wordlist[index]}')
break
else :
print(f'bad password:{wordlist[index]}')
index = index + 1
しかし、うまくいきませんでした。
異なる値と同じ値
/q9/
と/q9/htdigest
にアクセスしたとき、response
・nc
・cnonce
以外一致しています。
-
response
:暗号結果 -
nc
:同じnonce
を使った回数-
nonce
:サーバ側が生成するランダム値
-
-
cnonce
:リプレイ攻撃を避けるためのクライアント側が生成するランダム値
user
が変わっていないのでpassword
は変わっていないと推測できます。
そして、/q9/htdigest/
アクセスしているので、user:realm:MD5(A1)
がわかります。
(最初は何も気にしてなかった)
A1 = username ":" realm ":" password
ですから、常に一定と言えます。
つまり、私がA1を出そうとしていた行為は全くの無駄でした…
Digest認証の突破
MD5(A1)
がわかれば、任意のnc
・cnonce
に対して認証が通るresponse
を作ることができます。
A1 = username ":" realm ":" password ← 確定している
A2 = HTTPメソッド ":" URI ← 確定している
response = MD5(MD5(A1) ":" nonce ":" nc ":" cnonce ":" qop ":" MD5(A2)) ← 計算できる
せっかくなので先ほど書いたコードを改良して、responce計算
を行います。
import hashlib
# 要素
username = "q9"
realm = "secret"
method = "GET"
URI = "/q9/"
nonce = "HHj57RG8BQA=4714c627c5195786fc112b67eca599d675d5454b"
qop = "auth"
nc = "任意"
cnonce="任意"
A1_MD5 ="c627e19450db746b739f41b64097d449"
# 暗号計算
A2 = method + ":" + URI
A2_MD5 = hashlib.md5(A2.encode()).hexdigest()
r = A1_MD5 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + A2_MD5
r_MD5 = hashlib.md5(r.encode()).hexdigest()
print(r_MD5)
実践
Burp Suiteを使用します。
まずは、Proxy
タブからctfq.u1tramarine.blue/q9/
にアクセスします。
ここでintercept
をオンにしてログインします。すると、必要な情報が出てきます。
これらの情報をコードに入力し、実行するとresponse=74eb2d08e10461eb7210b2123f4d1cef
responseを書き換えて、Forward
を押すとアクセスできました。
here
を押すと、/q9/flag.html
で同じ認証が求められます。
上記と同様の方法でアクセスすることができます。(URI="/q9/flag.html"に変わります!)
まとめ
Burp Suiteの基礎的な活用方法を学べる良い問題だと思いました。
Digest認証の勉強にもなりました。
お疲れ様でした!