文章总结: 本文公开了一个Edge浏览器XSS过滤器绕过漏洞的完整技术细节。作者利用IE时代将location对象作为函数调用的老技巧,结合ES6计算属性特性,将tostring和valueof等关键字拆解为表达式,成功绕过Edge过滤器的正则检测。文章分析了过滤器正则的缺陷,指出基于黑名单正则的过滤方式存在根本性局限,建议采用输出编码和CSP作为更有效的防御方案,并分享了漏洞挖掘经验。 综合评分: 85 文章分类: web安全,漏洞分析,渗透测试,红队
Edge XSS 过滤器:一个至今没修的绕过
原创
升斗安全XiuXiu 升斗安全XiuXiu
升斗安全
2026年9月11日 07:58 广东
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
【文章说明】
- 目的:本文内容仅为网络安全技术研究与教育目的而创作。
- 红线:严禁将本文知识用于任何未授权的非法活动。使用者必须遵守《网络安全法》等相关法律。
- 责任:任何对本文技术的滥用所引发的后果自负,与本公众号及作者无关。
- 免责:内容仅供参考,作者不对其准确性、完整性作任何担保。
阅读即代表您同意以上条款。
📌 这篇讲什么:我之前给微软报过一个 Edge 的问题,一直没等到修复。等够了,干脆把细节写出来。文章会完整走一遍这条链路,一个 IE 时代的老怪癖,怎么在 Edge 上借尸还魂,又是怎么用 ES6 的计算属性把 XSS 过滤器绕过去的。适合挖洞的人、写过滤规则的人,以及所有爱看过滤器被打脸的人。
一、报给微软的那个洞,我等不下去了
先交代个背景。
这个 Edge 的问题,我早就报给微软了,到今天也没修。
报洞这事儿最磨人的,从来不是”挖”,是”等”。挖的时候你是猎手,等的时候像在窗口排队办证。等了这么久,我决定不再等了——细节公开,大家一起看。
我对”老洞公开”一直有个朴素看法:厂商不修,攻击者迟早也会摸到,那还不如先把防守方叫醒。毕竟挨打的是用户,不是厂商。
二、IE 的老毛病:把 location 当函数使 🔍
故事得从 IE 讲起。
IE 有个相当离谱的缺陷:你可以把 location 对象当成函数来调,再配上对象字面量里的 toString / valueOf,就能把代码跑起来。据我所知最早是 Sirdarckcat 捅出来的,要是我记错了,评论区尽管锤我。
payload 长这样:
-{toString:[].join,length:1,0:'javascript:alert(123)',valueOf:location}
一堆符号,第一眼看像猫踩了键盘。我们一句句拆。
最外层那个 – 是一元减号,它的作用是逼着 JS 引擎把这个对象转成数字。转数字之前得先转成原始值,于是引擎按顺序去对象身上找 valueOf。而我们把 valueOf 指向了 location——在老引擎里,location 是个可调用的宿主对象,于是”跳转”这个动作,是引擎自己规规矩矩触发的。
那它跳去哪儿?地址来自我们伪造的 toString。
我们把它指向了 Array.prototype.join,同时给对象配了 length: 1 和 0: ‘javascript:alert(123)’,让它伪装成一个只有一个元素的数组。join 一跑,就顺着 length 和下标 0,把那串 javascript:alert(123) 拼了出来。
说白了:我们造了个假数组,让join帮我们拼字符串,再让location帮我们执行。
整条链子上,没有任何一个字是我们直接塞给引擎去执行的,全是引擎照着自己的规矩走出来的。这就是这类技巧最好看的地方——你不是在硬闯,你是在请它自己开门。
(不同引擎、不同版本在取值顺序的细节上略有出入,但结果一致,感兴趣可以自己抓一下。)
三、好消息和坏消息 💥
好消息:这串 payload 在最新的 Edge 上依然好使。
坏消息:IE 和 Edge 的 XSS 过滤器,都认识它。
我扒出来的过滤器正则(简化版):
[”'`].?[{,].(valueOf|toString).*?:}
翻译成人话,它在找这么一串东西:
- 先看到一个引号,单引号、双引号、反引号都算;
- 后面跟零到任意一个字符;
- 出现{或者 ,;
- 紧接着出现 valueOf或 toString(中间最多隔一个字符);
- 再往后,找到冒号。
- 命中之后,Edge 会动手”消毒”:把 valueOf 里的 a、toString 里的 o换成 #。
payload 当场变成一坨废字符,弹窗自然也没了。到这儿,事情看起来黄了。
但我想说一句:黑名单正则最尴尬的地方在于,它是在猜”攻击者长什么样”。你猜得再准,也只是猜中了昨天那一个攻击者。
四、Edge 的新武器,也是它的新裂缝 🧩
Edge 和 IE 有个本质区别:它支持 ES6。
新语法当然是好事,但好事往往就是新的攻击面。这次帮上忙的(对我们来说),是 ES6 的计算属性(computed property names)。
它允许你用一个表达式,去算出属性名:
x = 'a'; o = {[x]: 123}; alert(o.a) // 123
看到方括号里那个 [x] 了吗?属性名不再是写死的字符串,而是运行时算出来的。
看到这儿,你应该已经有想法了。
五、合体:让正则一条都命中不了 ⚔️
过滤器要抓的是源码里的 toString 和 valueOf 这两个字面量。
而计算属性,正好能把字面量藏进表达式里。
两个技术一拼,Edge 的过滤器就成了睁眼瞎:
x='g',y='f', {['toStrin'+x]:[].join,length:1,0:'java\script:alert\x28123\x29',['valueO'+y]:location}-'';
每一处手脚,逐个说:
-
['toStrin'+x]——
x是g,拼出来就是toString。但源码里压根没出现 “toString” 这七个字母连在一起的样子,正则第一条就瞎了。 -
['valueO'+y]——
y是f,拼出来是valueOf。同理,字面量检测落空。 -
'java\script:...'—— 字符串里的
\s会被 JS 引擎当成普通的s吃掉,运行时它就是javascript:。可过滤器读的是源码,它看到的是java\script:,对javascript:的检测直接穿过。 -
alert\x28123\x29——
\x28\x29就是左右括号。还是那句:引擎懂,正则不懂。 -
末尾的
-''—— 负责把整个对象推去走”转原始值”的流程。扳机一扣,链子自己跑起来。
结果就是:五条规则一条没命中,payload 在 Edge 上照常执行。
六、挖洞的人,能从这儿带走什么 🧠
写点经验分享,也是我这些年反复验证过的几条:
-
新语法就是新绕过面。每一代语言特性落地,第一个受益的往往是攻击者。计算属性、模板字符串、可选链、装饰器……它们改变的都是”源码长什么样”。改一次,旧的黑名单就得重考一次。
-
过滤器读的是源码,引擎读的是语义。只要这两者之间存在缝隙,绕过就是必然,只是时间问题。所以我一直认为,靠正则挡 XSS 是条死路,输出编码加 CSP 才是正解——这话我在好几个项目复盘里说过,都要说腻了。
-
报洞要有耐心,也要有底牌。厂商不修是常态,别指望一封邮件改变世界。等够了就公开,把知识还给社区,至少能让防守方和攻击方站在同一条起跑线上。
-
老 payload 别扔。这次我干的,说白了就是把一个 IE 时代的老技巧,搬到支持 ES6 的新引擎上重新拼了一遍。你笔记里那些”过气”的存货,换个环境可能就是新的。
最后送一句我常挂在嘴边的:绕过过滤器这件事,拼的从来不是谁更聪明,而是谁更会换个姿势说同一句话。
七、几句说明 ⚠️
技术内容仅供安全研究和授权测试,别拿去干不该干的事。文中涉及的浏览器版本特性属于历史问题,现在复现环境未必好找,理解思路比背 payload 重要。
写到这里,照例求个三连。
这篇从翻旧笔记到写完,花了我一整个晚上。如果它让你想起了某个在收藏夹里吃灰的 payload,或者让你下次写过滤规则时多犹豫三秒,那这几个小时就没白花。
- 觉得有用,帮我点个「赞」和「在看」,让更多挖洞的朋友刷到;
- 顺手「转发」给群里那几个天天跟 WAF 较劲的兄弟,他们大概率用得上;
- 还没「关注」的朋友点个关注,压箱底的绕过笔记我会陆续整理发出来,只发在这里;
- 也欢迎「推荐」给身边做安全、做开发的朋友,一起少写点会被打脸的正则。
渗透测试 #XSS #Edge #赏金猎人 #Web安全 #漏洞挖掘 #经验分享 #WAF绕过 #浏览器安全
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:升斗安全 升斗安全XiuXiu 升斗安全XiuXiu《Edge XSS 过滤器:一个至今没修的绕过》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论