驚くほど簡単な技術系健忘録

驚くほど簡単な技術系健忘録

アプリやWebサービス、RPAを作る上での健忘録を書いていきます。

SQLインジェクション脆弱性を持つサイトを作ってみた

dev.classmethod.jp
ここのサイトを真似してSQLインジェクション脆弱性を持つサイトを作ろうとしたら色々とハマったので覚書。
※そもそもPHPでデータベースに接続することすらしたことない素人が頑張ってみました。

まずはログイン画面(これは上のサイトのソースをそのままコピペ)

■index.html
<html>
  <meta charset="UTF-8">
  <head>
    <title>ログイン画面</title>
  </head>
  <body>
    <form action="db.php" method="post">
      <table>
        <tr>
          <td>ユーザID</td>
          <td><input type="text" name="uid"></td>
        </tr>
        <tr>
          <td>パスワード</td>
          <td><input type="text" name="password"></td>
        </tr>
      </table>
      <input type="submit" value="ログイン">
    </form>
  </body>
</html>

次にデータベース接続を行ったりSELECT文を実行するページこれがこのページの最初に書いたブログでは情報が古くてそのままコピペできなかった。
ということでこちらは以下のQiitaの記事等を色々と参照。
■単純な接続部分
qiita.com
■接続確認コード含む等
kahoo.blog

■db.php
<html>
  <meta charset="UTF-8">
  <head>
    <title>ログイン処理</title>
  </head>
  <body>
<?php
// エラーを出力する
ini_set('display_errors', "On");

// defineの値は環境によって変えてください。
define('HOSTNAME', 'localhost');
define('DATABASE', 'system');
define('USERNAME', 'root');
define('PASSWORD', 'root');

//入力されたIDとpassword
$uid = $_POST['uid'];
$pass = $_POST['password'];

//データベース接続
$db  = new PDO('mysql:host=' . HOSTNAME . ';dbname=' . DATABASE, USERNAME, PASSWORD);

//SQL実行と結果
$sql = "SELECT email FROM users where uid='$uid' AND passwd='{$pass}'";
$stmt = $db->query($sql);
$stmt->execute();
$count=$stmt->rowCount();

//入力に誤りがあった場合
if ($count == 0) {
 echo "ユーザ名または、パスワードに誤りがあります。";
 exit;
}

//SQLで取得したデータを表示
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
  print('email addressはこちらです '.$result['email']);
  print('<br>');
}

$dbh = null;

?>
  <a href="index.html">ログイン画面に戻る</a>
  </body>
</html>

なお、IDやパスワードが誤っていた場合は取得した結果が0行ということで判別しているが、PDOで行数(レコード数)をカウントする関数がなくてややこしかった。それくらい用意してくれよ。このブログを参考にして解決できたから良いけど。
www.php-mysql-linux.com

■データベース

systemというデータベースにusersテーブルを作成する。テーブルの中身はこんな感じ。
usersテーブルを作成します。

uid varchar(20)
passwd varchar(20)
email varchar(20)

レコードは2レコード以上入れておきましょう。

SQLインジェクションを試してみる

パスワード欄に「'OR 'A' = 'A」と入れると全ユーザのデータが表示されて情報漏洩が起こることが確認できると思います。