SQLインジェクション入門:仕組みと対策
SQLインジェクションの章をまとめる
この回でやること
データベースから正しい直しと再検証まで、章の全体を1本の物語に束ねます。演習で自分の手に通し、同じ穴が検索や並び替えにも現れることと、次に何を読むかを示します。
- 読む 約 10 分
- 最後にクイズ 1 問
このレッスンで学ぶこと
この章でたどった道は、データベースとSQLから穴の生まれる理由、崩し方と見分け方、そして正しい直しと再検証までが1本につながっています。この回はそれを線にまとめ直し、章末の演習を1つの物語として通して、同じ穴が現場のどこに現れるかを確かめます。
読み終えると、手口の名前ではなく原因の一点から、この章のすべてを説明し直せるようになります。
この章でたどった一本道
出発点は、SQLがデータベースへの命令の言葉だということでした。アプリが入力を文字列として連結してSQLを組み立てると、値と命令の境界が消えます。そこから、閉じる・足す・消すの3手で条件式を書き換えられること、ログインでは AND が OR より先に結ばれるので名前欄とパスワード欄で通り方が変わることを見ました。壊す前に、反応の差でその欄がSQLに届いているかを見分ける段も置きました。
直す方向は一貫して「値を命令の組み立てに参加させない」でした。前回まででその具体をプレースホルダとして固め、直ったことの確認は攻撃と正規利用の両方を流すのだと確かめました。手口の名前は増えても、原因と直し方はこの1本に戻ります。
演習で1本にまとめる
章末の演習 sqli-login-bypass-lab は、この道を自分の手でたどる場です。まず tanaka のアカウントで普通にログインし、応答に出るSQLで自分の入力がどこに現れるかを見ます。次に名前欄へ admin' -- を入れ、パスワードを知らないまま admin として入れることを確かめます。' OR '1'='1' -- や ' OR 1=1 --、パスワード欄への ' OR '1'='1 でも通り抜けられます。
そのあと原因を選び、値を命令から切り離す方針で直します。再検証では、攻撃が止まるだけでなく o'brien と taylor が今までどおり入れることまで自動で流れます。シングルクォートを取り除く方針や語を弾く方針を選ぶと、攻撃は止まってもここで赤が出ます。試すのは自分が権限を持つ練習用のこの環境だけにします。
現場で何を見るか
同じ穴は、ログインだけの話ではありません。検索、並び替え、絞り込み、ページ送りなど、入力を使ってSQLを組む場所すべてに同じ形で現れます。
JavaScript
query = "SELECT name, role FROM users WHERE name = '" + input + "'"コードを読むときは、こうしてSQLの文字列に入力を + で継ぎ足している箇所を探します。見つけたら、そこがプレースホルダで値を別に渡す形になっているかを確かめます。ORMを使っていても、生の文字列を連結してから渡す口が残っていれば穴は同じです。
危ない語を探すのではなく、入力がSQLの文字列へ連結されている箇所を探します。連結があれば、そこが値と命令の境界を失う場所です。語の一覧ではなく、組み立ての形を見ます。
起きます。原因は画面の種類ではなく、入力を文字列として連結する組み立て方にあるからです。ログインで見た ' OR 1=1 -- は、検索欄では返る件数を全件に変える形で同じように効きます。入り口が違うだけで、境界が消える仕組みは同じです。
次に読むもの
この先の章では、認証そのものの弱さを扱います。パスワードの試行回数、多要素認証の抜け道、パスワード再発行の穴など、SQLインジェクションとは別の切り口でログインを崩す手が続きます。この章で見たブラインドや時間差の手は、応答が返らなくても同じ原因が生き続けることを示していました。この先は、それらを自動で回す道具や、OSコマンド、NoSQLといった別の注入へ、同じ「値と命令が混ざる」構図が広がっていきます。