攻撃から学ぶSQLインジェクション対策

#はじめに
このシリーズも第3回を迎えることができました。

様々なセキュリティについて継続的に学び、WEBエンジニアとしての基礎を固めていきましょう。
他の記事に興味がある方は、是非読んでみてください。

[攻撃から学ぶCSRF対策](https://qiita.com/risto24/items/e449c5edf648020258fa)
[攻撃から学ぶXSS対策）](https://qiita.com/risto24/items/70625bb6631ad12266d3)

また、本記事の内容は様々な文献をもとに自身で調べ、試したものをまとめています。
至らぬ点や、間違いがありましたら、コメントにてご指摘をお願いします。

#試したら犯罪になります
今回の記事は説明だけでは分かりにくいトピックなので、実際にコードを踏まえて説明します。

**簡易的なものではありますが、組み合わせ、書き加えることで、実際に有効な攻撃手法になります。**

実際に他社のサービスに試すと捕まる可能性があります。
試すときは仮想環境または自分のサービスにしてください。

本記事を元に行われた事象について、筆者は一切の責任を受けかねます。

#SQLインジェクションって何？
SQLインジェクションとは、セキュリティ上の不備を意図的に利用し、システムが想定しないSQL文を実行させることにより、データベースシステムを不正に操作する攻撃方法のことです。

と言われてもパッとしないですよね。

簡単に言うと、ログイン画面に対して

**「僕が正しいユーザーがチェックしてね。　あ、ついでに他のデータも全部ちょうだい！」**

のような要望を行う攻撃手法です。
#攻撃方法
では実際の事例を踏まえて、攻撃方法を学んでいきましょう。

###不正ログイン ver.
ユーザーネームとパスワードからなる、よくある構成における、SQLインジェクションの例をみてみましょう。

ネームとパスワードを元に、以下のようなSQLで認証を行なっていたとしましょう。

```
SELECT * FROM Users WHERE Name ="'ユーザーネーム'" AND Pass ="'パスワード'"
```

攻撃者が、ユーザーネームとパスワードを入力するテキストボックスに `" or ""="` を挿入すると、以下のようなSQLが発行されます。

```
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
```

SQLをご存知の方はお分かりかと思いますが、このSQLはTRUEとなります。
このように `" or ""="` は常にTRUEであるため、 攻撃者はパスワードを入力するテキストボックスに `" or ""="` を挿入するだけで、データベース内のユーザー名とパスワードにアクセスできます。

###非表示データの取得 ver.
サービスで削除済みのユーザーを論理削除（完全に消すのではなくフラグなどで非表示にする事）していた場合に、会員情報一覧を取得する際に以下のようにリクエストを発行していたとします。

`https://some-service.com/user?type=user`

この際に以下のようなSQLを発行していると仮定します。

```
SELECT * FROM user WHERE type = 'user' AND deleteFlag = 0
```

攻撃者が以下のようにリクエストを発行したとします。

`https://insecure-website.com/user?type=user'--`

すると以下のようなSQLが発行されます。

```
SELECT * FROM user WHERE type = 'user'--' AND deleteFlag = 0
```

SQLをご存知の方はもうお分かりですね。
二重ダッシュシーケンス `--` はSQLのコメントインジケーターであり、SQLの `--` 以降の部分がコメントとして解釈され `AND deleteFlag = 0` は含まれなくなります。
つまり、削除済みのユーザーも表示させる事ができてしまうという事です。

#SQLインジェクションの怖さ
SQLインジェクションには以下のような怖さが潜んでいます。

###秘密情報・個人情報の漏洩
ECサイトなどの場合、ユーザーのID・パスワード・クレジットカードの番号・住所などといった情報が満載です。
攻撃者がデータベースを不正に操作するという事は、これらの情報が全て奪われる可能性があるという事です。

###サービスの破壊
SQLを自由に発行できるという事は、データベース構造の変更も容易にできてしまうという事です。
先ほどのECサイトを例に挙げると、サービスはユーザーを識別するためにユーザー情報を格納するテーブルを用意しているはずです。

そのテーブル自体を削除してしまえば、システムは予期せぬエラーを出力する事でしょう。
このように、実行する事でサービス自体の機能を停止させる事も可能になってしまいます。

#SQLインジェクションの対策

SQLインジェクションは、アプリケーションがデータベースに対して行うクエリを攻撃者が妨害できるようにするWebセキュリティの脆弱性です。

このタイプの攻撃を防ぐには、攻撃者に自由にSQLを発行させないように対策を行う必要があります。

僕たちWEB開発者ができる対策を挙げてみましょう。
対策の細かい設定は別に調べてもらった方がいいと思うので簡略的に説明します。

###エスケープ処理
エスケープ処理はSQLに対して最も基本的で有効的な対策のひとつです。
たとえば、シングルクォート `'` は通常の言語では文字列として認識されますが、プログラムではSQL内で使うようなシングルクォートは命令文を識別するための特殊な意味が与えられています。

そのため、サイトやアプリケーションの情報入力画面でシングルクォートが使われた場合に、特殊な記号としてではなく、一般的な文字列として認識するように処理する必要があります。

これによってSQLインジェクションの脆弱性そのものを取り除く事ができます。

###データベースのアカウント権限の制御
これは、もしもSQLインジェクションを実行されてしまった際の、最終保険として行うものです。
アプリケーションからデータベースへ発行できるSQLを、予め制限しておく事で、もし攻撃者から不正なSQLを発行されても、被害を最小限に抑えられる事ができます。

###WAFの導入
WAF（ウェブアプリケーションファイアウォール）は、SQLインジェクションや、XSS、ゼロデイ攻撃のようにWEBアプリケーションの脆弱性を狙った攻撃を防御するためのシステムです。

これらを導入することによって、アクセス後のユーザーが不審な行動をしていないかをチェックします。
また、クライアントとサーバーの通信内容を検査することで本来ならば流出しないはずのデータがレスポンスの中に含まれていないかどうかを検査してくれます。

導入コストが高いことや、運用に専門的な知識が必要な事がデメリットではありますが、セキュリティまで気が回らないスタートアップや、セキュリティ人材の確保における費用削減が期待されます。

###外部の脆弱性診断サービスを利用する
脆弱性診断サービスは、外部から擬似的な攻撃を行い、悪用されると危険な脆弱性があるかどうかを判断するものです。

SQLインジェクションだけではなく様々な攻撃手法を擬似的に行なってくれるので、自身のWEBサイトが安全かどうかを、判断する事ができます。
運営しているWEBサイトの課題を明確に把握する事で、さらなる品質の向上が見込めるでしょう。

#まとめ
僕も含め、SQLインジェクションという言葉だけは知っているが、対策や攻撃方法は知らないという方も多いのでは無いでしょうか？

攻撃方法を知り、防御策を徹底することで、ユーザを犯罪に巻き込む危険性を最小限に抑えることができます。

セキュリティ関連の記事を書くたびに、様々な脆弱性や危険性に気がつく事ができて、サービスを開発・運営するものとしての責任を改めて感じますね。

また、今回も様々な文献を参考にさせて頂きました。
詳しく知りたい方は、是非読んでみてください。

###参考文献
[SQLインジェクション攻撃の方法と対策](https://www.shadan-kun.com/blog/measure/5613/)
[SQLインジェクション攻撃への対策｜脆弱性を悪用する仕組みと具体例](https://blogs.mcafee.jp/sql-injection-prevention#3SQL)
[SQL injection](https://portswigger.net/web-security/sql-injection)
[SQL Injection](https://www.w3schools.com/sql/sql_injection.asp)
[SQLインジェクションの概要と対策方法](https://www.kagoya.jp/howto/network/sql-injection/)