博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
XSS研究4-来自外部的XSS攻击的防范
阅读量:6815 次
发布时间:2019-06-26

本文共 5195 字,大约阅读时间需要 17 分钟。

引入:

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


实践:

其实从 文章中可以看出,主要的攻击手段无让攻击者机器上运行一段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标签:

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

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

红色部分显示,这时候我们是拿得到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标签

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

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

这次我们发现,这个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);
    
}
}

然后我们访问页面:

显然,从第七列看出来,这个刚创建的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,如需转载请自行联系原作者
你可能感兴趣的文章
第一个Ionic应用
查看>>
codeforces730I Olympiad in Programming and Sports(姿势题 优先队列?dp?)
查看>>
POJ 3260 The Fewest Coin
查看>>
201421410018 于佳裔 实验四
查看>>
【VUE】@click加上v-bind绑定切换类名及动画事件
查看>>
Microsoft发布新一代主机:Xbox One
查看>>
运维经验分享:关于系统运维监控的几点建议
查看>>
jQuery渐隐渐现字体发虚的问题
查看>>
[SDOI2008]烧水问题
查看>>
杂项之rabbitmq
查看>>
【转】关于大型网站技术演进的思考(十)--网站静态化处理—动静整合方案(2)...
查看>>
jQuery练习题HTML文件
查看>>
SQL注入原理
查看>>
MySQL 锁(lock与latch)
查看>>
python
查看>>
DataTable数据存入指定路径的Excel文件
查看>>
Linq-C#左连接
查看>>
c和指针读书笔记
查看>>
常用正则表达式集锦
查看>>
JS 验证
查看>>