Preface
This article documents the XSS vulnerabilities that require attention in java code auditing.
Vulnerability Analysis of 0x01 XSS
XSS Generation
The background does not check or filter the user input, but directly returns the user input to the front. Causes javascript code to execute arbitrarily on the client side.
Code examples
public void Message(HttpServletRequest req, HttpServletResponse resp) { // TODO Auto-generated method stub String message = req.getParameter("msg"); try { resp.getWriter().print(message); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
The msg field obtained here is returned intact, and if it is js code, it will also parse the execution, causing reflective xss vulnerabilities;
Defense against XSS
Depending on the cause of the vulnerability, you can defend against it by filtering the input:
- Enter escape for storage
- Filter special characters
- Special characters such as input limit < ` for the previous paragraph
Specific defenses can be:
-
Global filter, set filter:
<filter> <filter-name>XssSafe</filter-name> <filter-class>XssFilter</filter-class> </filter> <filter-mapping> <filter-name>XssSafe</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
It is important to note here that our configuration is /* instead of /, < url-pattern>/</url-pattern> will match a path url like / login, not a pattern of *. A suffix URL such as jsp, and < url-pattern>/*</url-pattern> matches all urls: path-type and suffix-type URLs (including/login,*.jsp,*.js, and *.html).
Then write the content of the filter, which is written on the Internet and can be used directly as follows:
//XssFilter implementation: public class XssFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response); } } //XssHttpServletRequestWrapper implementation public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { public XssHttpServletRequestWrapper(HttpServletRequest request) { super(request); } @SuppressWarnings("rawtypes") public Map<String,String[]> getParameterMap(){ Map<String,String[]> request_map = super.getParameterMap(); Iterator iterator = request_map.entrySet().iterator(); while(iterator.hasNext()){ Map.Entry me = (Map.Entry)iterator.next(); String[] values = (String[])me.getValue(); for(int i = 0 ; i < values.length ; i++){ values[i] = xssClean(values[i]); } } return request_map; } public String[] getParameterValues(String paramString) { String[] arrayOfString1 = super.getParameterValues(paramString); if (arrayOfString1 == null) return null; int i = arrayOfString1.length; String[] arrayOfString2 = new String[i]; for (int j = 0; j < i; j++){ arrayOfString2[j] = xssClean(arrayOfString1[j]); } return arrayOfString2; } public String getParameter(String paramString) { String str = super.getParameter(paramString); if (str == null) return null; return xssClean(str); } public String getHeader(String paramString) { String str = super.getHeader(paramString); if (str == null) return null; str = str.replaceAll("\r|\n", ""); return xssClean(str); } private String xssClean(String value) { //ClassLoaderUtils.getResourceAsStream("classpath:antisamy-slashdot.xml", XssHttpServletRequestWrapper.class) if (value != null) { // NOTE: It's highly recommended to use the ESAPI library and // uncomment the following line to // avoid encoded attacks. // value = encoder.canonicalize(value); value = value.replaceAll("\0", ""); // Avoid anything between script tags Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Avoid anything in a src='...' type of expression scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Avoid anything in a href='...' type of expression scriptPattern = Pattern.compile("href[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Remove any lonesome </script> tag scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Remove any lonesome <script ...> tag scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Avoid eval(...) expressions scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Avoid expression(...) expressions scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Avoid javascript:... expressions scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Avoid vbscript:... expressions scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Avoid onload= expressions scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); } return value; } }
-
Using the tool class xssProtect
Download the corresponding jar package into the lib directory and import: https://code.google.com/archive/p/xssprotect/
Simple usage:
protectedAgainstXSS(String html){StringReader reader = new StringReader(html); StringWriter writer = new StringWriter(); try { // Resolve incoming string from "html" variable HTMLParser.process( reader, writer, new XSSFilter(), true ); // Returns parsed and processed strings return writer.toString(); } catch (HandlingException e) { } }
Specific ways of using can be referred to: https://www.iteye.com/blog/liuzidong-1744023
-
Most web attacks can be defended against using the ESAPI
pom import:
<dependency> <groupId>org.owasp.esapi</groupId> <artifactId>esapi</artifactId> <version>2.2.1.1</version> </dependency>
Entity encoding occurs once before getting input parameters:
public void Message(HttpServletRequest req, HttpServletResponse resp) { // TODO Auto-generated method stub String message = req.getParameter("msg"); String s = ESAPI.encoder().encodeForHTML(message); //Entity encoding try { resp.getWriter().print(s); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
0x02 Audit XSS Vulnerability
setAttribute
The setAttribute method is used to save the variable usage in the same request cycle and then take it out using the getAttribute method.
@WebServlet("/demo") public class xssServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html");// Set Response Type String content = request.getParameter("content"); //Get context pass-through parameter data request.setAttribute("content", content); //content shared to request domain request.getRequestDispatcher("/WEB-INF/pages/xss.jsp").forward(request, response); //Forward to xxs. In JSP page } }
In jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> ${requestScope.content} </head> <body> </body> </html>
ModelAndView
ModelAndView can return parameters to the request scope of a specified page or specify the page name to be returned.
@RequestMapping("/test") public ModelAndView test(){ ModelAndView mav=new ModelAndView("hello"); mav.addObject("time", new Date()); mav.getModel().put("name", "caoyc"); return mav; }
In jsp:
time:${requestScope.time} <br/> name:${name }
We can audit by observing if the parameters passed in from ModelAndView are controllable or if there is any filtering.
You can see that no matter which way you use it, you will need to take it out and output at the end, except <%out. Println(msg);%> Is the el expression, that is, in audit xss you can also start with the el expression.