My security camera shipped a GitHub admin token in its login page

My security camera shipped a GitHub admin token in its login page

我的安防摄像头在登录页面中内置了 GitHub 管理员令牌

I have been thinking a bit more about security cameras again, because of AXIS starting to push more for every one of their cameras to be able to easily run linux applications on them, they’re far more serious targets in an enterprise environment and need to be managed as such for vulnerabilities and credential management etc. 我最近又开始思考安防摄像头的问题了。由于 AXIS 开始大力推动其每一款摄像头都能轻松运行 Linux 应用程序,它们在企业环境中的目标属性变得更加严重,因此在漏洞和凭据管理等方面需要进行相应的管控。

Someone brought up to me a company that sounded new to me, Hanwha (Vision.) I took a look at the site, and found that they had accessible firmware blobs for each model of camera, which is always a treat. Poking and prodding I took the image and threw it at binwalk hoping it was just a rootfs or something, but inside there was a separate tarball with some AI stuff for the camera and a fwimage.tgz that binwalk was flagging as encrypted. 有人向我提到了一个对我来说很陌生的公司:韩华(Hanwha Vision)。我浏览了他们的网站,发现每个型号的摄像头都有可下载的固件包,这总是令人欣喜。我尝试用 binwalk 对镜像进行分析,希望能直接提取出 rootfs 之类的东西,但里面包含了一个独立的 tarball(包含一些 AI 组件)以及一个被 binwalk 标记为加密的 fwimage.tgz。

I was googling around and saw that Matt Brown has a writeup on these cameras that got me through. Basically the passphrase is HTW + the model number so HTWXNP-9300RW worked. Seems like they do some more stuff now, because inside of that tarball was another fwimage.tgz that was encrypted but it wasn’t the same scheme, so we can’t just re-use the same setup from Matt Brown. 我在谷歌上搜索时,发现 Matt Brown 有一篇关于这些摄像头的文章,这帮了我大忙。基本上,解压密码是“HTW + 型号”,所以 HTWXNP-9300RW 成功了。看起来他们现在增加了一些新机制,因为在该 tarball 内部还有另一个加密的 fwimage.tgz,但加密方案不同,所以我们不能直接沿用 Matt Brown 的方法。

I kinda figured I was gonna have to give up and that Hanwha was doing something more advanced, like burning a key into the hardware (which isnt foolproof obviously but you at least need to own the camera to start.) Anyways, there was a fwupgrader binary that was in that outer tarball, so I threw it into ghidra and started poking around. Well I would have been poking around if it was 2023 or something, but I pointed claude code at it and went to make a lovely dinner and spent time with my partner instead, and came back a bit later to a description and a nice rootfs. 我本以为不得不放弃,认为韩华采用了更高级的手段,比如将密钥烧录到硬件中(虽然这显然不是万无一失的,但至少你得先拥有一台摄像头才能开始)。总之,外层的 tarball 中有一个 fwupgrader 二进制文件,我把它扔进 Ghidra 开始研究。如果是在 2023 年,我可能真的会自己动手研究,但我这次直接让 Claude Code 处理它,然后去做了顿美餐并陪伴我的伴侣。过了一会儿回来时,它已经给出了代码描述并提取出了一个完美的 rootfs。

Hanwha had built some obfuscation into the fwupgrader to hide how they decrypt the actual rootfs. The AES key is XOR’d against a small static key table in the binary and reassembled at runtime (the IV is just plaintext in there) the fwupgrader just shells out to the openssl CLI, and even the command fragments are XOR-obfuscated the same way. 韩华在 fwupgrader 中内置了一些混淆机制,以隐藏他们解密实际 rootfs 的方式。AES 密钥与二进制文件中的一个小静态密钥表进行异或(XOR)运算,并在运行时重新组合(IV 在其中只是明文)。fwupgrader 只是调用 openssl 命令行工具,甚至连命令片段也是以同样的方式进行异或混淆的。

Reconstructed the command looks like this: 重构后的命令如下: openssl enc -md sha256 -aes-256-cbc -d -K <KEY> -iv <IV> -in <INPUT> -out <OUTPUT>

Since the key and iv are just hardcoded (the same across the model line), I will publish them here: 由于密钥和 IV 只是硬编码的(在整个产品线中通用),我将在此公布它们: KEY = dfa049bb922e63e2decc764af5628068e5b7a2662e479a615b14643e567579b0 IV = 53f926801b81454a4f889c9a390db6e6 And with that we have a full rootfs to dig into normally. 有了这些,我们就可以获得完整的 rootfs 并进行常规分析了。

Truffles: since we finally can just look at stuff I ran trufflehog immediately to see if there was anything obvious, and there was a github token duplicated in like 30 files… I checked what repos the token had access to, and it had admin privileges to hundreds of repositories in their github organization. This isn’t my first rodeo with an org shipping a Github token in their firmware though… but that’s a story for a different blog post. “松露”(Truffles):既然终于可以查看内容了,我立即运行了 trufflehog 来看看是否有明显的漏洞,结果发现一个 GitHub 令牌在约 30 个文件中重复出现……我检查了该令牌有权访问的仓库,发现它对他们 GitHub 组织下的数百个仓库拥有管理员权限。不过,这已经不是我第一次遇到有公司在固件中泄露 GitHub 令牌了……但那是另一个博客文章的故事了。

