XSS研究4-来自外部的XSS攻击的防范

简介:

引入:

这篇文章我们来专门探讨如何防范来自外部的XSS攻击。


实践:

其实从http://supercharles888.blog.51cto.com/609344/1339921 文章中可以看出,主要的攻击手段无让攻击者机器上运行一段JS,这段js中包含一段对于document.cookie的处理,如果这个能拿到正确的值,那么就可以用获取的信息发送到攻击者的某个指定机器上,从而盗用。所以从这个思路上想解决方法就很容易了,就是通过一段机制,让植入到攻击者机器上的恶意的js代码中拿document.cookie拿不到内容。


能实现这一点么,简单查阅了下文档,发现了原来有Cookie 有个HttpOnly这么个标记,如果把它设置为true的时候,那么这个cookie只能通过http协议访问,而无法通过javascript 脚本,或者applet进行访问。我们在想,既然信息的盗用都是一段js脚本去拿到document.cookie的内容,那么如果设置Cookie为HttpOnly后,是否解决问题了呢?


为此,我们做个实验,我们让Cookie用java代码生成而不是和上文连接中的用某段js生成(这样做的目的是万一HttpOnly真起作用了,那么我们设置Cookie的这段js代码就生效了)

代码很简单,我们做了一个Servlet,然后让用户访问这个Servlet的时候,它会创建一个Cookie(现在hard-coded):为了比较,我们先做一个不设置HttpOnly的例子:

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package  com.charles.study;
import  java.io.IOException;
import  java.io.PrintWriter;
import  javax.servlet.ServletException;
import  javax.servlet.http.Cookie;
import  javax.servlet.http.HttpServlet;
import  javax.servlet.http.HttpServletRequest;
import  javax.servlet.http.HttpServletResponse;
/**
  * 这个Servlet用于产生一个Cookie
  * @author charles.wang
  *
  */
public  class  CookieServlet  extends  HttpServlet{
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
     public  void  doGet(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
         buildResponseWithCookie(response);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
     }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
     /**
      * hard-code一个Cookie信息,并且写到客户端
      * @param response
      * @throws IOException
      */
     private  void  buildResponseWithCookie(HttpServletResponse response)  throws  IOException {
         response.setContentType( "text/html;charset=utf-8" );
         PrintWriter out = response.getWriter();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
         Cookie cookie =  new  Cookie( "charles" , "1234567890" );
         cookie.setMaxAge( 24 * 3600 );
         cookie.setPath( "/" );
         response.addCookie(cookie);
         out.println( "Already Written Cookie to Client" );
     }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
     public  void  doPost(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
         doGet(request, response);
     }
}


然后在 web.xml中定义好 servlet-mapping(略去)

然后当我们访问页面时候,打开Firebug,切换到Cookie标签:

123446332.png

可以看到,默认情况下,这个CookieHttpOnly属性是没有设置值的(下方表格第七栏)

现在,我们切换到Console标签页,然后输入document.cookie:

123640124.png

红色部分显示,这时候我们是拿得到cookie的值的,也就是说js完全可以获取cookie的内容。


现在我们把我们的代码变下,在创建cookie的地方,加一行 cookie.setHttpOnly(true);


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
      * hard-code一个Cookie信息,并且写到客户端
      * @param response
      * @throws IOException
      */
     private  void  buildResponseWithCookie(HttpServletResponse response)  throws  IOException {
         response.setContentType( "text/html;charset=utf-8" );
         PrintWriter out = response.getWriter();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
         Cookie cookie =  new  Cookie( "charles" , "1234567890" );
         cookie.setMaxAge( 24 * 3600 );
         cookie.setPath( "/" );
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
         //以下这行专门用于解决来自外部的XSS攻击问题
         cookie.setHttpOnly( true );
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
         response.addCookie(cookie);
         out.println( "Already Written Cookie to Client" );
     }

其他不变,然后我们重复上面实验,我们打开这个servlet页面,打开Firebug,切换到Cookie标签

124119518.png

这时候可以发现第7列HttpOnly属性被设置了。

现在,我们切换到Console标签页,然后输入document.cookie:

124412888.png

这次我们发现,这个Cookie不再显示“charles=1234567890"了,取而代之的是,它只显示""空,这就表明,我们的HttpOnly属性起作用了。我们的恶意js无法通过document.cookie拿到任何有价值信息。


结论的延伸:

于是,从上面2个实验对比,我们发现了HttpOnly属性是解决来自外部XSS攻击的关键属性,我们不满足上面实验,我们还可以进行扩展,因为上述实验中,我们是让response直接添加了一个cookie, 然现实中的例子多数是通过会话HttpSession,然后它的scope上添加了一些机密信息,并且维护在服务器端的。然后客户端也会有一个id去引用这个对应的session,那么这个Session是否可以使用HttpOnly属性呢?答案是肯定的。

如果你使用的是servlet 3.0+的版本,那么在对应的web.xml中,可以天然的通过下面一段代码来配置HttpOnly属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version= "1.0"  encoding= "UTF-8" ?>
<web-app version= "3.0"  xmlns= "http://java.sun.com/xml/ns/javaee"
     xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation= "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" >
     <display-name>XSSDemo</display-name>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
     <session-config>
         <cookie-config>
             <http-only> true </http-only>
         </cookie-config>
     </session-config>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
..

这里,注意我们的xsd是servlet 3.0的xsd,所以我们可以在<session-config>中使用 <cookie-config>子元素,然后用<http-only>true来启用这个HttpOnly特征。

