首先还是要思考一下几个问题
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就说到这了,有什么不对的地方还请多多指教,笔者一定虚心请教并改正。
请登录后查看评论内容