JAVA代审之XSS漏洞
JAVA代审之XSS漏洞
T3Ysec T3Ysec 2025-05-05 15:06
一般来说,
XSS 的危害性没有 SQL 注入的大,
但是一次有效的 XSS 攻击可以做很多
事情,
比如获取 Cookie、
获取用户的联系人列表、
截屏、
劫持等。
根据服务器后端代码
的不同,
XSS 的种类也不相同,
一般可以分为反射型、
存储型以及和反射型相近的 DOM
型。
漏洞危害有:
窃取 Cookie,
键盘记录,
截屏,
网页挂马,
命令执行。
XSS 常见触发位置
1.JSP 表达式
“<%=变量 %>”是“<% out.
println(变量);
%>”的简写方式,
“<%=%>”用于将已声
明的变量或表达式输出到外网页中。
下面两种形式的写法实现的效果是相同的,
都是将变量输出到网页中。
形式一:
<%=msg%>
<% out.println(msg); %>
形式二:
<% String msg = request.getParameter('msg');%>
<%=msg%>
2.EL
EL(Expression Language,
表达式语言)是为了使 JSP 写起来更加简单。
EL 的灵感
来自于 ECMAScript 和 XPath 表达式语言,
它提供了在 JSP 中简化表达式的方法,
使得 JSP
的 代 码 更 加 简 化 。
例 如 :
“ <%=request.
getParameter(“username”)%> ”等价于
“${param.
username}”。
1)
out>标签
out>标签用来显示一个表达式的结果,
与<%= %>作用相似,
它们的区别是,
out>标签可以直接通过“.
”操作符来访问属性,
如下:
<c:out value="${user.getUsername()}"
2)
if>标签
if>标签用来判断表达式的值,
如果表达式的值为 true,
则执行其主体内容:
<c:if test="${user.salary > 2000}"
<p>我的工资为: value="${user.salary}"</p>
3)
forEach>标签
forEach>标签的作用是迭代输出标签内部的内容。
它既可以进行固定次数的迭代
输出,
也可以依据集合中对象的个数来决定迭代的次数:
<table>
<tr><th>名字</th><th>说明</th><th>图片预览</th></tr>
<c:forEach items="${data}" var="item">
<tr><td>${item.advertName}</td><td>${item.notes}</td><td><img src="${item.defPath}"/></td></tr>
</c:forEach>
</table>
<ul>
<li><a href='?nowPage=${nowPage-1}'>←上一页</a></li>
<c:forEach varStatus="i" begin="1" end="${sumPage}">
<c:choose>
<c:when test="${nowPage==i.count}">
<li class='disabled'>${i.count}</li>
</c:when>
<c:otherwise>
<li class='active'><a href='?nowPage=${i.count}'>${i.count}</a></li>
</c:otherwise>
</c:choose>
</c:forEach>
<li><a href='?nowPage=${nowPage+1}'>下一页→</a></li>
</ul>
3.ModelAndView 类的使用
ModelAndView 类用来存储处理完成后的结果数据,
以及显示该数据的视图,
其前端
JSP 页面可以使用“${参数}”的方法来获取值:
package com.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@RequestMapping("mvc")
@Controller
public class TestRequestMMapping {
@RequestMapping(value="/getMessage ")
public ModelAndView getMessage(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("messgae");
modelAndView.addObject("meggage", "Hello World");
return modelAndView;
}
}
4.ModelMap 类的使用
Spring 也提供了 ModelMap 类,
这是 java.
util.
Map 实现的,
可以根据模型属性的具体
类型自动生成模型属性的名称:
Public String testmethod(String someparam,ModelMap model){
//省略方法处理逻辑
//将数据放置到 ModelMap 类的 model 对象中,第二个参数可以是任何 Java 类型
Model.addAttribute("key",someparam);
return "success";
}
5.Model 类的使用
Model 类是一个接口类,
通过 attribue()添加数据,
存储的数据域范围是 requestScope:
Public String index1(Model model){
Model.addAttribute("result","后台返回");
Return "result";
}
常规XSS代码审计
<%=
${
<c:out
<c:if
<c:forEach
ModelAndView
ModelMap
Model
request.getParameter
request.setAttribute
response.getWriter().print()
response.getWriter().writer()
XSS 漏洞修复
前面已经讲过导致 XSS 漏洞的主要原因是输入可控并且没有经过过滤便直接输出,
因此防御 XSS 漏洞一般有以下几种方法。
(1)编写全局过滤器实现拦截,
并在 web.
xml 进行配置。
下面将给出一个网上使用较
多的拦截器样例。
WEB.
xml
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.ygj.control.XSSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>XSSFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>XSSFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
配置过滤器:
public class XSSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws
IOException, ServletException {
chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response);
}
}
实现包装类:
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class XSSRequestWrapper extends HttpServletRequestWrapper {
public XSSRequestWrapper(HttpServletRequest servletRequest) {
super(servletRequest);
}
@Override
public String[] getParameterValues(String parameter) {
String[] values = super.getParameterValues(parameter);
if (values == null) {
return null;
}
int count = values.length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = stripXSS(values[i]);
}
return encodedValues;
}
@Override
public String getParameter(String parameter) {
String value = super.getParameter(parameter);
return stripXSS(value);
}
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
return stripXSS(value);
}
private String stripXSS(String value) {
if (value != null) {
// NOTE: It's highly recommended to use the ESAPI library and uncomment the followingline to
// avoid encoded attacks.
// value = ESAPI.encoder().canonicalize(value);
// Avoid null characters
value = value.replaceAll("", "");
// Avoid anything between script tags
Pattern scriptPattern = Pattern.compile("(.*?)", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid anything in a src="http://www.yihaomen.com/article/java/..." type of e-xpression
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE |
Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE |
Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Remove any lonesome tag
scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Remove any lonesome tag
scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE |
Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid eval(...) e-xpressions
scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE |
Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid e-xpression(...) e-xpressions
scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE |
Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid javascript:... e-xpressions
scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid vbscript:... e-xpressions
scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid onload= e-xpressions
scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE |
Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
}
return value;
}
}
(2)采用开源安全控制库(OWASP)企业安全应用程序接口(ESAPI)实现,
类似的还有谷歌的 xssProtect 等。
// HTML Context
String html = ESAPI.encoder().encodeForHTML("<script>alert('xss')</script>");
// HTML Attribute Context
String htmlAttr = ESAPI.encoder().encodeForHTMLAttribute("<script>alert('xss')</script>");
// Javascript Attribute Context
String jsAttr = ESAPI.encoder().encodeForJavaScript("<script>alert('xss')</script>");
(3)对所有字符采用 HTML 实体编码。
<%
String Str = "<script>alert('XSS')</script>";
Str = Str.replaceAll("\"",""");
Str = Str.replaceAll("&","&");
Str = Str.replaceAll("\\(","(");
Str = Str.replaceAll("<","<");
Str = Str.replaceAll(">",">");
Str = Str.replaceAll("\'","'");
Str = Str.replaceAll("\\)",")");
out.println(Str);
%>
参考很多这里就不注明了,因为我觉得这些知识点没什么可以扩展