前置き
セキュリティのお勉強を始めてみたいということで、PortSwigger Academyを完走するついでに備忘録を残そうと思い記事を書いている。
PortSwiggerとはポートスキャンなどで用いられるjavaアプリケーションの一つであるBurp Suiteを開発した会社である。この会社がセキュリティ学習教材を提供しているとのことで、とりあえずここから触れていこうと思う。
筆者のスペック
- 情報系修士学生
- セキュリティのバックグラウンドはなし、初学者とほぼ同等
- javaやpythonでの開発をちらほら
この記事はportswiggerの内容と自分で調べたもので構成されている。専門家でも何でもない人間の記事であるため、事実と異なる点があれば是非教えてほしい。
PortSwigger Academy APPENTICE
Learning Pathsというものが用意されており、APPRENTICEとPRACTITIONERの二つのコースがあるようだ。英弱なりに調べたところ見習いコースと実践コースということで、まずはAPPRENTICEから挑戦していくことにした。
以下は座学の部分のメモであり、実際のサイトには演習も含まれているので、興味を持った人は是非直接講座を受けて見てほしい。
Path traversal
パストラバーサルとはどういうものか。
パストラバーサルは日本語だとディレクトリトラバーサル攻撃という名前の方が親しまれていると思う。
パスとはPC内でのファイルの格納場所を表す文字列のことである。ファイルやディレクトリ操作をするプログラムに不正なパスを挿入されてしまうことにより、本来意図しないファイルの表示が行われる攻撃である。
例えば以下のような任意のファイルを読み取られてしまう場合がある。
- アプリケーションのコードやデータ
- バックエンドの認証情報
- システムファイル
また、読み取りだけではなくファイルへの書き込みやアプリケーションの動作変更、サーバーの制御を乗っ取られるなどの影響を受ける可能性もある。
では具体例を見てみよう。
よくあるショッピングサイトを想像して見てほしい。そこには売り物の写真がたくさん表示されているはずだ。写真をロードして表示するhtmlコードはおそらくこのようなものになるだろう。
<img src="/loadImage?filename=218.png">
loadImageURLはfilenameをパラメータとして受け取り、画像ファイルのデータを返している。このファイルは以下の場所に格納されているとする。
/var/www/images/
画像データを返すためには、アプリケーションはこのベースとなるディレクトリのパスの末尾にファイル名を加えてファイルシステムのAPIを使用して画像の要求を行う必要がある。つまり、アプリケーションは先ほどのコードを実行する際以下のパスの中身を読むのだ。
/var/www/images/218.png
では、このアプリケーションにパストラバー猿の対策が施されていない場合一体どのようなことが起きるのか。
攻撃者は例えば以下のようなURLをリクエストとして送信する。
https://insecure-website.com/loadImage?filename=../../../etc/passwd
../は一つ前のディレクトリを指す。つまりシステムのルートディレクトリからパスワードファイルを読み取ろうとしているのだ。
/etc/passwd
これはLinuxやMacOSなどUnixベースのOSを使うシステムのログインに使われるユーザ情報などが格納されているファイルである。よってこのリクエストが実行されると、攻撃者はシステムのログイン情報を入手することができるのだ。このやり方でファイル情報を入手できるとわかった攻撃者はきっと次々と大切なファイルを奪っていくだろう。
余談だが、Windowsでは../と..\の両方が使用できる。
先ほどの攻撃を別の方法でWindowsOSのシステムを対象に行うなら以下のようになる。
https://insecure-website.com/loadImage?filename=..\..\..\windows\win.ini
Access Control
では上記のような攻撃に対して対策をするにはどうしたら良いのか。
その一つの解は正しいアクセス制御を行うというものである。
そもそもアクセス制御とは、APIの実行やリソースへのアクセスに誰に、何を許可するかに関する制約をつけることをいう。Webアプリケーションではアクセス制御は主に認証とセッション管理に大きく依存する。
- 認証
- ユーザーが本人であることを確認する。
- セッション管理
- 同じユーザーによってその後のどのHTTPリクエストが行われているかを識別する。
- アクセス制御
- ユーザーが実行しようとしているアクションの実行を許可して良いものかどうかを決定する。
このアクセス制御が破綻していると、重大なセキュリティ脆弱性を引き起こしてしまう可能性がある。
代表的なセキュリティ脆弱性として以下のものが挙げられます。
Vertical pricilege escalation
ユーザーがアクセスを許可されていない機能にアクセスできることを、垂直権限昇格という。例えば、管理者以外のユーザーがユーザーアカウントを削除できる管理ページにアクセスできることは垂直権限昇格が引き起こす状態の一つである。
この脆弱性は多くの場合アプリケーションが機密機能に対しての保護をおろそかにすることにより発生する。例えば、管理機能は管理者のwelcomeページにはリンクがあるが、ユーザーのwelcomeページにはリンクが存在しないと言う場合があるとしよう。しかし、このような場合でもユーザーは関連する管理URLをリクエストすることで管理機能にアクセスできてしまうことがあるのだ。
例えば、サイトは以下のようなURLで機密情報をホストしている可能性がある。
https://insecure-website.com/admin
上記にアクセスできるような状態だと、robots.txtファイルが他の場所で公開されてしまうことだって起こり得るかもしれない。
robots.txtファイルは検索エンジンのクローラ (検索エンジンがインターネット上にあるサイトから情報を収集するために巡回させているロボット) にサイトのどのURLにアクセスして良いかを伝えるものであり、下手したら管理画面がクロールされ検索結果に表示され始めるなんてことが起こってしまうかもしれない。
URLでのアクセスを制限していない場合、例えURLがどこにも公開されていないとしても攻撃者はワードリストなどを使用して機密情報が置いてある場所を総当たり攻撃で探し当てることができる可能性があるのだ。
Security by obscurity
アクセス制限以外にも、予想しずらいURLを与えることで機密性の高い機能を隠蔽することができる。
これが隠蔽によるセキュリティと呼ばれるものである。
しかし、攻撃者は様々な方法で難読化されたURLを発見する可能性があるため、効果的なアクセス制御になるとは言えないだろう。
以下のURLで管理機能をホストするアプリケーションを想像してほしい。
https://insecure-website.com/administrator-panel-yb556
確かにこのURLは攻撃者にとって推測しずらいだろう。しかし、URLはUIを構築するJavaScriptによって開示される場合がある。
<script>
var isAdmin = false;
if (isAdmin) {
...
var adminPanelTag = document.createElement('a');
adminPanelTag.setAttribute('https://insecure-website.com/administrator-panel-yb556');
adminPanelTag.innerText = 'Admin panel';
...
}
</script>
このスクリプトは、ユーザーが管理ユーザーの場合、そのユーザーのUIにリンクを追加するというものである。しかし、URLを含むスクリプトは、ロールに関係なく全てのユーザーに表示されてしまう。このように、意図しない場所からURLが露見する可能性があるため、ただ難読化するだけではセキュリティとしては不十分なのだ。
Parameter-based access control methods
一部のアプリケーションは、ログイン時にユーザーのアクセス権やロールを決めて、その情報をユーザーが制御可能な場所に保存する。
例えば以下のようなものが挙げられるだろう。
- 隠しフィールド
- クッキー
- クエリ
アプリケーション側は送られてきた値をもとにアクセス制御を行う。
例えばこのように。
https://insecure-website.com/login/home.jsp?admin=true
https://insecure-website.com/login/home.jsp?role=1
しかし、これでは攻撃者は値を変更することで管理機能などの権限のない機能にアクセスできてしまう可能性があり、これは正しい対処法とは言えない。
Horizontal privilege escalation
ユーザーがそのタイプの自分のリソースではなく、別のユーザーに属するリソースにアクセスできるようになっていることを水平権限昇格という。従業員が自分のレコードだけでなく他の従業員のレコードにもアクセスできる場合などのことである。
例えばユーザーが次のURLを使用して自分のアカウントページにアクセスできるようなアプリケーションがあるとする。
https://insecure-website.com/myaccount?id=123
この場合攻撃者がidパラメータ値を別のユーザーの値に変更すると、別のユーザーのアカウントページ及び関連データにアクセスできてしまう可能性がある。一部のアプリケーションでは増加する番号の代わりにグローバル一意識別子(GUID)を使用することで攻撃者が別のユーザーの識別子を推測または予測することを防いでいるケースもある。
多くの場合、水平権限昇格はただ他のユーザーのリソースにアクセスするだけでは終わらない。より強い権限を持つユーザーのリソースにアクセスして、垂直権限昇格を始めることが多い。
Authentication
Authentication vulnerabilities
認証について理解することはセキュリティを学ぶにあたって必要不可欠なことである。
認証の脆弱性により、攻撃者は機密データや機能にアクセスすることができるようになるかもしれず、得られた情報をもとに更に追加の攻撃をしてくる可能性もあります。
このセクションでは以下について説明していく。
- Webサイトで使用される一般的な認証メカニズム
- そのメカニズムの潜在的な脆弱性
- その他の認証に固有の脆弱性
- 不適切な実装によってもたらされる典型的な脆弱性
- 独自の認証メカニズムを可能な限り堅牢にする方法
まず、認証と認可の違いとはなんだろうか。
認証
認証とは、ユーザーが本人であるか確認することである。
IDとパスワードを用いたサービスログインなどが具体例として挙げられる。
認証は以下の三つに大きく分けられる。
-
SYK
Something You Know: ユーザーの記憶によるもの
例えばIDやパスワードなど、その人だけが知っている知識を認証に使用する。 -
SYH
Something You Have: ユーザーの所有物によるもの
IDカードやToken, 携帯電話など、その人しか持っていない所有物を認証に使用する。 -
SYA
Something You Are: ユーザーの身体的特徴によるもの
生体認証(指紋認証・顔認証)など、その人の身体的特徴を認証に使用する。
認可
認可とは、そのユーザーが何かを行うことが許可されているかどうかを確認することである。
具体的にはアクセス制御だったり、閲覧制限をかけたりなどが挙げられる。
Brute-force attacks
ブルートフォース攻撃とは、総当たり攻撃とも呼ばれ、パスワードで考えられる組み合わせを何回も試行し、ユーザーの資格情報を推測・特定する攻撃のことである。この攻撃は基本的に、ユーザー名とパスワードの単語リストなどを使用してツールによって自動化されていることが多く、高速で膨大な数のログイン試行を行うことが可能である。
この攻撃は日本語では総当たりとも呼ばれているが、必ずしもランダムにパスワードなどを試しているわけではない。ダークウェブ等に公開されている情報をもとに攻撃ロジックを微調整して攻撃の効率を上げている場合がある。よって、パスワードベースのログインに依存しているようなWebサイトは、この攻撃への対応策を実施していないと非常に脆弱なものとなってしまう場合がある。
例えば、ユーザー名を特定することについて考えてみよう。
ユーザー名は実名やメールアドレスなどの単語を組み合わせている場合、簡単に推測されてしまう。また、明らかなパターンがない場合でもadminやadministratorなど高い権限を持っている場合につけられがち名前として知られている単語を用いてしまうと、攻撃者に安易に特定されてしまうだろう。
次にパスワードを特定することについて考えてみよう。
パスワードの総当たり攻撃の難易度はパスワードの強度に応じて大きく異なる。そのため、多くのWebサイトでは何らかの形式のパスワードポリシーを採用しており、ユーザーは理論的に総当たり攻撃をしずらいパスワードを作ることを強いられている。
よくあるパスワードポリシーとして以下のようなものが挙げられる。
- 最小文字数
- 小文字と大文字の混合
- 少なくとも一つの特殊文字
確かにこのようなパスワードをコンピューターのみで解読することは困難となり、この対策は正しい。しかし、人間の行動の傾向からパスワードを推測できることがある。
ユーザーはランダムな文字の組み合わせで強力なパスワードを作るのではなく、覚えやすいパスワードをパスワードポリシーに合わせるように少し変形する場合が多い。例えばpasswordという単語が許可されていなかったらPassword!やPas4$$w0rdなどのように。
他にもユーザーがパスワードを定期的に変更するようなパスワードポリシーを定められている場合、ユーザーは元のパスワードと似ているパスワードを設定する傾向がある。例えば*password!をpassword!.*のような形で。
このように人間の行動に関する知識をもとに攻撃者はブルートフォースの攻撃ロジックを組み立て、効率的に攻撃を行なっていく。
Username enumeration
ユーザー名列挙攻撃はアカウントリスト攻撃とも呼ばれている。
この攻撃は、攻撃者が特定のユーザー名が有効かどうかをWebサイトの動作の変化を観察することで識別し、有効なユーザー名の候補リストを生成されることによって行われる。
例えばログインページでアカウントリストを作成するとなった場合よく見られるのは以下の項目である。
- ステータスコード
ブルートフォース攻撃をする時、大概の攻撃は違うアカウントの情報を入力し失敗しているはずである。この時、一部に異なるステータスコードが返されていると、ユーザー名だけが当たっている可能性が高いと判断されてしまう。
よって、必ずしも守る必要はないが、結果に関係なく常に同じステータスコードを返す仕様にすると良い。
- エラーメッセージ
よくある仕様で、ユーザー名とパスワードの両方が間違っているのかパスワードのみが間違っているのかによって返されるエラーメッセージが異なる場合がある。これはユーザーにとっては親切な仕様かもしれないが、攻撃者にとってもユーザー名とパスワードが推測しやすくなるありがたい仕様になっているのだ。
- 応答時間
ステータスコードと同様に、大半の攻撃と異なる応答時間で処理が行われた場合、攻撃者はバックグラウンドで何かしら別の処理がされたと判断しそれを推測の根拠にすることがある。
例えば、ユーザー名が有効な場合にのみパスワードが正しいかをチェックする場合、この処理を悪用される可能性は非常に高くなる。
攻撃者はどのような処理が行われるかを確かめるために異常なまでに長いパスワードを入れることでバックグラウンドの処理時間を試していたりするのだ。
Bypassing two-factor authentication
最近ではセキュリティを高めるために二要素認証を導入しているWebサイトも少なくない。確かに二要素認証は単純なユーザーID・パスワードで認証するよりも情報へのアクセスが難しくなる。しかし、二要素認証の実装方法によっては攻撃者に隙を与えてしまう可能性がある。
一般的な二要素認証を例とする。ユーザーが最初にパスワードの入力を求められた後、確認コードの入力を求められた場合に事実上のログイン状態になっていることがある。そのため、二要素認証の実装時には確認コードの認証時にログイン専用ページへ直接スキップできるようになっていないかテストする必要がある。
Server-side request forgery
SSRFとは
サーバサイド・リクエストフォージェリ(SSRF)とは、攻撃者がサーバーサイドアプリケーションに意図しない場所へのリクエストを実行させることができるようになる脆弱性のことである。
一般的なSSRF攻撃では、攻撃者はサーバーに組織のインフラストラクチャ内の内部専用サービスへの接続を確立させる必要がある。
そのほかに、サーバーを任意の外部システムに強制的に接続できるようにするというものもあります。
これにより認証資格情報などの機密データが漏洩する可能性がある。
サーバーに対するSSRF攻撃では、攻撃者はループバックネットワーク位インターフェイスを介してアプリケーションをホストしているサーバーにHTTPリクエストを送信させる。
これには通常127.0.0.1(ローカルループバックアドレスのこと。これは送信元のIPアドレスを指定したのと同じ扱いになる。)またはlocalhostのようなホスト名をURLに指定することである。
例えば特定の店舗に商品の在庫があるかどうかをユーザーが確認できるショッピングアプリを想像してほしい。
すると、ユーザーはフロントエンドHTTPリクエストを介して、関連するバックエンドAPIエンドポイントにURLを渡すことで情報を取得する。
例えば以下のようなリクエストを行う。
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118
stockApi=http://stock.weliketoshop.net:8080/product/stock/check%3FproductId%3D6%26storeId%3D1
この例では攻撃者はリクエストを変更してサーバーに対してローカルなURLを指定することができる。
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118
stockApi=http://localhost/admin
通常/adminURLにはアクセス自体は誰もできるものの、基本は認証されたユーザーしか中身を見ることはできまい。しかし、ローカルマシンから送信された場合、管理者権限を得たとして管理機能へのアクセスができてしまう場合がある。
このようにローカルマシンからのリクエストを暗黙的に信頼してしまう作りになる理由として以下のようなものが考えられる。
- アクセス制御チェックがサーバーの前にある別のコンポーネントに実装されており、サーバーへの接続が確立されてしまった場合認証がパスされたとしてしまう
- 災害復旧などの目的でローカルマシンから全てのユーザーに対してログインせずに管理アクセスを許可する場合がある
- そのため、管理者が資格情報を失った場合にシステムを回復する方法が提供されており、これが脆弱性となりうる
- 本来は完全に信頼されたユーザーのみがサーバーから直接アクセスすることを前提としているサービスである
- 管理インターフェイスがメインアプリケーションとは異なるポート番号を持っている
他のバックエンドシステムに対するSSRF攻撃
たまに、アプリケーションサーバーはユーザーが直接アクセスできないバックエンドシステムと対話できる時がある。
これらのシステムにはよくルーティングが不可能なプライベートIPアドレスが設定されていたりする。
バックエンドシステムはセキュリティ体制が弱いことが多く、内部バックエンドシステムにはシステムと対話できる場合には認証なしでアクセスできる機密事項が含まれていることもある。
例えば以下のように、攻撃者は管理インターフェイスにアクセスする可能性がある。
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118
stockApi=http://192.168.0.68/admin
ファイルアップロードの脆弱性
ファイルアップロードの脆弱性とは
ファイルアップロードの脆弱性とは、名前、タイプ、内容、サイズなどを十分に検証せずにWebサーバーがユーザーにファイルシステムへのファイルのアップロードを許可することで発生する。
なぜなら、潜在的に危険なファイルをアップロードされてしまう可能性があるからである。
潜在的に危険なファイルには例えばリモートコード実行を可能にするサーバー側のスクリプトファイルなどが挙げられます。
実際のWebサイトにはアップロードできるファイルに何かしらの制限が設けられている。
しかし、その実装が不完全であることも多い。
例えば、危険なファイルタイプをブラックリストに登録しようとするが、ファイル拡張子をチェックする際の解析の不一致を考慮していない、Burp ProxyやReplyerなどのツールを使用して攻撃者が簡単に操作できるプロパティにファイルの種類をチェックする項目が含まれているなどが挙げられる。
セキュリティの観点から考える最悪のファイルアップロード機能の脆弱性は、WebサイトでPHP・Java・Pythonファイルなどのサーバーサイドスクリプトのアップロードが許可されており、それをコードとして実行するように構成されていることである。
これは攻撃者がWebシェルを作成することを助長することになる。
- Webシェルとは
- Webシェルは攻撃者がHTTPリクエストを適切なエンドポイントに送信するだけで、リモートWebサーバー上で任意のコマンドを実行できるようにする悪意のあるスクリプトのこと
Webシェルを正常にアップロードできれば、実質的にサーバーを完全に制御できるようになる。
例えば任意のファイルの読み取りと書き込み、機密データの流出、さらには内部インフラストラクチャーとネットワーク外部の他のサーバーの両方に対してサーバーを使用して攻撃を開始することができる。
具体例として、次のPHPワンライナーを利用してサーバーのファイルシステムから任意のファイルを読み取ることができる。
<?php echo file_get_contents('/path/to/target/file'); ?>
アップロード後、この悪意あるファイルに対するリクエストを送信すると、応答でターゲットファイルのコンテンツが返されるようになる。
また、より汎用性の高いWebシェルは以下のようになる。
<?php echo system($_GET['command']); ?>
このスクリプトを使用すると、次のようにクエリパラメータを介して任意のシステムコマンドを渡すことができる。
GET /example/exploit.php?command=id HTTP/1.1
ファイルアップロードの欠陥のある検証を悪用する
実際に全くファイルアップロード攻撃に全く対策を施していないWebサイトはほとんどない。
しかし、その対策を悪用される可能性もある。
HTMLフォームを送信するとき、ブラウザは通常提供されたデータをPOSTのapplication/x-www-form-url-encodedコンテンツタイプのリクエストで送信する。
これは名前や住所などの単純なテキストを送信する場合に適している。
ただし、画像ファイル全体など大量のバイナリデータを送信する場合にはmultipart/form-dataが好ましい。
例として画像をアップロードして、説明とユーザー名を入力するフィールドがあるフォームを考えてみよう。
このようなフォームを送信すると、次のようなリクエストが生成されるとする。
POST /images HTTP/1.1
Host: normal-website.com
Content-Length: 12345
Content-Type: multipart/form-data; boundary=---------------------------012345678901234567890123456
---------------------------012345678901234567890123456
Content-Disposition: form-data; name="image"; filename="example.jpg"
Content-Type: image/jpeg
[...binary content of example.jpg...]
---------------------------012345678901234567890123456
Content-Disposition: form-data; name="description"
This is an interesting description of my image.
---------------------------012345678901234567890123456
Content-Disposition: form-data; name="username"
wiener
---------------------------012345678901234567890123456--
メッセージ本文はフォームの入力ごとに別々の部分に分割されている。
各部分にはContent-Dispositionヘッダーが含まれており、関連する入力フィールドに関する基本情報が提供される。
Webサイトがファイルアップロードを検証する方法の一つとしてこの入力固有のNotent-Typeヘッダーが予期されるMIMEタイプと一致するかどうかを確認することがある。
例えばサーバーが画像ファイルのみを想定する場合、image/jpegやimage/pngのようなタイプのみを許可する場合がある。この検証が行われない場合、このファイルアップロードの実装は攻撃ツールを使うことで簡単に回避可能となる。
OS command injection
OSコマンドインジェクションとは
OSコマンドインジェクションはシェルインジェクションとも呼ばれる攻撃の一つである。
攻撃者はアプリケーションを実行しているサーバー上でOS(オペレーティングシステム)コマンドを実行でき、アプリケーションとそのデータに影響を与えることができる。
OSコマンドインジェクションによく用いられるシステムに関する情報を取得できるコマンドとして以下のものが挙げられる。
取得したい情報の種類 | Linux | Windows |
---|---|---|
ユーザー名 | whoami | whoami |
OS | uname -a | ver |
ネットワーク設定 | ifconfig | ipconfig / all |
ネットワーク接続 | netstat -an | netstat -an |
実行中のプロセス | ps -ef | tasklist |
コマンドの挿入
実際にどう攻撃するか具体例を見る。
例えば、ショッピングアプリケーションにおいて、ユーザーが在庫確認するには以下のURLでアクセスする必要がある。
https://insecure-website.com/stockStatus?productID=381&storeID=29
在庫情報を提供するにあたって、アプリケーションは様々なレガシーなシステムに向かってクエリを実行する。
歴史的な理由から、この機能は以下のシェルコマンドを呼び出すことによって実装されている可能性が高く、このコマンドで出された在庫情報をもとにしてユーザーにレスポンスが送られる。
stockreport.pl 381 29
他にも以下の入力を送信して任意のコマンドを実行することができたりする。
& echo aiwefwlguh &
この入力がパラメータで送信された場合、アプリケーションによって実行されるコマンドは次のようになる。
stockreport.pl & echo aiwefwlguh & 29
このechoコマンドにより、指定された文字列が出力に書き出される。
一部の種類のOSコマンドインジェクションをテストするのによく使われる。
&文字はシェルコマンドの区切り文字であり、上の例では3つの個別のコマンドが順番に実行される。
ユーザーに返される出力は次のようなものになる。
Error - productID was not provided
aiwefwlguh
29: command not found
上の出力の意味はこのようになっている。
- 元のstockreport.plコマンドは予期された引数なしで実行されたため、エラーメッセージが返されました
- 挿入されたechoコマンドが実行され、指定された文字列が出力にエコーされました
- 元の引数が29コマンドとして実行されたため、エラーが発生しました
挿入されたコマンドの後に追加のコマンドセパレータを配置する&と、挿入されたコマンドが挿入ポイントの後に続くものから分離されるため便利である。
これにより、その後に挿入されたコマンドの実行が妨げられる可能性が低くなる。
SQL injection
SQLインジェクションとは
SQLインジェクションとは、アプリケーションがデータベースに対して行うクエリを攻撃者が妨害できるようにする脆弱性である。
これにより攻撃者は、通常は取得できないデータを閲覧することができてしまう。
この攻撃は大体の場合大切なデータを変更もしくは削除することに繋がり、アプリケーションのコンテンツや動作に大きな影響を与える可能性がある。
SQLインジェクションは手動で検出することが可能である。
アプリケーション内の検出したいエントリポイントに、次のようなものを送信する。
- 一重引用符を使用して、エラーやその他の異常を探す
- OR 1=1や などのブール条件を使用して、アプリケーションの応答の違いを探す
- アプリケーションの応答の体系的な違いを探すSQL固有の構文を使用して、エントリポイントの基本 (元の) 値と別の値を評価する
- SQLクエリ内で実行されるときに時間遅延をトリガーし、応答にかかる時間の違いを探すように設計されたペイロード
- OAST ペイロード
隠されたデータを取得する
実際にSQLインジェクションがどのように動作するかを見てみよう。
さまざまなカテゴリで商品を表示するショッピングアプリケーションを想像してほしい。
ユーザーがギフトカテゴリをクリックすると、ブラウザは次のようなURLをリクエストする。
https://insecure-website.com/products?category=Gifts
これにより、アプリケーションはSQLクエリを作成して、関連する製品の詳細をデータベースから取得する。
SELECT * FROM products WHERE category = 'Gifts' AND released = 1
productテーブルから全ての詳細を参照し、categoryが'Gifts'であり、releasedが1であるデータを探しているというSQL文となる。
releasedはリリースされていない製品を隠すためなどに使用されているのではないかと推測できる。
このようなアプリケーションには次のような攻撃ができる。
https://insecure-website.com/products?category=Gifts'--
これにより、次のSQLクエリが生成される。
SELECT * FROM products WHERE category = 'Gifts'--' AND released = 1
--はSQLのコメントインジケーターであり、これを入れることで残りの部分がコメントとして解釈されて事実上削除されることを意味する。
これを応用すると、以下のようなリクエストを送れば任意のカテゴリのすべての製品を表示させることができる。
https://insecure-website.com/products?category=Gifts'+OR+1=1--
このようにするとcategoryがGiftsであるすべての製品を取得できる。
アプリケーションロジックを破壊する
別の攻撃パターンについても考える。
ユーザーがユーザー名とパスワードを使用してログインできるアプリケーションについて考える。
ユーザーがユーザー名wienerとパスワードbluecheeseを送信すると、アプリケーションは次のSQLクエリを実行して視覚情報を確認する。
SELECT * FROM users WHERE username = 'wiener' AND password = 'bluecheese'
クエリがユーザーの詳細を返した場合ログイン成功、それ以外の場合は拒否される。
この場合、攻撃者はパスワードを必要とせずに、任意のユーザーとしてログインすることができる。
例えば、以下のようなSQLクエリを送れば、--以降が無視されることにより攻撃者はadministratorでログインすることができる。
SELECT * FROM users WHERE username = 'administrator'--' AND password = ''
ここで講座内容が終了する。
後書き
備忘録として色々書いてきたがずいぶん長くなってしまった。
これを持って興味を持った人はぜひ実際のサイトにログインし演習を試してみてほしい。