SQLインジェクション・XSS・CSRFの違い|攻撃対象と対策を比較
SQLインジェクション、XSS、CSRF。どれも「Webサイトへの攻撃」なのは分かるけれど、選択肢で並ぶと区別がつかない。
セキュリティの問題で、この3つの名前が並んだ選択肢に迷ったことはありませんか?
先に答えをお伝えします。3つの違いは、攻撃者が何を狙い、どこで悪さをさせるかにあります。
SQLインジェクションはWebサイトの裏にあるデータベースを狙い、XSSは利用者のブラウザで不正なスクリプトを動かします。CSRFは、ログイン中の利用者になりすまして、本人が意図しない操作をWebサイトに送らせる攻撃です。
この記事では、まず3つを表で並べて違いをつかみます。そのあと1つずつ仕組み・被害・対策を説明し、最後に自作の例題で見分け方を練習します。
3つの脆弱性を表で比較する¶
最初に用語を1つだけ確認しておきます。脆弱性(ぜいじゃくせい)とは、プログラムや設定の弱点で、攻撃者に悪用されるおそれがある部分のことです。
3つとも、Webアプリケーションの作り方に原因がある脆弱性です。違いは次の表のとおりです。
| 項目 | SQLインジェクション | XSS(クロスサイトスクリプティング) | CSRF(クロスサイトリクエストフォージェリ) |
|---|---|---|---|
| 攻撃の対象 | Webサイトのデータベース | 利用者のブラウザ | ログイン中の利用者の権限 |
| 悪用される入力 | 検索欄やログイン欄の文字 | 掲示板やURLに埋め込んだスクリプト | 罠のページから送られるリクエスト |
| 不正な処理が動く場所 | データベース(サーバ側) | 利用者のブラウザ | Webサイト(本人の操作として) |
| 主な被害 | 情報の漏えい・改ざん・削除 | Cookieの盗み出し、偽の画面の表示 | 意図しない投稿・購入・設定変更 |
| 代表的な対策 | プレースホルダ(パラメータ化クエリ) | 出力時のエスケープ | トークンの確認、再認証 |
表の中のスクリプトとは、ブラウザの上で動く小さなプログラム(主にJavaScript)のことです。Cookie(クッキー)は、ログイン状態などを覚えておくためにブラウザに保存される小さなデータを指します。
見分けるための3つの問い¶
表を丸暗記しなくても、次の問いで見分けられます。問題文を読みながら、順に当てはめてみてください。
1つ目は、不正な文字がSQL文の一部として実行されているかどうかです。そうならSQLインジェクションです。
2つ目は、不正なスクリプトが利用者のブラウザで動いているかどうかです。そうならXSSを疑います。3つ目は、利用者が気づかないうちに、本人の権限で操作が送られているかどうかです。そうならCSRFです。
共通する原因は「入力をそのまま信じること」¶
3つに共通するのは、外から来たデータを、確かめずにそのまま使ってしまう作りです。SQLインジェクションとXSSは入力された文字を、CSRFは送られてきたリクエストを、そのまま信じてしまいます。
この共通点を押さえておくと、対策の考え方もつながって見えてきます。ここからは、1つずつ詳しく見ていきましょう。
SQLインジェクションの仕組みと対策¶
SQLとは、データベースに対して「このデータを取り出して」「この行を消して」と命令するための言葉です。SQLインジェクションは、入力欄にSQLの一部になる文字を入れて、開発者が意図しない命令を実行させる攻撃です。
インジェクションは英語で「注入」という意味です。命令文の中に、攻撃者の文字を注入するイメージで覚えると分かりやすくなります。
攻撃の流れを具体例で見る¶
ここでは、会員を名前で検索する画面を例にします。プログラムは、入力欄の文字をそのままつなげてSQL文を作っているとします。
SELECT * FROM 会員 WHERE 名前 = '(入力された文字)'
ふつうに「佐藤」と入力すれば、名前が佐藤の会員だけが取り出されます。ところが、攻撃者が次のような文字を入れたとします。
' OR '1'='1
つなげた結果のSQL文は、次のようになります。
SELECT * FROM 会員 WHERE 名前 = '' OR '1'='1'
'1'='1' はいつでも正しい条件なので、WHERE の条件全体が常に真になります。その結果、全会員のデータが画面に表示されてしまいます。
入力した文字の中の ' (シングルクォーテーション)が、文字列の終わりとして扱われたことが原因です。データとして渡したはずの文字が、命令の一部に変わってしまったわけです。
対策はプレースホルダで命令とデータを分けること¶
いちばん大切な対策は、プレースホルダを使うことです。プレースホルダとは、SQL文の中に「ここに値が入る」という印(? など)だけを置き、値はあとから別に渡す仕組みです。パラメータ化クエリとも呼ばれます。
SELECT * FROM 会員 WHERE 名前 = ?
この書き方では、SQL文の形が先に決まります。あとから渡された値は、どんな記号を含んでいても「ただの文字列」として扱われ、命令として解釈されません。
ほかにも、データベースのアカウントに必要以上の権限を与えないこと、エラーの詳しい内容を画面に出さないことも被害を小さくします。ただし、これらは補助の対策で、根本的な対策はプレースホルダです。
SQLの基本的な書き方に不安がある人は、先にこちらの記事でSELECT文の読み方を確かめておくと、攻撃の例も読みやすくなります。
【関連記事】基本情報のSQL問題の解き方|SELECT・WHERE・ORDER BYを例題で解説
XSS(クロスサイトスクリプティング)の仕組みと対策¶
XSSは、Webページに攻撃者のスクリプトを紛れ込ませ、そのページを見た利用者のブラウザで動かす攻撃です。正式な名前はクロスサイトスクリプティングで、略すとCSSになるのを避けてXSSと書かれます。
SQLインジェクションとの大きな違いは、被害を受ける場所です。SQLインジェクションはサーバ側のデータベースが狙われますが、XSSではページを見に来た利用者が被害を受けます。
掲示板を例にした攻撃の流れ¶
書き込んだ文字をそのまま表示する掲示板があるとします。攻撃者は、文章の代わりにスクリプトのタグを書き込みます。
<script>(Cookieを攻撃者のサーバへ送る処理)</script>
掲示板のプログラムがこの文字を加工せずにページへ出すと、ブラウザはそれをただの文字ではなく、実行するスクリプトとして読み込みます。そのページを開いた利用者のブラウザで処理が動き、Cookieが攻撃者に送られてしまいます。
Cookieにログイン状態が入っていれば、攻撃者はその利用者になりすましてログインできるおそれがあります。偽の入力フォームを表示して、パスワードを入力させる手口もあります。
対策は出力するときのエスケープ¶
XSSの基本の対策は、ページに文字を出力するときにエスケープすることです。エスケープとは、HTMLで特別な意味を持つ記号を、意味を持たない表記に置き換える処理です。
置き換えの代表例を表にまとめます。
| 元の記号 | 置き換えたあとの表記 | 元の記号の役割 |
|---|---|---|
| < | < | タグの始まり |
| > | > | タグの終わり |
| & | & | 特別な表記の始まり |
| " | " | 属性の値の区切り |
| ' | ' | 属性の値の区切り |
こう置き換えると、ブラウザは画面に「<script>」という文字を表示するだけで、スクリプトとしては実行しません。入力を受け取るときではなく、ページに出すときに行うのがポイントです。
あわせて、Cookieに HttpOnly という属性を付けると、スクリプトからそのCookieを読めなくなります。万一スクリプトが動いても、Cookieを盗まれる被害を減らせる補助の対策です。
CSRF(クロスサイトリクエストフォージェリ)の仕組みと対策¶
CSRFは、ログイン中の利用者に罠のページを開かせ、本人が意図しないリクエストを正規のWebサイトへ送らせる攻撃です。フォージェリは英語で「偽造」という意味で、リクエストを偽造する攻撃だと覚えられます。
XSSとの違いは、スクリプトを正規のサイトに埋め込む必要がない点です。攻撃者は自分で用意した別のサイトに罠を置き、そこから正規のサイトへ操作を送らせます。
銀行の送金画面を例にした攻撃の流れ¶
利用者がネット銀行にログインしたまま、別のタブで攻撃者の用意したページを開いたとします。そのページには、開いただけで送金のリクエストを銀行へ自動で送る仕掛けがあります。
ブラウザは、銀行へのリクエストにログイン中のCookieを自動で付けて送ります。銀行のサイトから見ると、本人がログインした状態で送金ボタンを押したのと区別がつきません。
その結果、利用者が知らないうちに送金や投稿、パスワードの変更などが行われてしまいます。攻撃者は利用者のCookieを盗む必要がなく、本人のブラウザに操作を代行させている点が特徴です。
対策は正規の画面から来たことを確かめること¶
CSRFの代表的な対策は、トークンを使う方法です。トークンとは、サーバが画面ごとに発行する、推測できないランダムな値のことです。
サーバは、送金などの大切な操作の画面にトークンを埋め込みます。リクエストを受け取ったら、トークンが正しいかを確かめ、合わなければ処理しません。
攻撃者の罠のページは、正規の画面に埋め込まれたトークンを知ることができません。そのため、偽造したリクエストは受け付けられなくなります。
ほかにも、送金や退会などの重要な操作の前にパスワードを入れ直させる再認証も有効です。Cookieに SameSite という属性を付け、別のサイトから送られるリクエストにCookieを付けにくくする方法もあります。
3つの違いを例題で確かめる¶
ここまでの内容を、自作の例題で確かめましょう。どれも、この記事のために作った問題です。
例題1:攻撃の名前を答える¶
次の説明に当てはまる攻撃の名前を答えてください。
Webサイトの問合せ欄に、攻撃者が入力した文字列がSQL文の一部として解釈され、登録されている全顧客のメールアドレスが表示された。
答えはSQLインジェクションです。「SQL文の一部として解釈され」という部分が決め手で、被害がデータベースの情報漏えいである点も表と一致します。
例題2:適切な対策を選ぶ¶
次の状況に対して、最も適切な対策を選んでください。
商品のレビュー欄に書き込まれたスクリプトが、レビューを読んだ別の利用者のブラウザで実行され、利用者のCookieが外部に送信された。
選択肢は、ア:プレースホルダを使ってSQL文を組み立てる、イ:レビューを画面に出力するときに特別な記号をエスケープする、ウ:重要な操作の前にパスワードを入れ直させる、の3つとします。
答えはイです。利用者のブラウザでスクリプトが動いているのでXSSと分かり、その基本の対策は出力時のエスケープです。アはSQLインジェクションの対策、ウはCSRFの対策なので、この状況には合いません。
例題で使える判断の手順¶
例題を解くときに使った考え方を、手順として表にまとめます。本番の問題文を読むときにも、この順番で確かめると迷いにくくなります。
| 順番 | 問題文で確かめること | 当てはまったときの答え |
|---|---|---|
| 1 | 入力した文字がSQL文の一部として実行されたか | SQLインジェクション |
| 2 | 利用者のブラウザでスクリプトが実行されたか | XSS |
| 3 | 利用者が意図しない操作が、本人の権限で送られたか | CSRF |
| 4 | 対策を問われたら、上で決めた攻撃の対策を選ぶ | プレースホルダ/エスケープ/トークン |
選択肢には、別の攻撃の対策がもっともらしく混ぜてあることがよくあります。先に攻撃の種類を決めてから対策を選べば、取り違えを防げます。
試験での問われ方と学習の進め方¶
基本情報技術者試験では、科目Aで攻撃の名前と仕組み、対策の組み合わせが問われます。科目Bの情報セキュリティでは、事例の文章を読んで、どんな対策が適切かを判断する力が求められます。
科目Bの事例問題は、文章が長く、用語を知っているだけでは解きにくいことがあります。長文の読み方や選択肢の絞り方は、こちらの記事で詳しく解説しています。
【関連記事】科目Bのセキュリティ事例問題が解けない人へ|長文の読み方と選択肢の絞り方
Webの脆弱性は、情報セキュリティ分野の一部です。分野全体で何を勉強すればよいかは、次の記事で科目A・科目Bの両面から整理しています。
【関連記事】基本情報の情報セキュリティは何を勉強する?科目A・科目Bの対策を解説
科目Bの情報セキュリティに、擬似言語とどう時間を配分するかは親記事で解説しています。勉強の計画を立てるときに読んでみてください。
【関連記事】基本情報 科目Bの情報セキュリティ対策|擬似言語との勉強時間の配分を解説
私たちの Giji Academy のセキュリティ講座では、会社のネットワーク構成をシミュレーターに出しながら、科目Bの情報セキュリティの考え方を学べます。Webサーバやデータベースが構成のどこにあり、どこで対策をとるのかを図と一緒に確かめたい人は、セキュリティ講座から始めてみてください。
まとめ¶
SQLインジェクションは、入力した文字をSQL文の一部として実行させ、データベースの情報を盗んだり書き換えたりする攻撃です。対策の基本は、プレースホルダで命令とデータを分けることです。
XSSは、ページに紛れ込ませたスクリプトを利用者のブラウザで動かす攻撃で、出力時のエスケープが基本の対策になります。CSRFは、ログイン中の利用者に意図しない操作を送らせる攻撃で、トークンの確認や再認証で防ぎます。
見分けるときは、不正な処理がどこで動いているかに注目してください。データベースならSQLインジェクション、ブラウザならXSS、本人の権限で操作が送られているならCSRFです。
3つの名前と対策の組み合わせは、今日の比較表を見ながら一度自分で書き出してみると定着します。仕組みが分かれば、問題文の言い回しが変わっても落ち着いて答えを選べるようになります。