動画はこちら↓
今回は、SQLインジェクションという攻撃手法について解説していきます!
SQLは知ってるけど、インジェクションって何だろう?
SQLインジェクションはシンプルな攻撃だけど、データを盗んだり壊したりする危険な攻撃手法だよ。この記事でしっかり理解していこう!
SQLインジェクションとは、アプリケーションがデータベースと通信するときの安全性を脅かす攻撃方法の1つです。データベースのクエリ、SQL文ですね。に悪意のあるコードを挿入することで、機密データを不正に取得したり、不正な操作を実行したりすることができます。
データベースには、ユーザーのログイン情報や商品情報、予約管理データとか、大事なデータがいろいろ入ってるよね。
うんうん。Webアプリケーションで扱う多くのデータがデータベースに保存されているね。このデータを安全に操作するためにSQLという言語が使われるんだけど、それを悪用した攻撃になります。
SQLを悪用されるとどんな危険があるの?
例えば、機密情報の漏洩やデータの改ざんそして、サーバーやアプリケーションへのさらなる攻撃の足がかりにされるなどがあるよ
データの漏洩だけじゃなく、改ざんの危険もあるんだね!やろうと思えば色々できちゃうかも...
うんうん。
じゃあ、SQLインジェクションの仕組みについて、簡単な例を見てみよう!
このように、ユーザーの入力値をそのままSQLに組み込むコードがあるとします。ユーザーが入力した値を条件としてSQL文の中に入れて、ユーザー情報を検索する処理になっているよ。
ここで、IDにユーザーが「1’ OR 1=1;--」と入力したとします。
すると、作られるSQLはこうなるね。
1 OR 1=1ってどういう意味?
1 OR 1=1をこのSQLに組み込むと、「idが1、または1=1」が検索の条件になるよ。1=1は常に真だから、結果として全てのユーザー情報が取得されてしまいます。
えっ、それじゃあどんな情報でも引き出せちゃうってこと?
その通り!これがSQLインジェクションの怖さだよ。そしてさらに、それ以降は「--」の後ろだからコメント扱いになって、無視されちゃいます。
なるほど。元の文を無視して勝手に条件を変えられちゃうなんて怖い!
それではいくつかの代表的な攻撃手法を紹介していきます!
まずはエラーベース攻撃です。データベースのエラーメッセージを利用して構造や情報を探る方法だよ。わざとエラーが発生するようなSQLを実行させて、エラーメッセージの中にカラム名とかデータの内容を表示させて情報を探ります。
エラー内容でそんなに分かっちゃうの!?エラ〜メッセージは普段開発する時には便利だけど、利用者に見えてしまうと良くないんだね。
そうそう。そもそも詳細なエラーメッセージをユーザーに見せる必要はないから、出ないように設定しておくことも大事だよ。
UNIONキーワードを利用して、元のクエリの結果に追加の情報を含める方法だよ。例えば、さっきの例のuserInputにこんな値を入れます。
すると、全体はこうなるよ。
一行目の部分、元のクエリではusersテーブルのusernameを取得しているけど、攻撃者はUNIONを使ってadminテーブルのpasswordを取得しようとしているよ。
元々はusernameだけを取ってくるSQLだったのに、勝手に別のテーブルのpasswordも取ってくるように変えられちゃうんだね。。
これを見ると、usersテーブルだけ検索するSQLだから攻撃されても大丈夫!と安心することはできないってわかるね。
ログインフォームがこのようなSQLで処理をしていたとします。
このSQLで検索して結果が取得できればIDとパスワードが一致しているとしてログインができるよ。
もしIDがわかっていれば、パスワードとして最初の例のように入力することで、認証をパスできてしまう場合があります。
さっきと同じでパスワードの条件が常に正になっちゃうから、IDさえあってれば取得できちゃうのか。こんな簡単な方法でログイン回避できちゃうんだね。。。ログインを回避できたらさらに被害が広がっちゃいそう。
そうなんだ。SQLインジェクションではパスワードが漏洩する危険もあるし、そもそもパスワードがわからなくてもログインされてしまう危険もあるよ。他にもUPDATE句を付け足してデータを改ざんしたり、色々な攻撃ができます。
怖いな...どうやって対策すればいいんだろう?
じゃあ最後に対策を説明するね!
それでは、SQLインジェクションの対策について説明していきます。
SQLインジェクションの根本的な原因は、パラメータとして渡した文字列の一部が文字列ではなく構文の一部として扱われてしまうことです。
さっきの例だと、条件として入力した”1’ OR 1=1;--”がそのまま条件として扱われていれば問題ないよね。
こんな感じで、idが「1’ OR 1=1;--」の時、っていう条件になるってことだね。それなら単純にそういう文字列として扱われるだけだから問題なさそう。
そうそう。なので対策としては、プレースホルダを使ってSQLを組み立てることで、渡したパラメータを正しくパラメータとして扱い、SQL文自体が変更されてしまうのを防ぎます。
プレースホルダ?
プレースホルダとは、SQL文において実際の値を一時的に置き換える特殊な記号や文字列のことだよ。
こんな感じで、一時的に置き換える記号や文字列をパラメータが入る場所に埋め込んでおき、パラメータを当てはめることでSQL文を作成します。
言語によって書き方は変わるけど、例えばPythonだとこんな感じで書くことができるよ。
パラメータを直接文字列に埋め込まずに、メソッドの中で当てはめるって感じなんだね。
そうそう。SQLインジェクションの対策としては、これが根本的対策になります。
そして他にも気をつけることがいくつかあるよ。
まずは詳細なエラーメッセージを出さないことです。
さっき紹介したエラーベースSQLインジェクションで利用されてしまう可能性があるからだね!
そうそう!次に、データベースの権限設定です。
アプリケーションが利用するデータベースユーザーに対しては、アプリケーションで必要な最低限の権限だけを与えるようにすることで、意図しない読み出しや書き込みを防ぎます。
例えば情報を表示するだけのアプリケーションだったら、書き込み権限はいらないもんね。万が一攻撃を受けてしまっても被害を最小限に防ぐことができるね。
うんうん!そして最後に、入力値の検証です。例えばIDだったら数値の入力のみを許可するとか、制限をしておけば防げる攻撃もあります。
確かに!でも、数値以外も入力できる入力欄ももちろんあるだろうから、この対策だけじゃ不十分だね。
その通り!基本的にはプレースホルダの対策を必ず行うようにして、追加でこのような対策も行っていくことでセキュリティが強固になっていくよ。
今回はSQLインジェクションについて解説しました!
SQLインジェクション攻撃が行われてしまうと、データベース内のすべての情報が流出する可能性があるほか、改ざんされる可能性もあり、かなり危険なものになります!
怖いね...。必ずプレースホルダの対策を行うことが大切だね!
動画の方も、是非是非ご覧ください!