たけるのプログラミング

作ったものとか、気ままにアップします。

【日能研 個人情報流出】SQLインジェクションについて解説

最近よくフィッシングメールといったいわゆるサイバー犯罪が増えてきました。

そして最近話題になったのが日能研SQLインジェクションの被害にあり、個人情報を28万件流出させてしまった事件。
www2.nichinoken.co.jp


xtech.nikkei.com


SQLインジェクションって何?と思う方も多いと思うので簡単なプログラムと共に説明したいと思います。

まずSQLインジェクションSQLとはデータベースを操作するための言語です。

データベースは情報を記録する箱というイメージ。

この箱であるデータベースに対して、SQLを使ってデータを追加したり、読み取ったり、更新、削除します。

SQLインジェクションは、このSQLを悪用して情報を入手したり、不正ログインを可能にします。

具体例

今回はそんなSQLインジェクションの被害に遭うような全くセキュリティ対策がされていないコードを書いてみました。

名前とパスワードを入力してログインするだけのシステム。

この後実際にSQLインジェクションを行い、パスワードなしでログインしてみます。

用意するデータベースのテーブルはこんな感じ
f:id:takeru232423:20220203210434p:plain

nameとpasswordが合致したら

f:id:takeru232423:20220203210746p:plain

ログイン成功画面にリダイレクトする仕組み↓。

f:id:takeru232423:20220203211145p:plain

ログイン処理で使うSQL

SELECT * FROM student where name ='$name' and password = '$password'

例) ユーザーがnameに山田太郎、passwordにtaroyamadaと入力した際にプログラム上で実行されるSQL
SELECT * FROM student where name ='山田太郎' and password = 'taroyamada'


この$nameと$passwordには上記画像のフォームからユーザーが入力した値が入ります。
whereとは条件を指定する際に使い、andはかつという意味で、データベースのnameの値かつpasswordの値が一致する行を探し、その行を返します。
つまり行の情報が返されたらログインが成功というわけです。

実際にSQLインジェクションを行う

名前に山田太郎、そしてパスワードの部分に' OR '1' = '1と入力
f:id:takeru232423:20220203212512p:plain

ログインボタンを押すと、、、
f:id:takeru232423:20220203212541p:plain

ログイン成功画面が出てきました。

パスワードが全然違うのに何故でしょう。

この時実行されるSQL

SELECT * FROM student where name ='山田太郎' and password = '' OR '1' = '1'

このORは'または'という意味。ANDは'かつ'という意味。つまり上記のSQL文は

名前が山田太郎かつパスワードが''  または'1'='1'の時はログイン成功とするという意味になります。

このようにSQLの知識が少しあれば、誰でもSQLインジェクションを起こすことが可能です。

このようなSQLインジェクションを防ぐためには、プログラム側でユーザーの入力した値に対してエスケープ処理など様々な対策を行わなくてはいけません。

今回のセキュリティー対策がされていないコード

phpで書きました

//ログイン処理
if($_POST['name']!=''&&$_POST['password']!=''){
    //入力された値を変数に入れる
    $name = $_POST['name'];
    $password = $_POST['password'];

    //ログイン処理
    //ログインが2つの値と一致する行があった場合にログイン成功とする

    //不正ログイン
    // ' OR '1' = '1
    $count = $db->query("SELECT * FROM student where name ='$name' and password = '$password' ");
    
    if($count->fetch()){
        header('Location:userpage.php');
        exit();
    }else{
        echo 'ログイン不成功!';
    }
}

?>

<form action="" method='POST'>
    名前:<input type="text" name="name">
    パスワード:<input type="text" name="password">
    <input type="submit" value="ログイン">
</form>

感想

SQLインジェクション恐るべし、、、