5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【SQL入門】『SQLインジェクション』について

Last updated at Posted at 2020-03-15

この記事では、《SQLインジェクション》について、
業務を通して学習した内容を、備忘録としてまとめています。

  • 『良いSQL』と『悪いSQL』
  • 『SQLインジェクション』とは…?

こういった内容についてまとめています。

※本記事は、自分で学習したことのまとめ用として書いています。
尚、解説で誤った点があれば、スローして頂ければ喜んでキャッチしますのでお願い致します。

環境

  • apache2.4
  • php7
  • MySQL5.7

『良いSQL』 と 『悪いSQL』

良いSQL

  • メンテナンスしやすい

    自分が書いたSQL文を、他の人がメンテナンスすることもある
  • パフォーマンスが良い

    データ量、実行頻度、同時アクセスが増加しても、導入当初と同等のレスポンスが維持できる

悪いSQL

  • 必要以上のデータをメモリに読み込む

    パフォーマンスの劣化問題

    セキュリティ上の問題
  • 索引(index)を使用せず、全件検索する

    パフォーマンスの劣化問題

    (I/Oの増加、メモリの非効率的利用)

セキュリティの観点から見た 『悪いSQL』

rpa_3.jpg

ズバリ・・・

__『SQLインジェクション』の脆弱性があるSQL文__です。

『SQLインジェクション』 とは…?

『SQLインジェクション』とは・・・

データベースと連動したWebサイトで…

  • データベースへの問合せ
  • データベースへの操作

などを行うプログラムに、パラメータとしてSQL文の断片を与えることにより…

  • データベースの改ざん
  • データベースから不正に情報を入手

する攻撃です。

--- 『SQLインジェクション』 の例題 ---

例題として、__認証を回避する『SQLインジェクション』__があります。

SQL文は、よくログイン認証に使われますが、

例えば・・・

以下のような__フォームの入力値を代入した変数を利用して生成したSQL文__がtrueであれば、__ログインに成功する__というモノがあります。

sql_1.png
SELECT *
FROM
    users
WHERE
    user_name = '$user_name'
    AND password = '$password';

この$passwordに…

'or'x'='x

という不正な値を入力します。

SELECT *
FROM
    users
WHERE
    user_name = '$user_name'
    AND password = ''or'x'='x';

これだと分かりづらいので、改行すると…

SELECT *
FROM
    users
WHERE
    user_name = '$user_name'
    AND password = ''
    OR  'x' = 'x';

上記のように、WHERE句にORの条件が追加されます。

すると・・・

OR 'x' = 'x'trueとなるので、ログインに成功してしまいます。

上記は、SQL文の構造が変わってしまったため…

user_name = '$user_name'
AND password = ''

または・・・

OR 'x' = 'x'

trueになればログインできるSQL文に、変わってしまったということです。

『SQLインジェクション』の対策 【PHPの場合】

対策: 『プリペアドステートメント』を使う

プリペアドステートメント』を使い、実行したいSQL文をコンパイルすることで・・・

SQL文を固定し、構造が変わらないようにします。

『プリペアドステートメントの使い方』について詳しく知りたい方は、
下記を参照してみて下さい。

》【PDO】PHPでデータベースに接続する方法【INSERT編】

  • プリペアドステートメント

    SQL文で値がいつでも変更できるように、変更する箇所だけ変数のようにしたSQL文を作る仕組みのことです。
    通常『プリペアドステートメント』は『プレースホルダ』を使うために作られます。
  • プレースホルダ

    ユーザが入力した内容を後から挿入するために、予め確保した場所のこと。

仮に、パスワードに…

OR 'x' = 'x'

と入力しても、SQL文がコンパイルされているので、OR 'x' = 'x'というパスワードを探しにいく。

当然、そのようなパスワードはないため、ログインできない。

まとめ: 基本コーディング

sample.php
<?php

try {

    // リクエストから得たスーパーグローバル変数をチェックするなどの処理
    $user_name = "ここにユーザー名が入ります";
    $password = "ここにパスワードが入ります";

    // データベース接続設定
    $pdo = new PDO(
        'mysql:host=サーバー名;dbname=DB名;charset=文字エンコード',
        'ユーザー名',
        'パスワード',
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        ]
    );

        // パラメータ
        $spl = (
            'SELECT
                USER_NAME, PASSWORD
            FROM
                テーブル名
            WHERE
                AND USER_NAME = :USER_NAME
                AND PASSWORD = :PASSWORD'
        );
        
    // プリペアドステートメントを用意
    $stmt = $pdo->prepare($sql);

    // 値をバインドする
    $stmt->bindValue(':USER_NAME', $user_name, PDO::PARAMS_STR);
    $stmt->bindValue(':PASSWORD', $password, PDO::PARAMS_STR);
        
    // 結果を取得する
    $row = $prepare->fetch();

} catch (PDOException $e) {

    // エラー処理

}
5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?