Allureluoli 二月FEBRUARY

NESTCTF 2026 SSCP:空口令、诊断导出与尚未完成的摄像头转向

SSCP 这道题没有停在“所有入口都需要认证”。后续已经从媒体服务的空口令行拿到诊断包,登录只读控制台,并看到实时画面;但没有取得最终白板内容或完整 flag。跨到 11 月 1 日凌晨,状态文件还记录了一次 PTZ 认证突破,下面单独补记。

四个入口要分开看

服务 认证或用途
sscp-console/1.1 控制台登录、只读画面
dsapi/1.0 JSON 设备配置,X-Session
sscpd/1.0 SSCP 控制,/sscp/device_service
vhttpd/1.0 私有媒体,SHA-256 Digest,realm=TPC260

比赛把不同内网端口映射成多个域名。不能因为一个入口用同一端口号,就认定其认证逻辑也相同。

从空口令行进入媒体服务

hub_primary_2 配合空密码通过 vhttpd 的 Digest 认证。根路径给出 preview、stream.mjpg、playback、diagnostic 和 firmware/download 等端点。

这里的“空密码”仍然需要按照 Digest 协议计算 response,不是省略 Authorization 头。

诊断包给出了只读账号

/diagnostic 导出的 ZIP 里有 config.json,包含 viewer 账号的明文密码、camera_acc 用户名、第二管理身份及初始 pan/tilt。

用 viewer 登录 console 成功,还能登录 dsapi,但权限有限:console 的 PTZ move 返回 403,dsapi 只允许部分方法。账号能登录,并不代表能操纵摄像头。

抓到的画面是 OFFICE 门,初始位置 P=-150、T=10。/preview?pan=... 并没有改变机位,只改变查询参数不能绕过控制接口。

固件能解释算法,不能直接代表线上密钥

固件包是 VSCPFW 容器,解出 ARM32 静态二进制 vscpd。反编译与 qemu 实测确认,UsernameToken 的核心涉及:

1
Base64_NOPAD(SHA1(decoded_nonce || Created前缀 || 固件中的常量))

固件中的 cfg_account_password 字符串参与计算。本地用相应 digest 可以得到 AUTH_OK,改环境变量不影响结果;但线上不接受同一常量。

这份附件标识为 dev/local 构建。准确结论是“本地算法与线上认证尚未对齐”,而不是“线上密码一定藏在进程环境”或“出题人一定漏发口令”。后两种说法没有足够证据。

Base64 填充是一次实际踩坑

早期字典测试使用了带 = 的 28 字符 digest,后来根据固件编码器改为无填充的 27 字符。格式不同,旧批次的失败就不能用来排除相同密码在正确格式下有效。

修正后的 top10k 仍未命中,接着才运行设备定向字典。此前“已经尝试两万次”的数量本身没有意义,先确认协议字节才有意义。

跨日补记:00:09 的认证突破

SSCP_LOOT.md 末尾有 2026-11-01 00:09 的更新,部分中文存在编码损坏,但仍明确保留:

1
2
camera_acc : password@#123
GetStatus 200

该记录称无填充格式下,设备定向字典约 4700 条时命中。它比 10 月 31 日会话末尾“仍缺 camera_acc 密码”的状态更新。

因此后续不能继续把“没有 PTZ 凭据”当成唯一卡点。但这条是状态文件记录,本次没有重新对靶机认证,也没有找到最终白板或 flag 的成功回执。

真正剩下的工作

使用正确的 camera_acc 凭据和 UsernameToken 编码完成 PTZ,再把机位变化与媒体画面对应。工作区已经有 sscp_ptz.py 和相关抓帧脚本;下一轮应先验证 GetStatus、移动响应和实际图像是否一致,再判断白板能否读出。

实例关闭后多个入口曾退化为 Caddy 空响应,需要重新核对同一实例的映射和状态,不能把不同实例的会话凭据混用。

资料来源

根据 nest_226/SSCP_LOOT.md、SSCP 当日会话及早期测绘笔记整理。仅保留题目实验账号中与认证突破有关的信息,未附个人服务密钥、完整抓包或浏览器会话。

评论COMMENTS