
それでは、実際に、XSS(クロスサイトスクリプティング)をJavaサーブレットで、体験してみましょう。百聞は一見に如かずといいますしね。
なお、Chromeだと、XSSがデフォルトで動きませんので、IEで実行するようにしましょう。
XSS攻撃を体験する。
<%@ page language="java" contentType="text/html; charset=UTF8" pageEncoding="UTF-8" %>
<html>
<head>
<title>Xssサンプル</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<form action='XssServlet' method='POST'>
名前:<input type="text" name="name" value=''>
<input type="submit" value="送信">
</form>
<hr>
送信した名前:<%= request.getAttribute("name") %>
</body>
</html>
package servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/XssServlet")
public class XssServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req,
HttpServletResponse resp) throws ServletException,IOException{
req.setAttribute("name", "");
// クッキー設定
resp.addCookie(new Cookie("xss", "xsstest"));
common(req,resp);
}
@Override
protected void doPost(HttpServletRequest req,
HttpServletResponse resp) throws ServletException,IOException{
// 文字コード設定
req.setCharacterEncoding("UTF-8");
String name = req.getParameter("name");
req.setAttribute("name", name);
common(req,resp);
}
protected void common(HttpServletRequest req,
HttpServletResponse resp) throws ServletException,IOException{
RequestDispatcher disp = req.getRequestDispatcher("/xss.jsp");
disp.forward(req, resp);
}
}
上記、ソースをTomcat等で実行すると、下記のような表示になります。

太郎と、名前のテキストボックスに入力して、「送信」ボタンを押すと下記のように表示されます。

そこで、下記のJavaScriptを名前欄に入力して、「送信」を押しましょう。
<script>alert(document.cookie);</script>
すると、下記のように、簡単にクッキーで設定した情報をJavaScriptを使用して盗み出せてしまいます。

対策
下記の文字を、表示させる箇所をエスケープする処理を追加します。
修正後のサーブレット(メソッド「escape」を追加して、エスケープしています。)
package servlet; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/XssServlet") public class XssServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException{ req.setAttribute("name", ""); // クッキー設定 resp.addCookie(new Cookie("xss", "xsstest")); common(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException{ // 文字コード設定 req.setCharacterEncoding("UTF-8"); String name = req.getParameter("name"); req.setAttribute("name", escape(name)); common(req,resp); } protected void common(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException{ RequestDispatcher disp = req.getRequestDispatcher("/xss.jsp"); disp.forward(req, resp); } private static String escape(String val) { if (val == null) return ""; val = val.replaceAll("&", "& amp;"); val = val.replaceAll("<", "& lt;"); val = val.replaceAll(">", "& gt;"); val = val.replaceAll("\"", """); val = val.replaceAll("'", "'"); return val; } }
そうすることで、同じJavaScriptを実行しても、下記のようにタグがエスケープされるので、JavaScriptが実行されません。

また、実際の攻撃では、このように自分のクッキー情報を盗んでも意味がありませんので、攻撃用の他サイトにアクセスしたら、iframeで本記事のような脆弱性サイトを埋め込んで、クッキー情報を盗み出します。






この記事へのコメントはありません。