どのように脆弱性を作りこんでしまうのか

SNSを題材に、どのように脆弱性を作りこんでしまうのか考えてみる
Webアプリケーションとセキュリティへの対応は切っても切り離せない問題です。この記事では、自分たちでWebアプリケーションを開発するにあたり、どういった箇所に対してそれぞれどのようなセキュリティの注意点があるのか、どのような脆弱性を作りこんでしまうのかをイメージしやすくするために、SNSの実装を例に考えてみることにします。
SNSの機能
ここで想定しているSNSは、以下のような機能を持つものとします。
- メールアドレスとパスワードでログインする
- 200文字以内の好きなテキストを投稿できる
- 投稿されたテキストにURLを含めていた場合、画面上ではそのWebサイトの内容がサムネイル表示される
- 他の人の投稿に対しては、ひとつの投稿に一度だけ「いいね」を付与することができる
- 自分の投稿は自分で削除することができる
実用的なSNSであれば他にもたくさんの機能が必要ですが、いったんはこの範囲の機能だけを考えることにします。

SNSイメージ
ログイン機能に関するセキュリティの注意点
このSNSのログインは、事前に登録したメールアドレスとパスワードによるものとします。
ログイン画面は、他人になりすまそうとする攻撃者から常に不正ログインを試みようと狙われています。弱いパスワードを付けているユーザーや他のサービスと同じパスワードを利用しているユーザーは特に不正ログインの対象となりやすいでしょう。
参考記事:ログイン画面を狙った攻撃
また、不正ログイン以外にもセキュリティ上気を付けなければいけない点はあります。
仮にログイン失敗時に画面に表示されるメッセージが「メールアドレスが違います」「パスワードが違います」のようなものだった場合、メールアドレスの登録の有無がメッセージから判断できます。攻撃者はこの挙動を利用することで、サービスに登録されているメールアドレスを収集することができてしまいます。
さらに、ログイン処理の実装のSQLインジェクションも考えられます。実際のログイン処理の内部的な実装は、入力されたメールアドレスとパスワードについて、データベース内にそれらと一致するレコードが存在すればログイン成功、一致するレコードがなければログイン失敗のようになることが一般的です。
このとき、入力されたメールアドレスおよびパスワードを利用してSQLを作成していたとすると、SQLインジェクションが発生しやすくなり、それによりログイン処理を回避して不正にログインされる、データベースの情報が漏えいするといった被害につながる可能性があります。

SNSログイン画面のイメージ
テキスト投稿に関するセキュリティの注意点
SNSにログインすると200文字以内のテキストが投稿できますが、文字数のチェックが正しく行われていないと仕様で定められている200文字を超えるテキストが投稿される可能性があります。
テキストを投稿した日時についても、サーバー側で取得するのではなくクライアントから送信した日時を使っていると、ユーザーによって未来や過去の日時に加工された投稿が行われる可能性もあります。
文字数の制限を超えた投稿や日時を加工した投稿が行えるという点を、セキュリティ上の問題として取り扱うべきかどうかは判断が分かれるところですが、ここでは仕様を逸脱した異常な挙動によってサービスの信頼を損ねるということで、いったんはセキュリティ上の問題点であるとします。
また、投稿するテキストに HTML タグの <script> などの文字列が含まれており、それがそのままHTMLの一部として解釈されてしまうと、ユーザーによって作成された任意のJavaScriptがSNS内のHTMLに埋め込まれてしまうことになります。
このような、任意のJavaScriptがHTMLに埋め込まれてしまう脆弱性をクロスサイトスクリプティング、略して XSS といいます。

SNS テキスト投稿のイメージ
投稿するテキストに含まれるURLに関するセキュリティの注意点
このSNSにはURLを投稿したときにそのWebサイトの概要がサムネイルとして表示される機能がありますが、ここにもセキュリティ上注意すべき点があります。
投稿に含まれるURLがリンクとなる場合に、http や https だけでなく “javascript:” で始まる javascript スキームのURLもリンクとして有効になってしまうと、投稿を見たユーザーがそのリンクをクリックすると投稿者によって作成されたJavaScriptが動作する、クロスサイトスクリプティングが発生することになります。
また、URLとして http://192.168.0.1/ のようにイントラネット内のアドレスを投稿すると、Webアプリケーションの動いているサーバーからイントラネット内のサーバーに対してのリクエストが発生し、その結果がSNSに投稿されることになり、イントラネット内の情報が漏えいすることになります。
このような脆弱性はサーバーサイド・リクエスト・フォージェリ、SSRFと呼ばれます。

