检测敏感方法需三重验证:确认真实来源位置、检查是否被篡改或代理拦截、验证原型链完整性与防污染机制,单靠存在性判断易漏风险。

检测对象原型链是否包含敏感方法,关键不是“找得到”,而是“是否真能被安全调用”——因为原型链上存在方法 ≠ 该方法未被篡改、未被代理拦截、未被污染。重点在于验证方法的来源、完整性与行为一致性。
确认敏感方法的真实来源位置
敏感方法(如 toString、valueOf、toJSON、inspect 等)常被用于序列化、调试或权限校验,一旦被覆盖或劫持,可能泄露信息或绕过检查。先定位它到底来自哪一层:
- 用 Object.getPrototypeOf(obj) 逐层向上查,配合 hasOwnProperty 检查该方法是否定义在当前原型对象上
- 避免依赖 obj.toString 直接取值——它可能是被重写的,应使用 Object.prototype.toString.call(obj) 获取原始类型标签作为基准
- 对每个原型节点,执行 proto.hasOwnProperty('toString'),若为 true,说明该方法是显式定义在此层,需重点审查
检查方法是否被篡改或代理拦截
即使方法存在于原型链上,也可能已被 Proxy 拦截、被 Object.defineProperty 重定义、或被赋值为恶意函数:
- 用 Object.getOwnPropertyDescriptor(proto, 'toString') 查看其 value、get、writable 和 configurable 属性;若 get 存在或 value 是非原生函数(如 toString.toString() !== Function.prototype.toString.toString()),即存疑
- 尝试用 Reflect.get(proto, 'toString', proto) 和直接访问 proto.toString 对比结果,不一致说明有拦截逻辑
- 对疑似被代理的原型,可测试 typeof proto === 'object' && !!proto.constructor && !!(proto.constructor + '').includes('Proxy')(非绝对,但可作初筛)
验证原型链完整性与防污染机制
原型污染会把敏感方法注入到顶层(如 Object.prototype),导致所有普通对象意外继承危险行为:
- 检查 Object.prototype.toString 是否仍为原生函数:Object.prototype.toString === {}.toString —— 若为 false,说明已被污染
- 遍历原型链至 null,记录每层的 constructor.name 和 Object.prototype.isPrototypeOf(proto) 结果;若某层 proto.constructor === undefined 或 proto === Object.create(null),则后续链断裂,无法继承标准敏感方法
- 对高风险上下文(如沙箱、插件系统),可用 Object.freeze(Object.prototype) 提前锁定,再用 Object.isFrozen(Object.prototype) 验证是否生效
不复杂但容易忽略:敏感方法的存在性检测必须结合“来源可信度 + 行为真实性 + 链路完整性”三重验证,单靠 in 或 typeof obj.toString === 'function' 会漏掉绝大多数真实风险。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











