XSS攻击详解

XSS

跨站点脚本(Cross-site scripting,XSS)是一种允许攻击者在另一个用户的浏览器中执行恶意脚本的脚本注入式攻击。
攻击者并不直接锁定受害者。而是利用一个受害者可能会访问的存在漏洞的网站,通过这个网站间接把恶意代码呈递给受害者。对于受害者的浏览器而言,这些恶意代码看上去就是网站正常的一部分,而网站也就无意中成了攻击者的帮凶。

反射型XSS

发送请求时,XSS代码出现在URL中(反射型的典型特征),作为输入提交到服务器端,服务器端解析后响应(search中包含XSS代码,可以是js或者HTML或者CSS),XSS代码随着响应内容一起传回浏览器,最后浏览器解析执行XSS代码,这个过程像一个反射,所以叫做反射型XSS。
我们用node迅速起一个服务,在URL中输入

   localhost:3000/?xss=<img src="null" onerror="alert(1)" />

然后在express框架中把xss字段的值返回到视图层。我们会发现alert并没有执行,打开控制台发现浏览器使用了拦截。我们可以先在node服务中把这个禁掉

   res.set('X-XSS-Protection', 0);

这时候XSS攻击就生效了。
如果我们想在页面中引诱用户点击,那么就可以使用这样的方式

   localhost:3000/?xss=<p onclick="alert(1)">点我</p>

也可以使用iframe来嵌入页面,这就可以非常容易地植入广告

   localhost:3000/?xss=<iframe src="//baidu.com"></iframe>

当黑客将这个链接发给用户的时候,用户点击了这个链接,就会收到这样的攻击

存储型XSS

存储型XSS和反射型XSS的区别只在于,提交的恶意代码会存储在服务器端(XSS是在URL中),下次请求页面时不用再提交恶意脚本。
下面的例子是一个简单的服务端脚本,作用是展现网站上最新的评论:

    print "<html>"
    print "Latest comment:"
    print database.latestComment
    print "</html>"

这段脚本假设评论只由文本组成。但是因为用户的输入直接被包含进页面中,所以攻击者可能提交这样的评论:<script>...</script>。任何访问这个页面的用户都会收到下面这样的返回:

    <html>
    Latest comment:
    <script>...</script>
    </html>

当用户的浏览器加载页面时,浏览器会执行<script>标签中的任何脚本。这样以来攻击者就成功的完成了一次攻击。

XSS的后果

首先要明确的是,在受害者的浏览器中执行脚本的能力算不上特别恶意,js的执行环境受到严格限制并只有非常有限的权限访问用户的文件和操作系统。事实上,你现在就可以打开你浏览器的脚本控制台立刻执行任何你想执行的脚本,几乎不可能对你的电脑造成任何的伤害。但是恶意脚本有以下的权限

  • js有权访问一些用户的敏感信息,比如cookie
  • js能够通过XMLHttpRequest或者其他一些机制发送带有任何内容的HTTP请求到任何地址。
  • js能够通过DOM操作方法对当前页面的HTML做任意修改。

这种在其他用户的浏览器中执行任意脚本的权限,赋予了攻击者有能力发动以下几类攻击

  • Cookie窃取:攻击者能够通过document.cookie访问受害者与网站关联的cookie,然后传送到攻击者自己的服务器,接着从这些cookie中提取敏感信息,如Session ID。(使用一个隐藏的标签,可以参考我另一篇博文 CSRF攻击 中的cookie劫持)
  • 记录用户行为(Keylogging):攻击者可以使用 addEventListener方法注册用于监听键盘事件的回调函数,并且把所有用户的敲击行为发送到他自己的服务器,这些敲击行为可能记录着用户的敏感信息,比如密码和信用卡号码。
  • 钓鱼网站(Phishing):攻击者可以通过修改DOM在页面上插入一个假的登陆框,也可以把表单的action属性指向他自己的服务器地址,然后欺骗用户提交自己的敏感信息。

尽管这些攻击类型大不相同,但都有一条重要的相似之处:因为攻击者把代码注入进的页面是由网站的,所以恶意脚本都是在网站的上下文环境中执行,这就意味着恶意代码被当作网站提供的其他正常脚本一样对待,这些事实都在强调一个关键性问题:如果攻击者能够借助你的网站在另一个用户的浏览器中执行任意脚本,那么你网站的安全性已经无从谈起了。

XSS的防御措施

首先是编码的问题,我们不能让用户的输入保持原样,所以我们要对用户输入的数据进行HTML Entity编码。
其次是过滤,移除用户上传的DOM属性,如onerror(所有DOM事件)等。移除用户上传的Style节点(如html{ display: none !important}),Script节点(具有100%权限,容易触发CSRF攻击),iframe节点等。
最后是校正。首先我们要避免对HTML Entity解码(解码过程中已经被执行)。使用DOM Parse 转换,校正不配对的DOM标签

具体操作

在服务器端实现一个html_encode函数

   //进行一个最简单的编码
   function html_encode(str){
       s = str.replace(/&/g, '&gt;');
       //replace '<'
       s = s.replace(/</g, '&lt;');
       s = s.replace(/>/g, '&gt;');
       //空格符
       s = s.replace(/\s/g, '&nbsp;');
       s = s.replace(/\'/g, '&#39;');
       s = s.replace(/\"/, '&quot;');
       s = s.replace(/\n/g, '<br>');
       return s;
   }

而在客户端,可以使用自定义或者引入的domParse库对返回数据进行校正

   var parse = function(str) {
       var results = '';
       try {
           //对标签进行配对
           ...domParse 
       } catch(e) {
       } finally {
       }
   }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值