SNS URL投稿のイメージ
投稿への「いいね」付与に関するセキュリティの注意点
SNSにはそれぞれの投稿に「いいね」を付けられる機能があり、ひとつの投稿に一人1回だけ「いいね」を付けられるという制限があるとします。
この「いいね」の付与や取消しに関連する問題を考えてみます。
「いいね」をつけるときのサーバー内の処理として、①対象の投稿にすでに「いいね」がつけられているかどうかをまず検証し、②その結果まだ「いいね」がつけられていなければ、その投稿に対して「いいね」を付けるという処理になっていたとします。
このような実装では、①の「いいね」がつけられているかの検証と実際に②で「いいね」を付けるタイミングにわずかに差があるため、このタイミングの差を狙って連続して「いいね」を付けるためのリクエストを発行することで、ひとつの投稿に対して複数の「いいね」が与えられることになります。
同じように、「いいね」の取消に対しても、複数回の取消リクエストを同時に発行することで、いいねの総数をマイナスに減らすことができる可能性があります。
このような、処理を進める条件の検証と実際に処理が行われる時間に差があることによって生じる問題を「レースコンディション」と呼びます。

SNS「❤いいね」のイメージ
投稿の削除に関するセキュリティの注意点
SNSでは削除ボタンを押すことで自分の投稿に限り削除できます。
このとき、削除リクエストに対応するサーバー上の処理として、削除対象のテキストを投稿したユーザーと、削除のリクエストを発行したユーザーが同一であるかを検証していないとすると、本人のものではない第三者の投稿を、本人の許可なしに削除できてしまうことになります。
このように、処理に応じてユーザーに適切な権限があるのかの確認漏れにより発生する問題を、認可制御の不備といいます。
参考記事:アクセス制御、認可制御

SNS投稿削除のイメージ
まとめ
ここまでで、SNSを題材に、それぞれの機能に対して発生しそうなセキュリティの問題点のいくつかの例を紹介しました。
ここまでに紹介したもの以外にも、Webアプリケーションでは様々な機能に対して、それに関連したセキュリティの問題点が発生し得ます。
下の表では、実装しようとする機能に対して発生する可能性のある脆弱性や、その機能に対して発生し得る攻撃手法などをまとめています。
表の左側にはWebアプリケーションで実装されるそれぞれの機能、表の右側にはその機能を実装するときに発生しがちな代表的な脆弱性や攻撃手法を掲載しています。
どのような機能の実装時にどのような脆弱性を作りこんでしまうのかの参考にしてください。
| 実装する機能 | 発生する脆弱性や関連する攻撃手法 | |
|---|---|---|
| ログイン処理 | 認証機能の突破、セッションに関連する問題 | |
| ユーザーごとの機能 | 認可制御の問題、強制ブラウズ | |
| データの 入出力 |
全体 | パラメータ操作、コードインジェクション |
| HTMLの出力 | クロスサイト・スクリプティング(XSS) | |
| データベースへの アクセス |
SQLインジェクション | |
| ファイルへのアクセス | ディレクトリトラバーサル | |
| 外部コマンドの実行 | OSコマンドインジェクション | |
| サーバー上で状態が変化する処理 | クロスサイト・リクエスト・フォージェリ(CSRF) | |
| エラー処理 | エラーメッセージによる情報漏えい | |
| サーバーからのリクエスト発行 | サーバーサイド・リクエスト・フォージェリ(SSRF) | |
| 正規表現の使用時 | 正規表現によるDoS(ReDoS) | |
| アプリケーション全体 | レースコンディション、バックドアやデバッグモードの残存 | |

