As a continuation of the last time, I would like to touch on XSS countermeasures. There are various types of XSS, but this time I would like to focus on the problems when embedding Java Script code in a JSON string.
Last time, the server side created a Servlet that returns JSON when accessed by GET with a URL, but this time it will be used as it is. Then, try embedding the JavaScript code in the returned JSON data. Specifically, the following JSON is returned.
{"id":1,"name":"kimisyo","datas":["Programmer","Data Scientist<script>alert('hello!')</script>"]}
If it is not sanitized properly, the JavaScript code in the `<script> alert ('hello!') </ Script>`
part will be executed.
First, as a general method, access the URL of the server with Ajax, read the result as JSON, and execute JavaScirpt to display the contents. The source (jsp file) is as follows.
clientTest.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jQuery Hello World</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script>
$.ajax({
url:"http://localhost:8080/servletTest/helloworld", //URL of the communication destination
type:"GET", //HTTP method to use
// dataType:"json", //Response data type
dataType:"text", //Response data type(xml/html/script/json/jsonp/text)
timespan:1000 //Communication timeout setting(millisecond)
}).done(function(data,textStatus,jqXHR) {
var data2 = JSON.parse(data);
alert(data2.datas);
//fail is executed when communication fails
}).fail(function(jqXHR, textStatus, errorThrown ) {
alert("error");
//always is a success/Executed regardless of failure
}).always(function(){
alert("complete");
});
</script>
</head>
<body>
<div id="test"></div>
</body>
</html>
When you hit the URL of this jsp from the browser, the contents of the JSON data will be displayed as shown below. The JavaScript embedded in JSON is read as data as it is, and there is no problem.
Next, try hitting the URL of the Servlet that returns JSON directly in Edge. Then, the beautifully embedded JavaScript is executed by the browser. This is an operation that I don't want to see as a person involved in server-side development.
The problem is that the browser recognizes the part surrounded by "<" and ">" as an html tag, so special characters such as "<", ">" in JSON are Unicode escape sequences. You can convert it to. First, create the following class. Add the characters you want to escape to the CustomCharacterEscapes method.
CustomCharacterEscapes.java
package servletTest;
import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.io.CharacterEscapes;
public class CustomCharacterEscapes extends CharacterEscapes {
private final int[] asciiEscapes;
public CustomCharacterEscapes()
{
int[] esc = CharacterEscapes.standardAsciiEscapesForJSON();
esc['"'] = CharacterEscapes.ESCAPE_STANDARD;
esc['\''] = CharacterEscapes.ESCAPE_STANDARD;
esc['/'] = CharacterEscapes.ESCAPE_STANDARD;
esc['\n'] = CharacterEscapes.ESCAPE_STANDARD;
esc['>'] = CharacterEscapes.ESCAPE_STANDARD;
esc['<'] = CharacterEscapes.ESCAPE_STANDARD;
asciiEscapes = esc;
}
@Override
public int[] getEscapeCodesForAscii() {
return asciiEscapes;
}
// no further escaping (beyond ASCII chars) needed:
@Override
public SerializableString getEscapeSequence(int ch) {
return null;
}
}
Next, I will make some corrections in the previous Servlet.
ServletTest.java
package servletTest;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
//Reference https://itsakura.com/java-jackson
@WebServlet("/helloworld")
public class ServletTest extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//Set a value in a Java object
JsonBean jsonBean = new JsonBean();
jsonBean.setId(1);
jsonBean.setName("kimisyo");
List<String> datas = new ArrayList<>();
datas.add("Programmer");
datas.add("Data Scientist<script>alert('hello!')</script>");
jsonBean.setDatas(datas);
ObjectMapper mapper = new ObjectMapper();
mapper.getFactory().setCharacterEscapes(new CustomCharacterEscapes());
try {
//Convert from Java object to JSON
String testJson = mapper.writeValueAsString(jsonBean);
//JSON output
response.getWriter().write(testJson);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
Specifically, `mapper.getFactory (). SetCharacterEscapes (new CustomCharacterEscapes ());`
is added.
If you hit the URL of the above Servlet directly from the browser, it will be displayed on the browser as follows. It has been converted to a Unicode sequence and the embedded JavaScript code is not executed.
{"id":1,"name":"kimisyo","datas":["Programmer","Data Scientist\u003Cscript\u003Ealert(\u0027hello!\u0027)\u003C\u002Fscript\u003E"]}
Then, even if it is converted to a Unicode sequence, will it be correctly interpreted as JSON data on the JavasScirpt side that received the JSON? When this JSON is accessed by Ajax with JavaScript and displayed, the result of reading "<" and ">" as JSON data is displayed as in the case of not converting, and it can be seen that it was interpreted correctly.
Next, I would like to deal with the problem of embedding JSON in HTML and using it from JavaScript.
-[[Java] Escape multibyte characters in Jackson](https://atuweb.net/201608_java-jackson-escape-multibytechars/#%E3%83%9E%E3%83%AB%E3%83%81] % E3% 83% 90% E3% 82% A4% E3% 83% 88% E6% 96% 87% E5% AD% 97% E3% 82% 92% E3% 82% A8% E3% 82% B9% E3 % 82% B1% E3% 83% BC% E3% 83% 97)
Recommended Posts