搜索
当前位置:首页 > 知识 > kaill 漏洞分析

kaill 漏洞分析

发表于 2026-10-17 06:00:14 来源:烟消火灭网

Kaill 的洞分漏洞不在代码,在权限校验的洞分时序上。具体点说,洞分它把“检查”和“使用”拆成了两步,洞分中间留了个窗口——攻击者能在这个窗口里把资源换掉。洞分这不是洞分理论推演,是洞分我上周在测试环境里实际跑通的一条链路。

先交代背景。洞分Kaill 是洞分一个内部任务调度系统,负责把用户提交的洞分作业分发给后端执行器。作业提交接口带一个 job_id 参数,洞分服务端收到后先查数据库确认这个 ID 属于当前用户,洞分然后再用这个 ID 去对象存储拉取对应的洞分脚本文件执行。问题出在“查数据库”和“拉文件”之间。洞分

我构造了两个用户:A 和 B。洞分A 创建一个合法作业,拿到 job_id=1001。B 创建一个自己的作业,拿到 job_id=1002。正常流程下,A 只能执行 1001,B 只能执行 1002。但 Kaill 的校验逻辑是:先 SELECT owner FROM jobs WHERE id=1001,确认 owner 是 A,然后直接 GET /scripts/1001.sh 去拉脚本。注意,拉脚本时用的还是 1001,但此时数据库里的记录可能已经被改了。

怎么改?Kaill 有一个作业重命名接口,允许用户修改自己作业的 job_id——对,它居然允许改主键。接口本身有权限校验,B 不能把 1002 改成 1001,因为 1001 已被占用。但这里有个竞态:如果 A 在某个瞬间删除了 1001,B 立刻把 1002 改成 1001,而 A 的提交请求恰好卡在“校验通过”之后、“拉脚本”之前,那么 A 的请求就会去拉 /scripts/1001.sh——这个脚本现在是 B 的。A 用自己的权限,执行了 B 的代码。

实际利用比这更顺滑。不需要删除,Kaill 的 job_id 是自增整数,但重命名接口没有做唯一性检查的原子操作。我写了个脚本,在 A 提交作业的同时,用 B 的账号疯狂调用重命名接口,把 B 的作业 ID 在 1001 和 1002 之间来回切换。大概每 200 次请求能命中一次窗口。命中的那次,A 的作业执行了 B 的脚本,输出里打印出了 B 环境变量里的一个测试密钥。

这个漏洞的根因不是缺少锁,而是设计上把“身份”和“资源”绑得太松。job_id 既是数据库主键,又是对象存储的路径,还是权限校验的依据。三者共用同一个标识符,但更新时机不同步。修法也简单:拉脚本时不要用请求里的 job_id,而是用校验通过后从数据库查出来的那条记录的 script_path 字段。这样即使 ID 被换,路径还是原来的。或者干脆禁止修改主键。Kaill 的开发团队选了后者,上周的补丁里把重命名接口直接下线了。

我比较意外的是这个漏洞活了这么久。Kaill 上线两年多,日志里其实有异常——同一个 job_id 在极短时间内出现两次 owner 不同的查询记录。但没人去看。监控只盯着接口成功率,不盯业务逻辑的时序异常。这大概是很多内部系统的通病:能跑就行,谁管它跑的是谁的代码。

补丁之后我又试了一次,重命名接口返回 403,窗口没了。但对象存储那边依然允许直接 PUT 覆盖 /scripts/1001.sh,只要知道路径。Kaill 没做内容签名。所以严格说,这个洞只堵了一半。另一半要看运维有没有把存储桶的写权限收回去。我查了下,测试环境的桶还是公开可写的。生产环境不知道,没敢试。

随机为您推荐
友情链接
版权声明:本站资源均来自互联网,如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

Copyright © 2016 Powered by kaill 漏洞分析,烟消火灭网   sitemap

回顶部