首先还是要思考一下几个问题
1.什么是Xss
2.如何在代码中找到他们
3.如何防护
那么带着这几大疑问,我们正式开始今天的探究
Xss的中文名称为跨站脚本攻击,为了和层叠样式表(Cascading StyleSheets,CSS)的缩写进行区分,故将跨站脚本攻击的英文缩写为XSS。XSS是一种在Web应用中常见的安全漏洞,它允许用户将恶意脚本植入到Web页面中,当其他用户访问此页面时,植入的恶意脚本就会在其他用户的客户端中执行。XSS漏洞的问题很多,可以通过XSS漏洞获取客户端用户的信息,比如用户登录的Cookie信息;可以通过XSS蠕虫进行传播;可以在客户端中植入木马;可以结合其他漏洞攻击服务器,在服务器中植入木马等, 一般来说,XSS的危害性没有SQL注入的大,但是一次有效的XSS攻击可以做很多事情,比如获取Cookie、获取用户的联系人列表、截屏、劫持等。根据服务器后端代码的不同,XSS的种类也不相同,一般可以分为反射型、存储型以及和反射型相近的DOM型。漏洞危害有:窃取Cookie,键盘记录,截屏,网页挂马,命令执行
总的来说,xss能干浏览器能干的所有事情,所以对于xss的防范,特别是存储型xss更是重中之重
那么我们如何发现他们
比如
输入
request.getParmeter(param)
${param}
输出
response.getWriter().print()
jsp中的 通过“request.getParameter”获取msg传入的值,然后通过“<%=msg%>”将其输出到网页中。
<%=变量%>
<%out.println%>
<%=%>
还有一种是 EL表达式
例如:
“<%=request.getParameter("username")%>”等价于“${param.username}”
其中还有 <c:out>输出 , <c:if> if判断执行, <c:forEach> 迭代输出
在model类中则还有这些
- <c:forEach ModelAndView- ModelMap- Model
而在代码中,根据我们之前搭建的java代码学习审计台可以看的更清晰
// 简单的反射型XSS,没对输出做处理。当攻击者输入恶意js语句时可触发@GetMapping("/reflect")public static String input(String content) { return content;}
我们可以很直接的看到,对于输入content参数 没有任何校验直接进行了返回,被浏览器当成js代码执行


防范,除了比较直接的类型限制,还可以
// 将特殊字符做转义
private static String XssFilter(String content) { content = StringUtils.replace(content, "&", "&"); content = StringUtils.replace(content, "<", "<"); content = StringUtils.replace(content, ">", ">"); content = StringUtils.replace(content, "\", """); content = StringUtils.replace(content, "'", "'"); content = StringUtils.replace(content, "/", "/"); return content;}
将所有能用到的字符进行转义,输出后,全都属于字符串类型


同时如果是spring 框架,同样会进行转义
// 采用Spring自带的方法会对特殊字符全转义
import org.springframework.web.util.HtmlUtils;
@GetMapping("/safe1")public static String safe1(String content) { return HtmlUtils.htmlEscape(content);}
对于富文本编辑器,可以这样修复
// 场景:针对富文本的处理方式,需保留部分标签
import org.jsoup.Jsoup;import org.jsoup.safety.Whitelist;
public static String safe3(String content) { Whitelist whitelist = (new Whitelist()) .addTags("p", "hr", "div", "img", "span", "textarea") // 设置允许的标签 .addAttributes("a", "href", "title") // 设置标签允许的属性, 避免如nmouseover属性 .addProtocols("img", "src", "http", "https") // img的src属性只允许http和https开头 .addProtocols("a", "href", "http", "https"); return Jsoup.clean(content, whitelist);
还可以使用控件库ESAPI
// ESAPI 是一个免费、开源的、网页应用程序安全控件库,它使程序员能够更容易写出更低风险的程序// 官网:https://owasp.org/www-project-enterprise-security-api/
public static String safe4(String content){ return ESAPI.encoder().encodeForHTML(content);}
还有其他一些存在漏洞的dome
1.经典的request.getParament
public void Message(HttpServletRequest req, HttpServletResponse resp) {
String message = req.getParameter("msg"); try { resp.getWriter().print(message); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
2.存储型dome,输入直接存入数据库
public void ShowMessage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub MessageInfoService msginfo = new MessageInfoServiceImpl(); List<MessageInfo> msg = msginfo.MessageInfoShowService(); if( msg != null){ req.setAttribute("msg", msg); req.getRequestDispatcher("/message.jsp").forward(req, resp); return ; } }
其中,MessageInfoShowService 主要是⽤于实例化
调⽤MessageInfoShowDao()类,该类内容如下:try { .... MessageInfoDaoImpl() ,然后调String sql = "select * from message"; ps = conns.prepareStatement(sql); rs = ps.executeQuery(); messageinfo = new ArrayList<MessageInfo>(); while(rs.next()){ MessageInfo msg = new MessageInfo(); msg.setName(rs.getString("name")); msg.setMail(rs.getString("mail")); msg.setMessage(rs.getString("message")); messageinfo.add(msg); } .... } }
主要执⾏的是从message 表中查询所有数据,然后将 name、mail、message 的值加到 messageinfo
List 中,最后返回给 servlet 层。
数据来源可以从这里看出,这段代码中有地址转发,在message.jsp 中存在以下内容:<% List<MessageInfo> msginfo = (ArrayList<MessageInfo>)request.getAttribute("msg");for(MessageInfo m:msginfo){ %> <table> <tr><td class="klytd"> 留⾔⼈:</td> <td class ="hvttd"> <%=m.getName() %></td> </tr> <tr><td class="klytd"> e-mail:</td><td class ="hvttd"> <%=m.getMail() %> </td> </tr> <tr><td class="klytd"> 内容:</td><td class ="hvttd"> <%=m.getMessage() %> </td></tr> </table> <% } %> </div>
而可以控制输入点的地方同样没有限制
这是两个比较常见的dome示例,真实环境可能会更加的复杂,所以要始终追着数据走,从输入到输出一步步校验
好了,今天的xss就说到这了,有什么不对的地方还请多多指教,笔者一定虚心请教并改正。









请登录后查看评论内容