6.6. XSS対策¶
目次
6.6.1. Overview¶
6.6.1.1. Stored, Reflected XSS Attacks¶
XSS攻撃は、大きく分けて二つのカテゴリに分けられる。
Stored XSS Attacks
Reflected XSS Attacks
Stored XSS Attacks、Reflected XSS Attacksともに、出力値をエスケープすることで防ぐことができる。
6.6.2. How to use¶
必要に応じて、3種類のエスケープを使い分けること。
エスケープの種類:
- Output Escaping
- JavaScript Escaping
- Event handler Escaping
6.6.2.1. Output Escaping¶
エスケープ前 | エスケープ後 |
---|---|
& |
& |
< |
< |
> |
> |
" |
" |
' |
' |
f:h()
を使用することを必須とする。6.6.2.1.1. 出力値をエスケープしない脆弱性のある例¶
出力画面の実装
<!-- omitted -->
<tr>
<td>Job</td>
<td>${customerForm.job}</td> <!-- (1) -->
</tr>
<!-- omitted -->
項番 | 説明 |
---|---|
(1)
|
customerFormのフィールドである、jobをエスケープせず出力している。
|
6.6.2.1.2. 出力値をf:h()関数でエスケープする例¶
出力画面の実装
<!-- omitted -->
<tr>
<td>Job</td>
<td>${f:h(customerForm.job)}</td> <!-- (1) -->
</tr>
.<!-- omitted -->
項番 | 説明 |
---|---|
(1)
|
EL式の
f:h() を使用することにより、エスケープして出力している。 |
出力結果
<!-- omitted -->
<tr>
<td>Job</td>
<td><script>alert("XSS Attack")</script></td>
</tr>
<!-- omitted -->
Tip
java.util.Date継承クラスのフォーマット
java.util.Date継承クラスをフォーマットして表示する場合は、JSTLの
<fmt:formatDate>
を用いることを推奨する。 以下に、設定例を示す。<fmt:formatDate value="${form.date}" pattern="yyyyMMdd" />
valueの値に前述した
f:h()
を使用して値を設定すると、Stringになってしまい、javax.el.ELException
がスローされるため、そのまま${form.date}
を使用している。 しかし、yyyyMMddにフォーマットするため、XSSの心配はない。
Tip
java.lang.Number継承クラス、またはjava.lang.Numberにパースできる文字列
java.lang.Number継承クラスまたはjava.lang.Numberにパースできる文字列をフォーマットして表示する場合は、
<fmt:formatNumber>
を用いることを推奨する。 以下に、設定例を示す。<fmt:formatNumber value="${f:h(form.price)}" pattern="###,###" />
上記は、Stringでも問題ないので、
<fmt:formatNumber>
タグを使わなくなった場合にf:h()
を付け忘れることを予防するため、f:h()
を明示的に使用している。
6.6.2.2. JavaScript Escaping¶
エスケープ前 | エスケープ後 |
---|---|
' |
\' |
" |
\" |
\ |
\\ |
/ |
\/ |
< |
\x3c |
> |
\x3e |
0x0D(復帰) |
\r |
0x0A(改行) |
\n |
6.6.2.2.1. 出力値をエスケープしない脆弱性のある例¶
<html>
<script type="text/javascript">
var aaa = '<script>${warnCode}<\/script>';
document.write(aaa);
</script>
<html>
属性名 | 値 |
---|---|
warnCode | <script></script><script>alert('XSS Attack!');</script><\/script> |
出力結果
<script type="text/javascript">
var aaa = '<script><\/script><script>alert('XSS Attack!');<\/script><\/script>';
document.write(aaa);
</script>
Tip
業務要件上必要でない限り、JavaScriptの要素をユーザからの入力値に依存して動的に生成する仕様は、 任意のスクリプトが埋め込まれてしまう可能性があるため、別の方式を検討する、または、極力避けるべきである。
6.6.2.2.2. 出力値をf:js()関数でエスケープする例¶
f:js()
の使用を推奨する。使用例を、下記に示す。
<script type="text/javascript">
var message = '<script>${f:js(message)}<\/script>'; // (1)
<!-- omitted -->
</script>
項番 | 説明 |
---|---|
(1)
|
EL式の
f:js() を使用することにより、エスケープして変数に設定している。 |
出力結果
<script type="text/javascript">
var aaa = '<script>\x3c\/script\x3e\x3cscript\x3ealert(\'XSS Attack!\');\x3c\/script\x3e<\/script>';
document.write(aaa);
</script>
6.6.2.3. Event handler Escaping¶
f:h()
や、f:js()
を使用するのではなく、f:hjs()
を使用すること。${f:h(f:js())}
と同義である。<input type="submit" onclick="callback('xxxx');">
のようなイベントハンドラの値に"');alert("XSS Attack");// "
を指定された場合、別のスクリプトを挿入できてしまうため、6.6.2.3.1. 出力値をエスケープしない脆弱性のある例¶
<input type="text" onmouseover="alert('output is ${warnCode}') . ">
属性名 | 値 |
---|---|
warnCode | '); alert('XSS Attack!'); // 上記の値が設定されてしまうことで、意図せず文字列リテラルが閉じられ、XSSの脆弱性が生じる。
|
出力結果
<!-- omitted -->
<input type="text" onmouseover="alert('output is'); alert('XSS Attack!'); // .') ">
<!-- omitted -->
6.6.2.3.2. 出力値をf:hjs()関数でエスケープする例¶
使用例を、下記に示す。
<input type="text" onmouseover="alert('output is ${f:hjs(warnCode)}') . "> // (1)
項番 | 説明 |
---|---|
(1)
|
EL式の
f:hjs() を使用することにより、エスケープして引数としている。 |
出力結果
<!-- omitted -->
<input type="text" onmouseover="alert('output is \'); alert(\'XSS Attack!\');\" \/\/ .') ">
<!-- omitted -->