クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

SQLインジェクションとは

このレッスンのあとで: SQLインジェクションが起きる仕組みを示し、パラメータ化で直すことができる。

45分のレッスンコマンド2件SQL インジェクションのラボ:弱い検索を攻撃し、クエリを直して確かめる

検索ボックスが命令になる

SQLインジェクションとは、入力欄に書いた文字が、データベースへの命令として実行されてしまう弱点です。検索や、ログインの欄でよく起こります。

直し方は単純で、必ず守れる決まりがあります。今日は、起きる仕組みと、防ぐ書き方を学びます。ラボでは、自分専用のコピーだけを使います。

このレッスンのゴール

メモ

SQLインジェクションが起きる仕組みを示し、パラメータ化で直すことができる。

キーワード

ことばいみれい
SQLデータベースに命令を出すための言語
クエリデータベースへの問い合わせの文
入力値利用者が欄に書いた文字
インジェクション入力に命令を混ぜて、実行させる攻撃
プレースホルダ値を入れるために、あとで埋める目印?

学生が入力するセルは、このプレビューでは空白です。

守るべき約束はひとつ

注意

ラボの店は、自分専用のコピーで、外にはつながっていません。攻撃の練習は、その中だけです。許可のない他人のサイトには、絶対に試さないでください。上のバーの Start the lab を押します。

文字をつなげると命令が混ざる

検索のSQLを、入力した文字をつなげて作るとします。入力が普通の言葉なら、問題はありません。

ところが、入力に引用符(')やSQLの言葉を入れると、SQLの形が変わります。入力のつもりが、命令の一部になります。

例: 文字をつなげた検索(危険)

コード: python
def search_books(db, term):
    # 入力をそのままつなげている。これが弱点。
    sql = "SELECT title FROM books WHERE public = 1 AND title LIKE '%" + term + "%'"
    return db.execute(sql).fetchall()

例: 入力で変わるSQLの形

入力組み立てられたSQL(後半)結果
星LIKE '%星%'星の本だけ
x' OR 1=1 -- LIKE '%x' OR 1=1 -- %'非公開も全部出る
Tom'sLIKE '%Tom's%'引用符で形がくずれ、エラー

学生が入力するセルは、このプレビューでは空白です。

まず、ふつうの検索を見る

ラボには、小さな店の検索ページがあります。商品の名前で検索すると、名前と値段が1行ずつ返ります。

攻撃の前に、ふつうの動きを確かめます。入力の言葉は、ただの名前です。

「Pen」で検索する

コマンド
curl -G --data-urlencode "q=Pen" http://app:8000/search

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

「Mug」で検索する

コマンド
curl -G --data-urlencode "q=Mug" http://app:8000/search

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

パラメータ化で入力を値にする

直し方は、SQLに入力をつなげないことです。SQLの中には、値の場所に プレースホルダ(?)だけを書きます。

入力は、別に渡します。データベースは、入力を必ず「ただの値」として扱い、命令としては読みません。

例: プレースホルダを使った検索

コード: python
def search_books(db, term):
    # SQLは固定で、値は別に渡す。
    sql = "SELECT title FROM books WHERE public = 1 AND title LIKE ?"
    return db.execute(sql, ("%" + term + "%",)).fetchall()

よくある間違い

注意

「危険な文字を消せば、つなげても大丈夫だ」と考える人がいます。消し忘れや、別の書き方で、すり抜けられます。消すのではなく、入力を命令と分けて渡すのが、確実な方法です。

守りはいくつも重ねる

パラメータ化が基本ですが、それだけに頼りません。データベースのアカウントには、必要な操作の権限だけを与えます。

エラーの細かい文を、画面に出さないことも大切です。攻撃者に、手がかりを与えないためです。

例: 守りの重ね方

守り役目
パラメータ化入力を命令にしない(基本)
権限を最小にする破られても、できることを減らす
エラーを隠す攻撃者への手がかりを減らす
入力の形を確かめる数字の欄に文字が入るのを防ぐ

学生が入力するセルは、このプレビューでは空白です。

さらに挑戦: ラボで直す

ラボの店の検索は、入力をつなげて作られています。ラボの手順に従い、自分のコピーのコードを、このレッスンの考え方で直してください。

直したあと、ラボの確認プログラムですべて合格になるかを見ます。直した行と、なぜ安全になったかを、1文で書きます。

このラボとソースについて: SQL インジェクションのラボ:弱い検索を攻撃し、クエリを直して確かめる

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。