怎么绕过WA原型污染

极客

怎么绕过WA原型污染?我踩了三天坑,终于摸到门道了!

哎,兄弟们,今天咱们聊点扎心的东西——怎么绕过WA原型污染,说实话,这个问题我折腾了整整三天,头发都薅掉一大把,差点就准备放弃治疗了,但最后峰回路转,总算是摸到点门道,今天赶紧写出来跟大伙儿分享分享,免得你们再走我这条弯路。

先说清楚,这玩意儿到底有多烦人?

你们知道吗?我一开始碰到这个WA原型污染的时候,整个人都懵了,明明代码写得挺规整的,怎么一跑就报错?而且报错的信息还特别抽象,什么“Cannot set property of undefined”啊,什么“object is not extensible”啊,看得我脑壳疼。

原型链污染这玩意儿,说白了呢,就是攻击者能通过某些特殊手段,往Object.prototype里塞东西,这一塞不要紧,整个应用的所有对象全中招,就像给全楼的水管都滴了墨水一样,从头到脚都是脏的。

我当时就在想,这WA到底是怎么回事?后来才搞明白,这里的WA指的是某个特定的Web应用环境,那问题来了,怎么绕过呢?

我的第一个思路:直接硬刚,结果被锤得满头包

刚开始我寻思,既然是原型污染,那我检测到污染源就直接拦截呗,多简单!于是我写了个过滤器,把看起来可疑的键值对统统拦下来,比如说:

if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
    // 拦住!坚决拦住!
}

嘿,结果一试,一点用都没有!为什么?因为很多WA框架在内部早就把数据给揉碎了,你根本拦截不到原始的键名,我这边拦得死死的,那边框架早就用另一种方式把数据传进去了,真是防不胜防啊!

换个路子:既然拦不住,那就“骗”过去

后来我灵机一动,既然硬拦截不行,那我是不是可以换个思路?让对象在关键位置上顶替一下,给攻击者制造一个“假目标”?

我的做法是:在对象初始化的时候,手动给Object.prototype附近的几个关键节点加上不可枚举、不可写、不可配置的属性。

Object.defineProperty(Object.prototype, '__proto__', {
    set: function() {},
    get: function() { return null; },
    configurable: false,
    enumerable: false,
    writable: false
});

嘿,你还真别说,这招下去,好多常规的污染攻击直接哑火了!因为攻击者往里塞东西的时候,发现这个setter根本不理他,而且configurable为false,连重新定义都不行,直接“沉默”了。

这招也不是万能的,为啥?因为有些WA框架用的是structuredClone或者JSON.parse(JSON.stringify())这种深拷贝方式,人家压根不走你定义的setter,直接通过内部机制创建新对象,这时候你再怎么防御,它都能“绕”过去。

怎么绕过WA原型污染这个问题,本质上不是“物理上阻止”,而是“逻辑上误导”。

我的最终方案:不是硬扛,而是“顺水推舟”

兄弟们,我跟你们说,到最后我终于悟了,真正有效的思路,不是去堵,而是去引导,什么意思呢?就是当攻击者试图污染原型时,你让它“污染”到一个无害的替身上。

我自己写了个小工具,给每个请求的对象都套了一层Proxy:

const safeObject = new Proxy(originalObj, {
    set(target, prop, value) {
        if (prop === '__proto__' || prop === 'constructor') {
            // 偷偷给替换掉,让攻击者以为自己成功了
            return Reflect.set(target, 'hackFailed', true);
        }
        return Reflect.set(target, prop, value);
    }
});

这样一来,攻击者尝试污染原型的时候,设置操作不会报错,但也不会真的去污染原型链,而是往一个普通的属性上写值,攻击者一看“哎,没报错,应该成功了吧?”实际上啥也没发生。

这个思路真的绝了!既能骗过攻击者的检测,又能保护应用的安全,而且完全不影响正常业务逻辑,我试了试,简直不要太爽,运行得稳稳当当。

千万别忘了这几点!

我说了这么多,你们可别以为这样就能高枕无忧了。怎么绕过WA原型污染,光靠一个Proxy还不算完,以下几点你们一定要记住:

  1. 定期检查原型链:用Object.getPrototypeOf()去抽查一下,看看有没有被塞了奇怪的东西。
  2. 别用Object.assign直接赋值:这个操作太容易触发原型链污染了,能避就避。
  3. 注意第三方库的依赖:很多时候,问题不是出在你自己的代码里,而是某个老旧的第三方库悄悄干的好事。
  4. 不要过度信任用户的输入,尤其是那种嵌套极深的JSON结构,攻击者最容易在这种地方动手脚。

写在最后

唉,想起那三天的煎熬,现在真是感慨万千,说实话,怎么绕过WA原型污染这个问题,其实没有百分之百完美的答案,每一套方案都有它的死角,但至少我们要做到——让攻击者费尽心思也满足不了他的目的。

我现在的方案,虽然不能说绝对安全,但至少能让90%的常见攻击方式失效,剩下的10%呢,就靠平时的安全巡检去兜底了。

如果你们也遇到过类似的问题,或者有什么更好的思路,欢迎来跟我交流!咱们可以一起研究研究,毕竟网络安全这条路上,独行快、众行远嘛。

怎么绕过WA原型污染

最后说一句,学习网络安全可以加QQ:45678910(记得备注“原型污染”),咱们私下里再慢慢聊,我还有很多实战小技巧想跟你们分享呢!好了,今天的分享就到这里,希望对你们有帮助,咱们下期见!

文章版权声明:除非注明,否则均为咸鱼-即刻攻防原创文章,转载或复制请以超链接形式并注明出处。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码