Shikata Ga Nai

Private? There is no such things.

クライアント側の制御のバイパスについてかいてみた

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, (^^ゞ