原型链污染
原型链污染(原型链属性改变)
Python原型链污染
去找了一下原理,有如下特征
- 方法的层级调用(和ssti相似
- 父类与子类
一些方法
waf有对
_.的过滤转义
__init__\\\\.__globals____init__是访问对象初始化方法__globals__则是访问全局命名空间。双反斜杠
\\\\:- 双反斜杠是用来转义反斜杠的。
- 在字符串中,
\\\\实际代表一个单一的反斜杠\
{"key":"__class__\\\\.__init__\\\\.__globals__\\\\.app.router.name_index.__mp_main__\\.static.handler.keywords.file_or_directory","value": "/"}1
2
3
4
5
6
7
8
9
10
3.
### python的一些语句碎片
```python
if key and value and type(key) is str and '_.' not in key:
pollute = Pollute()
pydash.set_(pollute, key, value)
return text("success")
确保key和value存在,
且key是一个字符串且不包含_和.的组合,
然后使用pydash.set_方法在pollute对象中设置属性
pydash.set_
set_ 方法用于在对象中设置或添加属性,支持使用点表示法的路径
1 | import pydash |
1 | class Pollute: |
__init__方法当前没有实现任何初始化逻辑。
在Python中,__init__方法是类的构造函数,用于在实例化对象时初始化对象的属性。它通常接受self参数,代表类的实例。
Javascript的原型链污染
原型==样机
原型链:实例可以通过原型链访问原型对象中的属性和方法。如果实例需要访问的属性或方法在自身上找不到,它就会沿着原型链向上查找父类,直到找到为止。
去了解了一下Javascript的原型链污染https://juejin.cn/post/7201668416170901563
const user = JSON.parse('{"__proto__": {"isAdmin": true}}');
- 导致
user对象继承isAdmin属性,即使这个属性在原始数据中不存在。 __proto__在JavaScript中,__proto__属性允许你访问或修改对象的原型。通过传递包含__proto__的JSON字符串,你可以操纵创建对象的原型链。
解决方法:
使用安全库:使用设计用来安全处理JSON解析的库,这些库可以检测并防止原型污染。
1 | const safeParse = require('secure-json-parse'); |
原理:
在 JavaScript 中,每个对象都有一个
__proto__属性,它指向该对象的原型。person1.__proto__ === Person.prototype
person1对象
Person函数
prototype对象所特有的属性,实例没有
操作: JSON.parse('{"__proto__": {"isAdmin": true}}'),其他见Javascript的原型链污染相关函数解析
目的:修改对象的属性
Javascript的原型链污染相关函数解析
call Animal.call(this, name)
this绑定到当前的Dog实例。name是传递给Animal构造函数的参数。
通过这种方式,Animal构造函数中的this.name = name将会把name属性赋值给当前的Dog实例,从而实现继承父类属性的目的。
Dog.prototype = Object.create(Animal.prototype);
Object.create(proto, [propertiesObject])
proto: 要作为新对象原型的对象。
propertiesObject(可选): 该对象的可枚举(可选)属性将被作为新对象的自身属性。
Object.create 是 JavaScript 中用于创建一个新对象的方法,新对象的原型是一个指定的对象
Dog.prototype.constructor = Dog;
将Dog的构造函数指回Dog,确保constructor属性正确指向。
Object.prototype.toString = function(){……}
修改所有对象的 toString 方法
Object.setPrototypeOf(normalObj, maliciousObj);
使用 Object.setPrototypeOf 方法将 normalObj 的原型设置为 maliciousObj
merge 函数:
Lodash 库的 _.merge 方法来合并对象。Lodash 是一个流行的 JavaScript 工具库,提供了许多有用的函数来处理数组、对象、字符串等。
当使用 merge 函数合并两个对象时,如果这两个对象都有相同的属性,那么 merge 函数会将目标对象中的属性值替换为源对象中的属性值。然而,如果这些属性的值是对象或者数组,那么 merge 函数并不会复制它们的值,而是将它们的引用复制给了目标对象。这样,如果修改目标对象中的这些属性,那么源对象中的这些属性也会被修改,进而污染了原型链。
浅拷贝: 这个 merge 函数实现的是浅拷贝,只会复制 source 对象的第一层属性。如果属性的值是对象,则只会复制对象的引用,而不会递归合并对象的嵌套属性。
1 | // 修改全局变量中的属性 |
_.merge 用于递归合并两个或多个对象的属性。它会修改第一个对象并返回该对象。对于同名属性,如果它们的值是对象,那么会递归地合并它们;否则后面的值会覆盖前面的值。
Lodash
安装 Lodash,通过 npm 安装:
1 | npm install lodash |
然后在代码中引入:
1 | const _ = require('lodash'); |
Object.assign({}, source)
复制source对象的原型对象中的属性和方法
Object.create(proto, [propertiesObject])
eval()函数:
eval()函数是一个全局函数,它将传入的字符串作为 JavaScript 代码进行解析和执行。具有执行任意代码的能力.
1 | // 使用 eval 函数创建一个函数并在其中访问全局变量 |
1 | var code = "this.__proto__.myProperty = 'Hello World';"; // 向原型对象添加属性 |
object.hasOwnProperty(property)
object: 要检查的对象。
property: 要检查的属性名,必须是字符串类型。
hasOwnProperty 是 JavaScript 对象的一个方法,用于检查对象是否具有某个属性作为其自身的属性(而不是从原型链继承的属性)。
merge({}, JSON.parse('{"__proto__": {"isAdmin": true}}'));
{}空对象。source 对象包含 __proto__ 属性,并且没有进行安全检查,合并操作会导致整个原型链被污染。最终,这种污染会影响到所有新创建的对象,使它们都包含 isAdmin 属性。
JavaScript中可以触发弹窗的函数
alert()函数可以在浏览器中弹出一个警告框,用于向用户显示一条消息。
alert('Hello, world!');
confirm()函数可以在浏览器中弹出一个确认框,用于向用户显示一条消息并询问用户是否继续操作。
1 | if (confirm('Are you sure you want to delete this item?')) { |
prompt()函数可以在浏览器中弹出一个对话框,用于向用户显示一条消息并询问用户输入内容。
1 | let name = prompt('What is your name?'); |