XSSのテスト
構成
Java Spring Boot
Tymeleaf
コントローラ.java
/**
*
* @param model
* @param name
* @param response
* @return
*/
@GetMapping("/xss")
public String xss(Model model, @RequestParam(name = "name", required = false, defaultValue = "") String name, HttpServletResponse response) {
model.addAttribute("name", name);
Cookie cookie = new Cookie("id", "testCookie"); // Cookieの作成
cookie.setMaxAge(265 * 24 * 60 * 60); // Cookieの残存期間(秒数)
cookie.setPath("/"); // Cookieの適用対象となるサーバ上のパス
response.addCookie(cookie);
return "xss";
}
xss.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>登録</h2>
<form action="xss">
<div>名前:</div>
<input type="text" name="name" value="">
<div>
<button type="submit">OK</button>
</div>
</form>
<h2>登録前の確認</h2>
<form action="xss">
名前:
<th:block th:if="${name}">
[(${name})]
</th:block>
<div>
<button type="submit">OK</button>
</div>
</form>
</body>
</html>
[(〜〜〜)]はアンエスケープインライン。コードをエスケープしない。
Tymeleafのthタグやインラインはデフォルトでエスケープするので、通常のHTMLと同じくエスケープ察せないように今回はアンエスケープインラインをあえて使用する。
攻撃者を装って、以下のコードを打ち込んでみる
<script>console.log(document.cookie)</script>
スクリプトが上手く動いた。
続いて、実際にリダイレクト先を指定する。
<script>window.location='http://localhost:8080/xss?'+document.cookie;</script>
URLを見てわかるように元画面のIDが送信されている。
対策
例えばtymeleafの場合、デフォルトエスケープ処理になっている為
アンエスケープインライン[()]
を使用せず、エスケープする通常のインライン[[]]
を使う。
- [(${name})]
+ [[${name}]]
エスケープされた為、スクリプトタグと認識されず画面上にテキストとして表示された。
htmlでDBの値を使用してページ生成するような場合は、
htmlで特殊文字のエスケープ処理をする。
今回みたいにhtml生成時に画面側でサニタイジングしたりや、サーバ側でバリデーションチェックしたりする。
特殊文字のみを置換するように対策していても文字コードを突いた攻撃もあるので注意。
HTTPレスポンスに設定されるcharsetも正しく設定しておく。