SQLインジェクション入門:仕組みと対策
ログイン処理を条件式から崩す
この回でやること
ログインは条件が2つ並ぶので、素のOR型は名前欄だけでは通りません。なぜ通らないか、どう切ると誰として入れるかを、章末の演習と地続きで見ます。
- 読む 約 9 分
- 最後にクイズ 1 問
このレッスンで学ぶこと
ログインは、名前とパスワードの2つの条件が AND で並ぶぶん、1本条件のときの手がそのままでは効きません。この回は素のOR型が名前欄で空振りする理由と、どう切れば「誰として入れるか」まで選べるのかを見ます。
読み終えると、なぜ名前欄では通らずパスワード欄では通るのかを、結合の順序から手で追えるようになります。
2つ並ぶと素のOR型は空振りする
ログインではこういうSQLが組み立てられます。
SQL クエリ
SELECT name, role FROM users WHERE name = 'admin' AND password = 'xxxx'名前欄に ' OR '1'='1 だけを入れると、こう組み上がります。
SQL クエリ
SELECT name, role FROM users WHERE name = '' OR '1'='1' AND password = ''ここが勘所です。AND は OR より先に結ばれるので、この文は 名前が空 OR ('1'='1' AND パスワードが空) と括られます。右側は '1'='1' こそ真ですが、パスワードが空 が偽なので、まとまると偽です。左の 名前が空 も偽。だれの行でも真にならず、ログインは通りません。前回の1本条件では効いた手が、ここでは後ろのパスワード条件に足を引っ張られます。
後ろごと切ると誰にでもなれる
生き残っているパスワード条件を消せば済みます。-- で後ろを切り落とします。名前欄に admin' -- と入れると、こうです。
SQL クエリ
SELECT name, role FROM users WHERE name = 'admin' --' AND password = ''-- から先はコメントなので、条件は name = 'admin' だけ。admin の行に一致し、パスワードを知らないまま admin として 入れます。
admin' -- は狙った admin になります。一方 ' OR '1'='1' -- は条件が全行で真になるだけなので、最初に見つかった行の人になり、相手を選べません。同じ「通る」でも、誰の権限を手にするかが変わります。
パスワード欄を使う手もあります。名前に tanaka、パスワード欄に ' OR '1'='1 を入れると、(名前がtanaka かつ パスワードが空) OR '1'='1' と括られ、末尾の OR の後ろにもう条件が続かないので、全体が真になって通ります。名前欄と違い、こちらは足を引っ張る AND が後ろに残りません。
OR を置く位置が違うからです。名前欄だと後ろに AND password が残り、AND が先に結ばれて足を引っ張ります。パスワード欄だと OR が文の一番後ろに来るので、引っ張るものがありません。順序を思い出せば、どちらが通るか手で追えます。
直す方向と、章末の演習で確かめること
直った版は文字列を組み立てず、入力を値としてだけ渡します。すると admin' -- は admin' -- という名前の人を探すだけで、コメントにも条件にもならず、正しいパスワード無しでは入れません。この章の締めくくりの演習では、実際に名前とパスワードを送り、返ってくる「誰として入れたか」と役割を見られます。まず自分のアカウントで普通に入り、次に admin' -- を名前欄へ、パスワード欄は何でもよい形で送ると、パスワードを知らないまま admin になれます。素のOR型を名前欄だけに入れても入れないことも、同じ画面で確かめられます。試すのは自分が権限を持つ練習用の環境だけにします。