我们来做个实验证明,我们修改下CookieServlet,从而当我们访问这个Servlet时候他会创建一个Session:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public  class  CookieServlet  extends  HttpServlet{
                                                                                                                                                                                                                                                                                                                                                                                                         
     public  void  doGet(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
         HttpSession session= request.getSession();
         session.setAttribute( "charles_session" , "9876543210" );
                                                                                                                                                                                                                                                                                                                                                                                                             
         response.setContentType( "text/html;charset=utf-8" );
         PrintWriter out = response.getWriter();
         out.println( "Session Created" );
                                                                                                                                                                                                                                                                                                                                                                                                              
     }
                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                       
     public  void  doPost(HttpServletRequest request, HttpServletResponse response)
             throws  ServletException, IOException {
         doGet(request, response);
     }
}

然后我们访问页面:

125850183.png

显然,从第七列看出来,这个刚创建的Session Cookie ,它的HttpOnly被正确的设置了。


总结:

我们做了几个实验,大体上解决了外部XSS攻击的问题,主要是通过设置HttpOnly属性,这个属性可防止js或者applet去操作cookie,而且它不仅适用于一般的Cookie,也适用于Session Cookie. 其实它的思想很简单,既然外部XSS攻击是你把情报带出去,那么我海关就严格一条,任何纸条只要通过海关就”烧“掉(我只是打个比方) ,这样你不管如何,你都不能通过恶意代码从这个灰烬的纸条中拿到信息了。


实践上看,对于一般的Cookie,只要在它创建的时候,设置cookie.setHttpOnly(true).

对于Session Cookie,如果你的app容器支持servlet 3.0规范,那么只要配置 <cookie-config>让其启用<http-only>就可以了,如果你的app容器比较老,那么你必须通过覆写SET-COOKIE的 Http响应头来显式添加HttpOnly标志。

1
2
3
//通过覆写SET-COOKIE的 Http响应头来显式的添加HttpOnly
  String sessionid = request.getSession().getId();
  response.setHeader( "SET-COOKIE" "JSESSIONID="  + sessionid +  "; HttpOnly" );


其实,现在主流的浏览器都能很好的支持HttpOnly了,黑客们要入侵难度又加大了。





本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1341060,如需转载请自行联系原作者
目录
相关文章
|
7月前
|
JavaScript 安全 前端开发
同源策略如何防止 XSS 攻击?
【10月更文挑战第31天】同源策略通过对 DOM 访问、Cookie 访问、脚本执行环境和跨源网络请求等多方面的严格限制,构建了一道坚实的安全防线,有效地防止了 XSS 攻击,保护了用户在网络浏览过程中的数据安全和隐私。
211 49
|
7月前
|
安全 前端开发 Java
Web安全进阶:XSS与CSRF攻击防御策略深度解析
【10月更文挑战第26天】Web安全是现代软件开发的重要领域,本文深入探讨了XSS和CSRF两种常见攻击的原理及防御策略。针对XSS,介绍了输入验证与转义、使用CSP、WAF、HTTP-only Cookie和代码审查等方法。对于CSRF,提出了启用CSRF保护、设置CSRF Token、使用HTTPS、二次验证和用户教育等措施。通过这些策略,开发者可以构建更安全的Web应用。
243 4
|
7月前
|
安全 Go PHP
Web安全进阶:XSS与CSRF攻击防御策略深度解析
【10月更文挑战第27天】本文深入解析了Web安全中的XSS和CSRF攻击防御策略。针对XSS,介绍了输入验证与净化、内容安全策略(CSP)和HTTP头部安全配置;针对CSRF,提出了使用CSRF令牌、验证HTTP请求头、限制同源策略和双重提交Cookie等方法,帮助开发者有效保护网站和用户数据安全。
211 2
|
7月前
|
存储 安全 Go
Web安全基础:防范XSS与CSRF攻击的方法
【10月更文挑战第25天】Web安全是互联网应用开发中的重要环节。本文通过具体案例分析了跨站脚本攻击(XSS)和跨站请求伪造(CSRF)的原理及防范方法,包括服务器端数据过滤、使用Content Security Policy (CSP)、添加CSRF令牌等措施,帮助开发者构建更安全的Web应用。
315 3
|
8月前
|
存储 JavaScript 前端开发
Xss跨站脚本攻击(Cross Site Script)
Xss跨站脚本攻击(Cross Site Script)
|
7月前
|
SQL 存储 安全
什么是XSS攻击?什么是SQL注入攻击?什么是CSRF攻击?
理解并防范XSS、SQL注入和CSRF攻击是Web应用安全的基础。通过采用严格的输入验证、使用安全编码实践以及实现适当的身份验证和授权机制,可以有效防止这些常见的Web攻击,保障应用程序和用户的数据安全。
166 0
|
9月前
|
存储 安全 JavaScript
XSS跨站脚本攻击详解(包括攻击方式和防御方式)
这篇文章详细解释了XSS跨站脚本攻击的概念、原理、特点、类型,并提供了攻击方式和防御方法。
2355 1
|
8月前
|
存储 JavaScript 安全
|
10月前
|
存储 安全 JavaScript
解释 XSS 攻击及其预防措施
【8月更文挑战第31天】
826 0
|
10月前
|
SQL 监控 安全
在Linux中,如何检测和防止SQL注入和跨站脚本(XSS)攻击?
在Linux中,如何检测和防止SQL注入和跨站脚本(XSS)攻击?