UltraRAG — 默认管理员凭证 + 知识库默认公开 + 会话不随改密失效
本报告记录了在 main 分支(审计时最新)发现的多个高危/严重漏洞,均已对照当前源码核实。最严重的是 CRITICAL 级默认管理员凭证:系统用硬编码弱密码 12345678 自动置备 admin 账户,无强制改密、无启动校验。
漏洞 1 — [CRITICAL] 默认管理员凭证从不强制更改
位置: ui/backend/auth.py:15, 339-359 (_ensure_default_admin_user)
ADMIN_DEFAULT_PASSWORD = "12345678" # L15 硬编码弱密码
def _ensure_default_admin_user(self, conn):
...
generate_password_hash(ADMIN_DEFAULT_PASSWORD), # L359 用弱密码种子化 admin
系统初始化时自动置备 admin 账户(用户名 admin,密码 12345678)。无 must_change_password 标志、无首次登录强制改密、无启动时拒绝默认密码的校验。verify_credentials(L190-203)用 check_password_hash 校验,对默认密码直接通过。
影响: 任何知道公开默认密码的人获得完整管理员权限——管理所有知识库、查看/修改所有用户的模型设置(含 API keys via update_model_settings)、访问所有聊天会话。
复现:
curl -X POST "http://<host>/api/login" \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"12345678"}'
# verify_credentials → check_password_hash 通过 → 获 admin session。
修复: 首次启动强制设置管理员密码(环境变量或交互式提示);加 must_change_password 标志并在首次登录强制改密;启动时检测默认密码并拒绝启动/警告。
漏洞 2 — [HIGH] 未追踪知识库集合默认公开可见
位置: ui/backend/kb_visibility_store.py:148 (bootstrap_legacy_public)
bootstrap_legacy_public 为每个缺少可见性记录的集合创建 is_public = 1 的可见性记录。它由 app.py 的 _ensure_legacy_collection_visibility 调用,而后者在每次集合列表请求的 _filter_collections_by_acl 中被调用。upsert_default_private(创建私有记录)仅在 pipeline_name == 'milvus_index' AND index_mode == 'new' 的 _run_kb_background 中调用。
任何通过 'append' 模式、'overwrite' 模式、非 milvus_index 管道或任何外部路径创建的集合都没有可见性记录。第一个列出集合的用户触发 bootstrap_legacy_public,把所有这类集合标记为 PUBLIC(admin 拥有),对所有用户可搜索可见。业务规则"新集合默认私有(最小权限)"被破坏——系统默认公开。
影响: 用户 A 用 index_mode='append' 索引含敏感数据的 KB,集合无可见性记录。任意用户(攻击者)请求集合列表 → bootstrap_legacy_public 为 A 的集合创建 PUBLIC 记录 → 攻击者看到并可查询 A 的集合内容。所有用户获得 A 私有数据的永久访问。
复现:
- 用户 A 用 append 模式索引敏感 KB(集合无可见性记录)。
- 攻击者请求集合列表 →
bootstrap_legacy_public 把 A 的集合标记 PUBLIC。
- 攻击者搜索/查询 A 的集合内容。
修复: 默认私有(is_public=0);bootstrap_legacy_public 改为 bootstrap_legacy_private;新集合统一走 upsert_default_private。
漏洞 3 — [HIGH] 会话不随密码修改失效
位置: ui/backend/auth.py:229-257 (update_password)
update_password(L229)只更新数据库 password_hash(L257 generate_password_hash(new_password)),无任何机制使已存在的 Flask 会话失效。users 表无 password_changed_at 时间戳,session 无 token 版本信息。app.py 的 _get_authenticated_user_id() 只校验 session 中 auth_user_id 的格式(^[A-Za-z0-9_-]+$),不检查密码是否在 session 建立后被修改。
影响: 攻击者通过 XSS/中间人/共享设备窃取受害者 Flask session cookie。受害者发现异常后改密(update_password),但攻击者持有的旧 session cookie 仍有效——_get_authenticated_user_id() 仍返回受害者 user_id。受害者无法通过改密夺回账号控制权,攻击者访问权限实质永久。
复现:
- 攻击者窃取受害者 session cookie。
- 受害者改密(
/api/auth/password → update_password)。
password_hash 更新,但攻击者旧 cookie 仍有效。
- 攻击者持续保持认证状态。
修复: users 表加 password_changed_at;session 校验时对比 session 建立时间与 password_changed_at,改密后失效旧 session。
汇总
| # |
漏洞 |
严重度 |
位置 |
| 1 |
默认管理员凭证 12345678 |
CRITICAL |
auth.py:15, 339-359 |
| 2 |
知识库集合默认公开 |
HIGH |
kb_visibility_store.py:148 |
| 3 |
会话不随改密失效 |
HIGH |
auth.py:229-257 |
所有漏洞均已对照 main 分支源码核实。
UltraRAG — 默认管理员凭证 + 知识库默认公开 + 会话不随改密失效
本报告记录了在
main分支(审计时最新)发现的多个高危/严重漏洞,均已对照当前源码核实。最严重的是 CRITICAL 级默认管理员凭证:系统用硬编码弱密码12345678自动置备 admin 账户,无强制改密、无启动校验。漏洞 1 — [CRITICAL] 默认管理员凭证从不强制更改
位置:
ui/backend/auth.py:15, 339-359(_ensure_default_admin_user)系统初始化时自动置备
admin账户(用户名admin,密码12345678)。无must_change_password标志、无首次登录强制改密、无启动时拒绝默认密码的校验。verify_credentials(L190-203)用check_password_hash校验,对默认密码直接通过。影响: 任何知道公开默认密码的人获得完整管理员权限——管理所有知识库、查看/修改所有用户的模型设置(含 API keys via
update_model_settings)、访问所有聊天会话。复现:
修复: 首次启动强制设置管理员密码(环境变量或交互式提示);加
must_change_password标志并在首次登录强制改密;启动时检测默认密码并拒绝启动/警告。漏洞 2 — [HIGH] 未追踪知识库集合默认公开可见
位置:
ui/backend/kb_visibility_store.py:148(bootstrap_legacy_public)bootstrap_legacy_public为每个缺少可见性记录的集合创建is_public = 1的可见性记录。它由app.py的_ensure_legacy_collection_visibility调用,而后者在每次集合列表请求的_filter_collections_by_acl中被调用。upsert_default_private(创建私有记录)仅在pipeline_name == 'milvus_index' AND index_mode == 'new'的_run_kb_background中调用。任何通过 'append' 模式、'overwrite' 模式、非 milvus_index 管道或任何外部路径创建的集合都没有可见性记录。第一个列出集合的用户触发
bootstrap_legacy_public,把所有这类集合标记为 PUBLIC(admin 拥有),对所有用户可搜索可见。业务规则"新集合默认私有(最小权限)"被破坏——系统默认公开。影响: 用户 A 用
index_mode='append'索引含敏感数据的 KB,集合无可见性记录。任意用户(攻击者)请求集合列表 →bootstrap_legacy_public为 A 的集合创建 PUBLIC 记录 → 攻击者看到并可查询 A 的集合内容。所有用户获得 A 私有数据的永久访问。复现:
bootstrap_legacy_public把 A 的集合标记 PUBLIC。修复: 默认私有(
is_public=0);bootstrap_legacy_public改为bootstrap_legacy_private;新集合统一走upsert_default_private。漏洞 3 — [HIGH] 会话不随密码修改失效
位置:
ui/backend/auth.py:229-257(update_password)update_password(L229)只更新数据库password_hash(L257generate_password_hash(new_password)),无任何机制使已存在的 Flask 会话失效。users表无password_changed_at时间戳,session 无 token 版本信息。app.py的_get_authenticated_user_id()只校验 session 中auth_user_id的格式(^[A-Za-z0-9_-]+$),不检查密码是否在 session 建立后被修改。影响: 攻击者通过 XSS/中间人/共享设备窃取受害者 Flask session cookie。受害者发现异常后改密(
update_password),但攻击者持有的旧 session cookie 仍有效——_get_authenticated_user_id()仍返回受害者 user_id。受害者无法通过改密夺回账号控制权,攻击者访问权限实质永久。复现:
/api/auth/password→update_password)。password_hash更新,但攻击者旧 cookie 仍有效。修复:
users表加password_changed_at;session 校验时对比 session 建立时间与password_changed_at,改密后失效旧 session。汇总
12345678auth.py:15, 339-359kb_visibility_store.py:148auth.py:229-257所有漏洞均已对照
main分支源码核实。