Hello there, ('ω')ノ
クライアント側に配置されたコントロールと検証と。
それをどのようにバイパスするかについて。
クライアントサーバアーキテクチャの基本的なセキュリティ上の欠陥は。
サーバがクライアントを制御できないことで。
【クライアント経由でデータを送信】
■非表示のフォームフィールド
Webアプリケーションでクライアントからデータを送信する最も一般的な方法で。
<input type=”text” name=”quantity”>
<input type=”hidden” name=”price” value=”49”>
非表示のフィールドは、UI にレンダリングされない/画面に表示されて。
ただ、フォームが送信されると下記のリクエストが発生して。
POST /shop/28/Shop.aspx?prod=1 HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
quantity=1&price=49
サーバで検証されていない可能性があるので、負の値を送信したりと。
■HTTPクッキー
Cookieは、クライアントからデータを送信する一般的な方法で。
通常のユーザは、Cookieを直接変更することはできず。
ただ、傍受プロキシを使用すると簡単に実行できて。
1)Cookie が設定されている場合、サーバからのレスポンスを傍受して。
HTTP/1.1 200 OK
Set-Cookie: DiscountAgreed=15
Content-Length: 153
2)サーバに送信するときにリクエストを変更して。
追加のリクエストを送信すると対応するリクエストが行われて。
DiscountAgreed Cookieを変更することで、任意の割引を取得できて。
POST /shop/92/Shop.aspx?prod=3 HTTP/1.1
Host: example.com
Cookie: DiscountAgreed=200
Content-Length: 10
quantity=1
■URLパラメータ
データは、変数=値の形式でURLで送信されて。
http://example.com/shop/?prod=3&pricecode=12
ブラウザのアドレスバーで簡単に修正できて。
埋め込まれた画像や埋め込まれたiframeや。
事前設定されたパラメータを持つフォームだったり。
アドレスバーを隠すための何らかの手段を使用するアプリケーションは。
ブラウザから直接URLを修正できないので。
傍受プロキシで、インターセプトを使用したりと。
■リファラーヘッダ
リファラーヘッダは、リクエストの発信元を示して。
一部のアプリケーションは、要求されたアクションを許可するために。
これらを処理する場合があって。
パスワードリセットのリクエストの例だと。
GET /auth/CreateUser.ashx HTTP/1.1
Host: example.com
Referer: https://example.com/auth/Admin.ashx
サーバがリファラーヘッダに基づいたリセット アクションを許可する場合は。
管理者ユーザのパスワードをリセットすることになる可能性があって。
リファラーヘッダは完全にオプションで。
■不透明データ
データがプレーンテキスト形式でなくて。
何らかのアルゴリズムを使用して暗号化またはエンコードされている場合があって。
これは、アプリケーションが入力データに対して。
追加のチェックを実行することを意味して。
これはそれ自体でバグを引き起こす可能性があって。
<input type=”hidden” name=”price_token” value=”E76D213D291B8F216D694A”>
【ユーザデータのキャプチャ】
■長さ制限
ブラウザは、ユーザが maxlength属性を使用して。
長いデータを入力することを制限する場合があって。
<input type=”text” name=”quantity” maxlength=”10”>
これを回避するには、単に属性を削除して。
■スクリプトベースの検証
スクリプトベースの検証を実行するために javascript に入ります。
送信ボタンがクリックされたときに関数が呼び出される例だと。
<script>
function validateForm(theForm)
{
var isInteger = /^\d+$/;
var valid = isInteger.test(quantity) &&quantity > 0 && quantity <= 10;
if (!valid)
alert(’Please enter a valid quantity’);
return valid;
}
</script>
このような単純な検証は簡単に回避できて。
1) ブラウザで Javascript を無効にして。
2) リクエストをインターセプトして値を変更して。
3) レスポンスを傍受し、常にtrueを返すように関数を変更して。
■無効フィールド
無効なフィールドはグレー表示され、編集できずサーバーには送信されず。
これらのフィールドは、開発プロセスで使用されている場合があって。
なので、フィールドをテストして、サーバが指定されたフィールドを。
処理するかどうかを確認する必要があって。
<input type=”text” disabled=”true” name=”price” value=”300”>
【防御:クライアント側データの処理 】
1.クライアントから重要なデータを送信しないで。
サーバに参照を設定して、サーバ側で利用可能なデータを使用して。
2.他に方法がなければ、難読化・暗号化は必須で。
暗号化を使用すると、リプレイ攻撃を受ける可能性があって。
なので、暗号化中には、アイテムに関連するデータを使用して。
たとえば、商品の賞品が暗号化されている場合だと。
固有の商品コードとともに暗号化を実行して。
3.割引などのプロファイル固有のものが発行されている場合は。
プロファイルに保存するか、セッションオブジェクトを使用して。
4.クライアント側からのデータは、クライアント側自体では検証できず。
5.難読化または拡張機能を使用すると攻撃者の速度が低下させても。
攻撃を止めることはできず。
6.サーバ上でも、常にすべてのクライアント側の検証を複製して。
【搾取】
攻撃者として必要なことは、下記のとおりで。
■クライアント経由のデータ送信
1.クライアント経由でデータが送信されるすべてのインスタンスを見つけて。
(非表示フィールド、URLパラメータ、Cookie、ヘッダーなど)。
2.特定のアイテムがアプリケーションで果たす役割を推測して。
3.アプリケーションの動作に影響を与えるようにアイテムを変更して。
つまり、脆弱性が公開されているかどうかを確認できて。
■不透明データ
1.プレーンテキストがわかっている場合は、データの解読を試して。
2.アプリケーションで関数 else-where を使用して、データの難読化を解除します。
3.価格が難読化されている場合は。
高価な商品には、低価格の商品のトークンを送信したり。
4.何も機能しない場合は、ロジックを攻撃して。
長すぎるデータや変更されたデータ、異なる文字セットなどを送信したり。
■入力のキャプチャ
1.クライアント側の検証が行われている場所を特定して。
2.クライアント側の検証に失敗したであろう値を送信してみたり。
3.クライアント側の検証がサーバに複製されているかどうかを確認して。
そうでない場合は、さらに攻撃を行うことができて。
4.クライアントで複数のフィールドが検証されている場合は。
各フィールドを個別に試して。
Best regards, (^^ゞ