Hanwha 보안 카메라 펌웨어를 분석하는 과정에서 로그인 페이지에 포함된 GitHub 관리자 토큰과 CI 환경 변수 유출을 발견한 이야기.
보안 카메라에 대해 다시 조금 더 생각하게 됐다. AXIS가 자사 모든 카메라에서 Linux 애플리케이션을 쉽게 실행할 수 있도록 더 적극적으로 밀고 있기 때문인데, 이런 기기들은 엔터프라이즈 환경에서 훨씬 더 진지한 공격 대상이 되며, 따라서 취약점 관리나 자격 증명 관리 같은 측면에서도 그렇게 다뤄져야 한다. 누군가가 내게 Hanwha (Vision.)라는, 내게는 생소한 회사를 언급했다. 사이트를 살펴보니 카메라 각 모델별로 접근 가능한 펌웨어 블롭이 있었고, 이런 건 언제나 반가운 일이다.
이미지를 가져와 binwalk에 던져 넣었다. 그냥 rootfs 같은 것이길 바랐지만, 내부에는 카메라용 AI 관련 내용이 담긴 별도의 tarball과 binwalk가 암호화되었다고 표시하는 fwimage.tgz가 들어 있었다.
주변을 검색하다가 Matt Brown이 이 카메라들에 대해 쓴 글이 있어서 큰 도움이 됐다. 기본적으로 암호 구문은 HTW + 모델 번호라서 HTWXNP-9300RW가 동작했다.
지금은 뭔가를 더 하는 듯했다. 그 tarball 안에 암호화된 또 다른 fwimage.tgz가 있었는데 같은 방식이 아니어서 Matt Brown의 설정을 그대로 재사용할 수는 없었다. Hanwha가 하드웨어에 키를 굽는 식의 좀 더 고급 방식을 쓰는 건가 싶어서 거의 포기할 뻔했다. 물론 그것도 완벽한 방법은 아니지만, 적어도 시작하려면 카메라를 실제로 가지고 있어야 하니까 말이다. 아무튼 바깥쪽 tarball 안에 fwupgrader 바이너리가 있어서 ghidra에 넣고 들여다보기 시작했다.
뭐, 이게 2023년쯤이었다면 내가 직접 뒤적거리고 있었겠지만, 이번에는 claude code에 맡겨 두고 근사한 저녁을 만들러 가서 파트너와 시간을 보냈고, 조금 뒤 돌아오니 설명과 멋진 rootfs가 준비되어 있었다.
Hanwha는 실제 rootfs를 어떻게 복호화하는지 숨기기 위해 fwupgrader에 난독화를 넣어 두었다. AES 키는 바이너리 안의 작은 정적 키 테이블과 XOR된 뒤 런타임에 다시 조립되고, IV는 그냥 평문으로 들어 있다. fwupgrader는 단순히 openssl CLI를 호출하며, 명령 조각들조차 같은 방식으로 XOR 난독화되어 있다.
복원한 명령은 다음과 같다:
openssl enc -md sha256 -aes-256-cbc -d \
-K <KEY> -iv <IV> -in <INPUT> -out <OUTPUT>
키와 iv가 그냥 하드코딩되어 있으므로(모델 라인 전체에서 동일하다), 여기 공개한다:
KEY = dfa049bb922e63e2decc764af5628068e5b7a2662e479a615b14643e567579b0
IV = 53f926801b81454a4f889c9a390db6e6
이제 평범한 방식으로 파고들 수 있는 완전한 rootfs를 얻게 된다.
드디어 그냥 내용을 볼 수 있게 되었으니, 눈에 띄는 것이 있는지 보려고 즉시 trufflehog를 돌렸다. 그랬더니 약 30개 파일에 중복된 github 토큰이 들어 있었다... 그 토큰이 어떤 저장소들에 접근 가능한지 확인해 보니, 그들의 github 조직에 있는 수백 개 저장소에 대해 관리자 권한을 가지고 있었다.
하지만 펌웨어에 Github 토큰을 넣어 출하하는 조직을 본 것이 이번이 처음은 아니다... 다만 그건 다른 블로그 글에서 할 이야기다. 그런데 왜 이 조직은 이 토큰을 30개쯤 되는 파일에 넣어 둔 걸까? 보아하니 이 카메라들의 UI를 vite로 빌드하는데, 변수 중 하나가 빌드 시점에 process.env 전체로 설정되고 있었다. 즉, CI 작업의 전체 환경이 이 파일들에 그대로 기록되고 있었다는 뜻이다.
var W = {
DATAPORT: "9090",
GIT_LFS_SKIP_SMUDGE: "1",
npm_command: "run-script",
KUBERNETES_SERVICE_PORT_HTTPS: "443",
GITHUB_NPM_TOKEN: "<snip>:ghp_…REDACTED…",
npm_config_userconfig: "/home/docker/.npmrc",
// etc
이 카메라들을 실제로 가지고 있지는 않지만, 내 생각에는 이것은 이 카메라의 관리자 UI에 접근하는 누구에게나 이 github 토큰이 네트워크를 통해 전송되었을 가능성이 크다는 뜻이다. 그리고 (부디) 아무 악의적인 사람도 그걸 눈치채지 않았기를 바란다. 물론 실제로는 서빙되지 않고 디스크에만 있었을 수도 있다.
그런데 환경 안에는 다른... 흥미로운 데이터 조각들도 있었다. 몇몇 환경 변수에 IP 주소가 들어 있었는데, 그것들이 미국 국방부에 할당된 주소였다:
음... 이건 단순한 우연일까? 아니면 사람들이 절대 상호작용하지 않을 거라고 생각하고 내부 서비스에 가져다 쓰는 이상한 경우 중 하나일까(정말 제정신 아닌 관행이다...) 아니면 Hanwha가 미국 DoD와 더 직접적으로 연결되어 있는 걸까?
Hanwha 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.
아... 그렇구나.... 고등학교 때 SGR-A1에 대한 글을 읽었던 기억이 난다. 하지만 몇 년 뒤 커리어를 이어 가다가 그 제조사의 왕국 열쇠 같은 것을 바닥에서 우연히 줍게 될 줄은 전혀 생각하지 못했다... 가끔은 내 인생이 좀 이상하다...
그래도 이것들이 미국 장비인 것은 아니고, 그런 비슷한 것도 아니다. 그렇다면 왜 Hanwha Vision에 DoD와 조금이라도 관련된 무언가가 필요한 걸까? 이들의 CI가 모회사 Hanwha의 중앙화된 팀에서 제공되고 있어서, 자매 회사인 Hanwha Aerospace의 요구 때문에 공유 플랫폼의 CI 환경 변수에 이런 항목들이 들어가게 되었을 가능성이 있을까? 아니면 또 다른 자매 회사인 Hanwha Defense USA 때문일까? 그쪽에서는 또 다른 크고 무서운 강철 기계들을 만들고 있으니 말이다.
![]()
이게 어떤 일회성 우연이 아니라는 점, 그리고 그들의 펌웨어 안에 수백 개의 다른 github 토큰이 들어 있는 것은 아니라는 점을 확인하고 싶었다. 그래서 Hanwha 웹사이트를 긁어서 찾을 수 있는 모든 카메라의 모든 펌웨어를 다운로드했고, 그 결과 대략 500개 정도의 펌웨어를 모았다(카메라는 600몇 개쯤 있었지만 모두 펌웨어가 올라와 있던 것은 아니었다). 그리고 위와 같은 방식으로 그중 62%를 추출할 수 있었으며, github 토큰이 들어 있던 것은 단 세 개뿐이었고 모두 같은 토큰이었다.
왜 나머지는 잘 안 됐는지는 잘 모르겠지만, 이 정도면 나는 충분히 납득할 수 있다.
토큰이 어디 있는지 식별할 수 있을 만큼의 정보만 담은 아주 짧은 이메일을 작성해 Hanwha에 보냈다. 다행히 그들은 보안 문제 제보용 공개 이메일 주소를 잘 마련해 두고 있었고, 12시간 안에 응답해서 토큰이 폐기되었다고 알려 주었다. 애초에 gh 토큰이 거기에 있었어서는 안 됐지만, 이렇게 신속한 응답과 해결을 본 적은 없었다.
우리는 정말 이런 실수를 이렇게 자주 반복하는 걸 멈춰야 한다. 이러면 내가 밤에 어떻게 편히 잠들 수 있겠나?
고맙다 컴퓨터, 다음에 또 보자