ssti学习
常见自带魔术变量
__dict__
用于显示出实例的属性
是类
或实例
自身的 命名空间字典,存储该类或实例 直接定义的所有属性和方法。对于类对象:
包含类层级上的所有 属性、方法、元类、继承关系 等。对于实例对象:
包含实例层级上的所有 动态添加的属性(不包括类定义的属性和方法)。比如:
1
print(().__class__.__bases__[0].__subclasses__()[94].__dict__)
这里将原型
__subclasses__()[94]
所有的属性以字典形式列出举个例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class Person:
species = "human" # 类变量
def __init__(self, name):
self.name = name # 实例变量
def greet(self):
return f"Hello, {self.name}"
print(Person.__dict__) # 输出示例如下:
# {
# 'species': 'human',
# '__init__': <function Person.__init__>,
# 'greet': <function Person.greet>, 即前面的Person为该类的名字,greet为该类中的一个函数
# ...
# }
# 注意:实例变量(如 name)不在此字典中,属于实例的 __dict__
__init__.__globals__["builtins"]
它是一个字典,包含了 整个 Python 模块运行时的所有全局变量和导入的模块。
以下是一段帮助我们辨析理解的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import os
global_var = "I'm a global variable"
class MyClass:
class_attr = "I'm a class attribute"
def __init__(self, instance_attr):
self.instance_attr = instance_attr
def method(self):
pass
_class = MyClass("Hello, world!")
# 查看类的__dict__
print(MyClass.__dict__) # 输出类本身的定义内容
print("\n")
print(_class.__dict__) # 输出实例的__dict__(只会包含实例属性)
print("\n")
print(MyClass.__init__.__globals__)
print("\n")
print(MyClass.__init__.__globals__["__builtins__"])这里的
print(MyClass.__init__.__globals__)
的结果为:1
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002660053BC50>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'i:\\.python小脚本\\web\\ssti\\test.py', '__cached__': None, 'MyClass': <class '__main__.MyClass'>, '_class': <__main__.MyClass object at 0x0000026600738A40>}
即为该python模块,通俗来说就是这个python代码文件的所有导入模块以及变量等属性。
关于__globals__["__builtins__"]
输出结果的解释
- 个人最为疑惑的就是为什么有时对该类的
__init__.__globals__["__builtins__"]
进行打印只会回显:<module 'builtins' (built-in)>
,因为此时该类中对__builtins__
模块的引用属于直接引用,并没有呈字典形式在类中引用。
而有些python自带类则以字典形式对__builtins__
模块中的方法进行引用,所以打印该键所代表值可以得到大量键值对数据。
杂项疑点
关于寻找eval
函数以及寻找popen
的区别
- 为什么寻找前者需要在子类的
__subclasses__()[i].__init__.__globlas__['__builtins__']
中寻找,后者只需在:
__subclasses__()[i].__init__.__globlas__
中寻找? - 原因在于,
eval
为python自带模块中的方法,所以需要再在每个类自动引入的[__builtins__]
模块中寻找,而popen
方法并不属于__builtins__
类,所以不需要在该模块中寻找,直接在全局变量中寻找。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Dedsec的博客!