Why would this org put this token in like 30 files though? It looks like they build the UI for these cameras with vite, and one of the variables is being set to the entirety of process.env at build time, which means the entirety of the CI job’s environment is being written to these files. 为什么这个组织会把这个令牌放在 30 个文件里呢?看起来他们是用 Vite 构建这些摄像头的 UI,其中一个变量在构建时被设置为整个 process.env,这意味着整个 CI 作业的环境变量都被写入了这些文件中。

I don’t have any of these cameras to test, but I think this would mean that anyone accessing the admin UI of these cameras likely has had this github token sent to them over the wire and (hopefully) nobody evil noticed. Maybe it didn’t get actually served and just lived on disk, though. 我手头没有这些摄像头可以测试,但我认为这意味着任何访问这些摄像头管理界面的人,其 GitHub 令牌很可能已经通过网络传输给了他们,(希望)没有坏人注意到这一点。不过,也许它并没有被实际服务出去,只是存在于磁盘上。

There were some other… interesting bits of data in the environment though: there were some env vars with IP addresses in them, but they are assigned to the US Department of Defense: 不过,环境中还有一些……有趣的数据:有一些环境变量中包含 IP 地址,但它们被分配给了美国国防部: SWARM_MASTER_NFS_ADDRESS: 55.101.212.23 OTEL_ELASTIC_URL: http://55.101.212.21:5601/<snip> CIMIP: 55.101.211.213

Huh… is this just a coincidence and one of those weird instances where people have taken IP space for internal services when they know they will never interact with it (insane practice btw…) or is Hanwha more directly tied with the US DoD? 嗯……这只是巧合,还是那种人们在明知永远不会与外部交互的情况下,擅自占用 IP 地址段作为内部服务的怪事(顺便说一句,这是一种疯狂的做法……),又或者是韩华与美国国防部有更直接的联系?

Let’s look at the wikipedia page for Hanwha Vision: 让我们看看韩华 Vision 的维基百科页面: Hanwha Vision (Korean: 한화비전), founded as Samsung Techwin, is a video surveillance company. It is a subsidiary of Hanwha Group. Former products: K9 Thunder self-propelled artillery, K10 ammunition resupply vehicles, sub-systems for K2 Black Panther, sentry gun robot SGR-A1. 韩华 Vision(韩语:한화비전),前身为三星 Techwin,是一家视频监控公司。它是韩华集团的子公司。曾生产的产品包括:K9“雷霆”自行火炮、K10 弹药补给车、K2“黑豹”主战坦克子系统、SGR-A1 哨兵机器人。

Oh… okay… I remember reading about the SGR-A1 when I was in high school, but I never thought I would be accidentally finding keys to the kingdom of the manufacturer on the ground later in my career… my life is kinda weird sometimes… 哦……好吧……我记得高中时读过关于 SGR-A1 的报道,但我从没想过在职业生涯的后期,我会意外地在地上捡到这家制造商的“王国钥匙”……我的生活有时确实有点奇怪……

SPECULATION WARNING: Even still, these aren’t American devices, or anything like that. Why would Hanwha Vision need anything remotely related to the DoD? Is it possible that their CI is provided by some centralized team at their parent company Hanwha, where the needs of their sister company Hanwha Aerospace cause the shared platform to have these entries in the CI environment variables? Or maybe because of their other sister company, Hanwha Defense USA, where they make other large scary steel machines. 推测警告:即便如此,这些也不是美国设备。为什么韩华 Vision 会需要与国防部相关的东西?有没有可能他们的 CI 是由母公司韩华的某个集中化团队提供的,而其姊妹公司韩华航空航天(Hanwha Aerospace)的需求导致共享平台在 CI 环境变量中包含了这些条目?又或者是因为他们的另一家姊妹公司——韩华防务美国(Hanwha Defense USA),他们在那里制造其他大型且可怕的钢铁机器。

A little extra digging: I wanted to make sure this wasn’t some kind of fluke, and that there weren’t hundreds of other different github tokens in their firmware, so I scraped the Hanwha website to download every firmware for every camera I could find, and ended up with around ~500 firmwares. I was able to extract 62% of them with the same approach as above, and only three of them had github tokens, and they were all the same token. Not really sure why the others didn’t work, but it’s close enough for me to feel satisfied. 进一步挖掘:我想确保这并非偶然,也不存在固件中包含数百个其他不同 GitHub 令牌的情况。因此,我抓取了韩华网站,下载了我能找到的所有摄像头的固件,最终得到了约 500 个固件。我用上述同样的方法成功提取了其中 62% 的固件,只有三个固件中包含 GitHub 令牌,而且它们都是同一个令牌。虽然不确定为什么其他固件无法提取,但这已经足够让我感到满意了。

Disclosure: I wrote up a very small email with enough information to identify where the token… 披露:我写了一封简短的邮件,其中包含了足够的信息来识别该令牌的位置……