XSS-过滤特殊符号的正则绕过

靶场网址:https://xss.pwnfunction.com/

题目源码:

php 复制代码
    mafia = (new URL(location).searchParams.get('mafia') || '1+1')
    mafia = mafia.slice(0, 50)
    mafia = mafia.replace(/[\`\'\"\+\-\!\\\[\]]/gi, '_')
    mafia = mafia.replace(/alert/g, '_')
    eval(mafia)

分析代码:

根据源码可以分析出,过滤了`, ', ",+,-,!,\,,并且过滤了弹窗函数alert,这样的一个正则,如果去绕过它呢?

首先我们必须知道,弹窗最常用的三个函数,为alert、prompt、confirm,三个函数都能实现弹窗,那么第一个绕过的payload简单的有些过分:

payload:prompt(1337);

payload:confirm(1337);

因为这里是作者编写的失误,所以导致绕过过于简单,实际上过滤了alert也会过滤掉其他弹窗函数 。所以上述解法不算做今天讲的重点。

解法一:构造函数

bash 复制代码
var add = new Function(
	'x',
	'y',
	'return x+y'
);

等同于:

bash 复制代码
function add(x,y){
	return x+y;
}

如何执行:

Function()()

因为JavaScript是严格区分大小写的,所以我们可以将大写的ALERT转为小写然后执行:

Function(/ALERT(1337)/.source.toLowerCase())()

代码执行成功!

解法二:使用eval函数绕过限制

这里用到了js中的一个函数:

parseInt(*string*, *radix*): 解析一个字符串并返回指定基数的十进制整数, radix 是2-36之间的整数,表示被解析字符串的基数。

  • string

    要被解析的值。如果参数不是一个字符串,则将其转换为字符串(使用 ToString抽象操作)。字符串开头的空白符将会被忽略。

  • radix 可选

    从 2 到 36,表示字符串的基数。例如指定 16 表示被解析值是十六进制数。请注意,10不是默认值!

示例:

parseInt('123', 5) // 将'123'看作5进制数,返回十进制数38 => 1*5^2 + 2*5^1 + 3*5^0 = 38

所以我们可以将alert先用三十进制转换为数字,然后再转回为字符串,

至于为什么是三十进制:0-9占十位,a-t占二十位,如果小于三十进制的话,当它从数字转回为字符串时,字符会丢失(例如:asert用29进制转换为数字,然后再转回为字符串时会变为aser,少了一个t),转回字符串的原因:数字无法运行。

所以我们这里得用三十进制:

parseInt('alert', 30)

结果为数字8680439也就是说我们利用parseInt函数将关键字变为一串数字,但数字肯定无法运行,我们还需要再变回去,要将一个数字转换为特定的 radix 中的字符串字段,要使用 thatNumber.toString(radix)函数。

8680439..toString(30) === alert

注意:转为tostring方法中间为..

所以最终的payload为:

javascript 复制代码
eval(8680439..toString(30))(1337)

代码执行成功!

解法三:利用location中的hash来绕过关键字

先来学习一下URL的组成:

javascript 复制代码
var url = document.createElement('a');
url.href = 'https://developer.mozilla.org/en-US/search?q=URL#search-results-close-container';
console.log(url.href);      // https://developer.mozilla.org/en-US/search?q=URL#search-results-close-container
console.log(url.protocol);  // https:
console.log(url.host);      // developer.mozilla.org
console.log(url.hostname);  // developer.mozilla.org
console.log(url.port);      // (blank - https assumes port 443)
console.log(url.pathname);  // /en-US/search
console.log(url.search);    // ?q=URL
console.log(url.hash);      // #search-results-close-container
console.log(url.origin);    // https://developer.mozilla.org

我们可以看到location.hash是取url中#后面的部分 ,而#后面的部分不会算作get传参的内容,所以我们可以将代码写在location.hash的位置,然后用eval函数来执行。

注意:location.hash第一个位置是#,所以我们还得使用一个slice函数来进行切割:

slice(index),index为索引

所以最终的payload为:

javascript 复制代码
eval(location.hash.slice(1))#alert(1337)

代码执行成功!

相关推荐
web打印社区6 分钟前
Windows 网页静默打印设置步骤:客户端、防火墙与联调清单
开发语言·前端·javascript·chrome·pdf·ecmascript
恋猫de小郭13 分钟前
KMP 又改了编译流程, Separate Compilation 禁止了 `commonMain` 的依赖穿透
android·前端·flutter
吴声子夜歌15 分钟前
Nginx应用与运维——Nginx Web服务应用实战(静态文件服务器的搭建)
运维·前端·nginx
y = xⁿ32 分钟前
关于Agent工程落地
前端·人工智能·python
web打印社区1 小时前
JS 静默打印怎么做:纯前端为什么不行,以及最小可跑通写法
开发语言·前端·javascript·websocket·网络协议·http·pdf
web打印社区1 小时前
HTML5 静默打印:前端页面怎么调用打印机且尽量不弹窗
前端·javascript·vue.js·pdf·html·html5
Python大数据分析1 小时前
开源免费、AI 驱动的 Web 打印设计器 OpenPrint:从拖拽设计到 ERP 对接全流程实战
前端·人工智能·开源
溪语流沙1 小时前
【每天一个CSS | Day11】赛博朋克故障风文字:红青分离 + 切片抖动
前端·css
liangshanbo12152 小时前
React Fiber:从“解决卡顿”到完整更新链路
前端·javascript·react.js
cindershade2 小时前
登录态不是一枚令牌,而是一条可撤销的生命线
xss