検索ボックスが命令になる
SQLインジェクションとは、入力欄に書いた文字が、データベースへの命令として実行されてしまう弱点です。検索や、ログインの欄でよく起こります。
直し方は単純で、必ず守れる決まりがあります。今日は、起きる仕組みと、防ぐ書き方を学びます。ラボでは、自分専用のコピーだけを使います。
このレッスンのゴール
メモ
SQLインジェクションが起きる仕組みを示し、パラメータ化で直すことができる。
キーワード
| ことば | いみ | れい |
|---|---|---|
| SQL | データベースに命令を出すための言語 | |
| クエリ | データベースへの問い合わせの文 | |
| 入力値 | 利用者が欄に書いた文字 | |
| インジェクション | 入力に命令を混ぜて、実行させる攻撃 | |
| プレースホルダ | 値を入れるために、あとで埋める目印 | ? |
学生が入力するセルは、このプレビューでは空白です。
守るべき約束はひとつ
注意
ラボの店は、自分専用のコピーで、外にはつながっていません。攻撃の練習は、その中だけです。許可のない他人のサイトには、絶対に試さないでください。上のバーの Start the lab を押します。
文字をつなげると命令が混ざる
検索のSQLを、入力した文字をつなげて作るとします。入力が普通の言葉なら、問題はありません。
ところが、入力に引用符(')やSQLの言葉を入れると、SQLの形が変わります。入力のつもりが、命令の一部になります。
例: 文字をつなげた検索(危険)
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's | LIKE '%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の中には、値の場所に プレースホルダ(?)だけを書きます。
入力は、別に渡します。データベースは、入力を必ず「ただの値」として扱い、命令としては読みません。
例: プレースホルダを使った検索
def search_books(db, term):
# SQLは固定で、値は別に渡す。
sql = "SELECT title FROM books WHERE public = 1 AND title LIKE ?"
return db.execute(sql, ("%" + term + "%",)).fetchall()よくある間違い
注意
「危険な文字を消せば、つなげても大丈夫だ」と考える人がいます。消し忘れや、別の書き方で、すり抜けられます。消すのではなく、入力を命令と分けて渡すのが、確実な方法です。
守りはいくつも重ねる
パラメータ化が基本ですが、それだけに頼りません。データベースのアカウントには、必要な操作の権限だけを与えます。
エラーの細かい文を、画面に出さないことも大切です。攻撃者に、手がかりを与えないためです。
例: 守りの重ね方
| 守り | 役目 |
|---|---|
| パラメータ化 | 入力を命令にしない(基本) |
| 権限を最小にする | 破られても、できることを減らす |
| エラーを隠す | 攻撃者への手がかりを減らす |
| 入力の形を確かめる | 数字の欄に文字が入るのを防ぐ |
学生が入力するセルは、このプレビューでは空白です。
さらに挑戦: ラボで直す
ラボの店の検索は、入力をつなげて作られています。ラボの手順に従い、自分のコピーのコードを、このレッスンの考え方で直してください。
直したあと、ラボの確認プログラムですべて合格になるかを見ます。直した行と、なぜ安全になったかを、1文で書きます。