概念
XSS,跨站脚本攻击 (Cross Site Scripting),是一种经常出现在 web 应用中的计算机安全漏洞,它允许恶意 web 用户将代码植入到提供给其它用户使用的页面中。比如这些代码包括 HTML 代码和客户端脚本。
攻击者利用 XSS 漏洞旁路掉访问控制——例如同源策略 (same origin policy)。这种类型的漏洞由于被骇客用来编写危害性更大的 phishing 攻击而变得广为人知。
对于跨站脚本攻击,黑客界共识是:跨站脚本攻击是新型的 “缓冲区溢出攻击 “,而 JavaScript 是新型的 “ShellCode”。
XSS 的分类
反射型XSS
这种类型的 XSS 攻击是最常见的,就是把恶意脚本提交到 URL 地址的参数里。反射性 XSS 只执行一次,且需要用户触发。
这里写了一个简单的页面
<form action="" method="post">
<input type="text" name="name">
<input type="submit" name="submit" value="提交">
</form>
<?php
if( @ $_POST['submit'] == "提交"){
$name=trim($_POST['name']);
echo "hello".$name;
}
输入后下面显示hello
这个时候我们可以输入特定的标签,由于页面未作任何过滤操作,我们可以输入一些标签,就会显示出来,比如输入<script>alert(1)</script>,就会执行,这样的代码就出现了xss漏洞
那么这种漏洞如何修复呢?
可以在代码中加入替换函数,将<script>标签替换为' ':
$name=str_replace('<script>','',$name);
但是我们可以输入<sc<script>ript>alert(1)</script> ,弹窗就又会出现。
第二种防护方法是利用正则替换:
$name=preg_replace('/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t(.*)/i','',$name);
这时再输入<sc<script>ript>alert(1)</script>就会全被替换成' ',并没有弹窗
这时可以输入一个不存在的图片,利用onerror.输入<img src="1" οnerrοr="alert(1)">,会弹出相同的警告框,并且hello后面出现一个图片,但显然这个图片根本不存在。
对付这种漏洞就要使用第三种方法了,把预定义字符"<",">","&"等转化为HTML实体,防止浏览器将其作为HTML元素:
$name=htmlspecialchars($name);
输入相同的内容,不再出现弹窗
补充:常见的实体编码
存储型XSS
储存性 XSS需要服务端接收并且存入数据库,当用户访问这个页面时,这段 XSS 代码会自己触发。储存性 XSS 只执行一次,不需要有客户端去手动触发操作。
存储型漏洞涉及数据库,以MySQL为例,先写一个简单的页面,存储型漏洞一般存在于个人信息,评论留言。
先建一个表comment来存储用户评论
由于只是演示,就不再判断用户名与评论是否符合条件
<form action="" method="post">
用户名<input type="text" name="name">
<br>
留言<input type="text" name="comment">
<br>
<input type="submit" name="submit" value="提交">
</form>
<?php
$server = "localhost";
$db_user = "root";
$db_psw = "123456";
$conn = mysqli_connect($server, $db_user, $db_psw); //连接数据库
if (!$conn)
die("error!" . $conn->connect_error);
mysqli_select_db($conn, "test"); //选择数据库
$rel = mysqli_query($conn, "SELECT * FROM comment");
while($row = mysqli_fetch_assoc($rel)){
$name = $row['name'];
$comment = $row['comment'];
echo $name.'<br>'.$comment.'<br>';
}
if( @ $_POST['submit'] == "提交"){
$name=trim($_POST['name']);
$comment=trim($_POST['comment']);
mysqli_query($conn,"INSERT INTO comment(name,comment) VALUES ('$name','$comment')");
echo "<script>alert('添加成功');</script>";
}
先写入几条评论,打开时显示这样
用相同的方法,我们在输入时可以输入一些标签,在该页面展示评论时即可展示出来。
输入<script>alert(1)</script>,其他用户打开即会出现提示窗口,评论的内容变成了标签,所以显示在下面是空白
第一种解决办法是通过strip_tags(addslashes())将标签删掉
$name=strip_tags(addslashes($name));
$comment=strip_tags(addslashes($comment));
此时输入相同的语句<script>alert(1)</script>,数据库存储的只是除了标签的部分
第二种办法也是把预定义字符"<",">","&"等转化为HTML实体:
$name=htmlspecialchars($name);
$comment=htmlspecialchars($comment);
这种方法展示在网页上的内容没有发生改变
当然可以在数据存储时进行防护,也可以在数据展示时进行,由于代码一样,这里就不介绍了。
DOM XSS
DOM XSS 就是出现在 javascript 代码中的 xss 漏洞,不需要服务端交互,只发生在客户端传输数据的时候,原理同反射型XSS相同。今天刚好写了一道这样的题,就拿这个题举例了,题目如下欢迎来到level2
先随便输入看见输入的内容插入在value处,所以可以输入test" οnclick="alert(1)
test"和前面的”构成一个闭合引号,后面加入一个事件,和后面的引号闭合。
其他类型
由于还没接触其他类型,接触到再补充。
简单漏洞绕过
01<>被过滤的情况下
假如在特殊标签下的时候,可以构造一些事件触发
"autofocus οnfοcus=alert(1)
02alert被过滤的情况下
注:prompt和confirm也可以弹窗
<a href=data:text/html;base64,PHNjcmlwdD5hbGVydCqzKTwvc2NyaXB0Pq (firefox可,chrome不行)
<svg/οnlοad=prompt(1)/>
<a href=javascript:alert(13)>M
03on事件被过滤的情况下
<form><button formaction=javascript:alert(1)>M
<a href="javascript:alert(document.location);">XSS</ a>
<b style="width:expression(alert(document.location));">XSS</b> (IE6以下可)
<math><a xlink:href=javascript:alert(1)>1</ a></math>(firefox可,chrome不可)
可以执行js的属性:
formaction action href xlink:href src content data
04其他
标签和属性之间并不是只能出现空格
<img/src=x οnerrοr=alert(1)>
有时候并不需要一个合法的标签
<M/οnclick="alert(1)">M