XSS 小结
2016-09-14 17:14
267 查看
前言
上一篇文章中写了关于项目中处理SQL盲注的安全漏洞.其中也提到了
XSS.这篇文章就来说一下XSS 是怎么来进行攻击的,如何对其进行防御.
概述
XSS攻击:跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为
XSS。
XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。比如这些代码包括HTML代码和客户端脚本。攻击者利用
XSS漏洞旁路掉访问控制——例如同源策略(same origin policy)。这种类型的漏洞由于被黑客用来编写危害性更大的网络钓鱼(Phishing)攻击而变得广为人知。对于跨站脚本攻击,黑客界共识是:跨站脚本攻击是新型的“缓冲区溢出攻击“,而JavaScript是新型的“ShellCode”。
`XSS`攻击的危害包括: 1、盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号 2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力 3、盗窃企业重要的具有商业价值的资料 4、非法转账 5、强制发送电子邮件 6、网站挂马 7、控制受害者机器向其它网站发起攻击
—-摘自百度百科 XSS攻击
原理
我们首先搭建一个简易的环境来模拟XSS攻击 ,其中
xssTest.jsp代码如下
模拟XSS攻击实例 1
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Insert title here</title> </head> <body> <form action="xssTestServltet" method="get"> <input type="txt" name="userName"> <input type="submit" value="提交"> </form> <hr> 您输入的账户为: ${userName } </body> </html>
后台处理
xssTestServlter.java
@WebServlet("/xssTestServltet") public class XssTestServltet extends HttpServlet{ @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //接受参数 String userName=request.getParameter("userName"); //存储数据到 作用域 request.setAttribute("userName", userName!=null?userName:""); //跳转到原页面. request.getRequestDispatcher("/xssTest.jsp").forward(request, response); } }
然后我们请求到测试页面
我们尝试输入 qazxc110,得到的结果为:
此时页面源代码为:
我们注意到,我们的输入的字符被原封不动的显示在 15行的位置.那么我们试想一下,如果我们在输入框中输入 这样一段代码:
<script>alert('xss')</script>,会是什么样子.按照刚才的测试,那么这次源码中在刚才的位置就应该显示
<script>alert('xss')</script>这串代码相当于在展示的位置插入了一段javaScript 代码,那么就应该执行alert弹出弹窗 并打印
xss.
我们按照刚才的假设,在代码中实验.我们输入
<script>alert('xss')</script>这串代码在文本框中,然后提交页面.然后我得到了一下页面:
这时我们看到浏览器出现了弹窗,说明刚才的那段
script代码执行了.这个时候也就基本说明了,页面存在
XSS漏洞了.
此时的页面源码为:
这是一种非常简单的方式.我们只是在页面上弹窗一个字符串而已,显然是执行了
<script></script>中的代码.那么这里面不但可以写弹窗代码,还可以写其他比如让页面跳转到一个指定的地址.如果这个地址的页面是一个跟当前页面相似的钓鱼页面的话,后果不堪设想.
很多网站都有留言模块.我们可以在留言板上插入一段恶意的代码,提交到后台.由于这段代码是保存在服务器上,若管理员并没有去及时发现并删除这段留言的代码,当范文留言列表的时候,留言会被加载出来.当用户访问这个留言的页面时,这段恶意代码就会执行.实例如下:
模拟XSS攻击实例 2
/** * 原页面访问地址. * */ @WebServlet("/xssTestServltet") public class XssTestServltet extends HttpServlet{ @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //接受参数 String userName=request.getParameter("userName"); //存储数据到 作用域 request.setAttribute("userName", userName!=null?userName:""); //模拟存储一个cookie 到 客户端.在xss 攻击链接中获取. Cookie cookie = new Cookie("xxzx","1234"); response.addCookie(cookie); //模拟数据库中存储的留言. request.setAttribute("ly1", "xxzx"); //模拟数据库中存储的留言.这里插入了一段 script 代码.去访问src 对应的xss 攻击 链接. request.setAttribute("ly2", "<script src='http://localhost:8080/XssTestServlet2'></script>么么哒"); //跳转到原页面. request.getRequestDispatcher("/xssTest.jsp").forward(request, response); } }
/** * 模拟留言中 xss 攻击的 地址. * */ @WebServlet("/XssTestServlet2") public class XssTestServlet2 extends HttpServlet{ @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("访问了攻击地址......."); //得到cookies Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) { System.out.println("name:"+cookie.getName()); System.out.println("value:"+cookie.getValue()); } } }
这时我们任意用户在浏览器中访问 留言页面时,页面的代码:
在
留言2的后面,还去加载了一个 我们之前定义好的
XSS链接 .这样一来我们除了请求正常的地址,页面还另外请求了攻击的地址:
而在我们XSS 攻击地址的后台.我们获取到了这些信息:
当管理员进入后台来浏览留言时,就会触发,然后管理员的cookie 后后台地址 等等一系列信息都可以被拿到,然后攻击者就可以用一些cookie欺诈工具来更改管理员的cookie ,就可以不用输入账号,密码 也可以以管理员的身份登录进系统.
解决方案
为解决上面出现的问题,现提供两种解决方案.方案 1
我们使用一个第三方的jar 包.调用第三方的api 来防止 XSS 攻击带来的危险.具体步骤如下:首先,添加 apache 的commons-lang-2.6.jar .
然后,在后台调用
StringEscapeUtils.escapeHtml(string);
StringEscapeUtils.escapeJavaScript(string);
StringEscapeUtils.escapeSql(string);对请求过来的参数进行转义,若还需要这些值到前台.我们可以使用;
StringEscapeUtils.unescapeXXX(String);(
XXX可以表示
Html,
JavaScript,
Sql,
Xml等) 来进行反转义,或者在前台使用js 调用escape 可是可以的.
后台处理action:
@RequestMapping("/stringEscapeUtils") public void stringEscapeUtils(HttpServletRequest request,HttpServletResponse response){ String str=request.getParameter("username"); System.out.println("username: "+str); System.out.println("escapeSql: "+StringEscapeUtils.escapeSql(str)); System.out.println("escapeHtml: "+StringEscapeUtils.escapeHtml(str)); System.out.println("escapeJavaScript: "+StringEscapeUtils.escapeJavaScript(str)); }
当我们前台输入:
<script>alert('1')</script>时,后台的输出结果为:
注意:
commons-lang-3.x里面已经没有
escapeSql
escapeJavaScript方法,取而代之的是
escapeEcmaScript.具体的使用方法,就请自行验证了.
方案 2
这里我们重点说一下方案二.这也是我们解决XSS攻击时采用的一种方式.
前面我们说到
XSS攻击无非就是我们对于参数的过滤没有做好.导致一些不安全的字符被原封不动的进入到我们的业务中.那么最终就是对参数进行过滤.在这种方案中.我们需要自己写一个
Filter,使用
Filter来过滤发出的请求.对于每个post 的请求的参数过滤一些关键字,把他们替换成安全的.例如:
< > ' " \ / # &,方法是实现一个自定义的
HttpServletRequestWrapper,然后在
Filter里面调用它替换
getParameter方法即可,具体步骤如下.
首先 我们在后台添加一个
XssHttpServletRequestWrapper类,让它继承
javax.servlet.http.HttpServletRequestWrapper,代码如下:
package com.zhouq.filter.Xss; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** 对请求 的参数 进行 Xss 安全过滤 * @author zhouq * */ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { public XssHttpServletRequestWrapper(HttpServletRequest request) { super(request); } /** * 替换 getParameterValues */ public String[] getParameterValues(String parameter) { String[] values = super.getParameterValues(parameter); if (values == null) { return null; } int count = values.length; String[] eccodedValues = new String[count]; // 对每个参数值进行 XSS 清理 for (int i = 0; i < count; i++) { eccodedValues[i] = cleanXSS(values[i]); } return eccodedValues; } /** * 替换 getParameter */ public String getParameter(String parameter){ String value=super.getParameter(parameter); if(value!=null){ //对参数值进行 XSS 清理 value=cleanXSS(value); } return value; } public String getHeader(String name) { String value = super.getHeader(name); if (value == null) return null; return cleanXSS(value); } /** XSS 清理 * @param value * @return */ private String cleanXSS(String value) { System.out.println("清理前 :"+value); value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;"); value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;"); value = value.replaceAll("'", "& #39;"); value = value.replaceAll("eval\\((.*)\\)", ""); value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); value = value.replaceAll("script", ""); System.out.println("清理后 :"+value); System.out.println("----------------------------------------------------------"); return value; } }
然后我们还需要在后台添加一个过滤器
XssFilter,让它实现
javax.servlet.Filter,具体代码如下:
package com.zhouq.filter.Xss; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; public class XssFilter implements Filter { FilterConfig config = null; @Override public void destroy() { this.config = null; } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //执行 我们自己定义的 XssHttpServletRequestWrapper chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response); } @Override public void init(FilterConfig config) throws ServletException { this.config = config; } }
最后,我们还需要在web.xml 中应用 这个过滤器.web.xml 中的配置如下:
<!-- 配置自实现的 XSS 过滤器 --> <filter> <filter-name>XssFilter</filter-name> <filter-class>com.zhouq.filter.Xss.XssFilter</filter-class> </filter> <filter-mapping> <filter-name>XssFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>
到这里.我们的
XSS清理就编写完成了.每一次请求中的危险字符,敏感信息都会被过滤掉,您可以去测试一下是否对您的应用生效.当然了,如果您要处理更多的字符,那么您可以继续在
cleanXSS中去添加你需要处理的东西.当然,需要注意的是,一些必要的字符不能被过滤,否则就改变了用户的真实数据.比如在我们当前系统中在为菜单添加操作的时候 会有前缀为
javascript的代码.那么这里就会被过滤掉.如果你应用中也出现这种情况,那么就得请您自己做取舍了.
假设登录页面有个输入用户名和密码的输入框,可以有很多
XSS
CSRF 注入钓鱼网站
SQL注入等的攻击手段,例如:
输入用户名 : >"'><script>alert(1779)</script> 输入用户名: usera>"'><img src="javascript:alert(23664)"> 输入用户名: "'><IMG SRC="/WF_XSRF.html--end_hig--begin_highlight_tag--hlight_tag--"> 输入用户名: usera'"><iframe src="http://demo.testfire.net--en--begin_highlight_tag--d_highlight_tag--"> 密码随意输入。
下面提供了一个登录页面的攻击实例,你可以通过下面的方式进行简单的测试:
用户名: `1' or '1'='1` 密码:`<script>alert('xss')</script>`
测试结果:
结束语
到这里,XSS攻击的防御措施就写完了,使用
Filter的这种方式,不仅仅可以防御
XSS攻击,还可以防御
CSRF攻击,
SQL注入等安全问题。
参考资料
freebuf.com XSS系列文章CSDN WEB安全实战系列文章
相关文章推荐
- xss漏洞挖掘小结
- xss,csrf入侵方式小结 站内的GET和POST 与 站外的GET与POST
- xss,csrf入侵方式小结 站内的GET和POST 与 站外的GET与POST
- xss测试用例小结
- DVWA1.9平台XSS小结
- XSS跨站脚本小结(转)
- XSS跨站脚本小结
- Web程序中网页间数据传递方法小结
- VC目录操作小结
- C++静态成员小结
- 奋斗黑马程序员----Java之File对象小结
- 2014.3.6-C语言学习小结
- php中异常处理方法小结
- PHP中set error handler函数用法小结
- java多线程小结
- 小结
- static用法小结
- Linux设置环境变量小结
- Spring中JdbcTemplate小结
- 在新窗口打开超链接的方法小结