CPU 사용량 몇 퍼센트가 수년짜리 공급망 백도어를 잡아냈다 — xz-utils 사건

CPU 사용량 몇 퍼센트가 수년짜리 공급망 백도어를 잡아냈다 — xz-utils 사건

분류: CVE · 커널·OS · RCE · CVE-2024-3094 [정보성]

덱. 2024년 3월, 압축 라이브러리 xz-utils(liblzma)의 배포판 빌드 산출물 안에서 정교하게 숨겨진 백도어가 발견됐습니다. 이 백도어는 systemd 알림 기능을 쓰는 OpenSSH의 인증 경로를 타고 원격 코드 실행(RCE)으로 이어질 수 있었습니다. 발견 계기는 한 개발자가 로그인 과정에서 sshd의 CPU 사용량이 평소보다 유독 높다는 것을 이상하게 여긴 것이었습니다.

리드

오픈소스 생태계에서 가장 값어치 있는 자산은 코드가 아니라 유지관리자에 대한 신뢰입니다. 오랜 기간 정상적으로 기여하며 신뢰를 쌓은 계정이 결국 커밋 권한이나 릴리스 권한을 얻게 되고, 그 권한이 공급망 전체로 퍼집니다. 이번 사건은 그 신뢰가 어떻게 배신당할 수 있는지를 보여주는 사례입니다 — 코드 저장소(git) 자체에는 백도어의 최종 트리거가 없고, 배포용으로 만들어 배포하는 압축 파일(tarball)에만 악성 빌드 로직이 심어져 있었다는 점에서 더 그렇습니다. 검토가 몰리는 곳(공개 git 이력)과 실제로 사용자 손에 들어가는 곳(릴리스 아카이브)이 다르다는 틈을 정확히 노린 설계였습니다.

핵심 사실 요약

  • 악성 코드는 xz-utils 5.6.0 릴리스부터 확인됐고, CVE-2024-3094로 지정됐습니다. 여러 겹의 난독화를 거쳐, 소스코드 안에 숨겨진 테스트 파일이 liblzma 컴파일 과정에서 미리 컴파일된 오브젝트 파일을 추출하는 데 쓰이고, 이 파일이 liblzma의 특정 함수 동작을 바꿔치기합니다.
  • 이 변조된 liblzma는 systemd 알림 기능을 지원하도록 빌드된 OpenSSH(sshd)에 영향을 줍니다. libsystemd가 lzma에 의존하기 때문에, 백도어가 이 의존 관계를 타고 인증 데이터 처리 과정에 개입할 수 있습니다.
  • 백도어 트리거는 Git 저장소의 소스에는 없고, 특정 배포판이 배포하는 릴리스 tarball에만 들어 있습니다. 빌드 트리거 역할을 하는 M4 매크로가 git 배포본에는 빠져 있기 때문입니다.
  • 악성 코드 작성자로 지목된 계정은 @JiaT75이며, 이 계정은 oss-fuzz 프로젝트에도 코드를 제출한 이력이 있는데, 원문은 그 제출이 오히려 퍼저(fuzzer)가 이 백도어를 잡아내지 못하게 막는 효과를 냈을 가능성을 지적합니다.
  • 발견 경위: 개발자 Andres Freund가 sshd 로그인 과정에서 CPU 사용량이 비정상적으로 높다는 점과, 메모리 분석 도구 Valgrind로 프로파일링하던 중 다수의 오류가 발생한 점을 이상하게 여겨 조사에 들어갔고, 그 결과 백도어를 발견했습니다.
  • 빌드 과정에서 실행되는 Build-to-Host.m4 스크립트가 configure 스크립트 마지막에 난독화된 스크립트를 주입합니다. 이 스크립트는 (1) x86-64 리눅스인지, (2) Debian 또는 RPM 패키지 빌드 과정인지를 확인한 뒤에만 동작하며, liblzma의 Makefile을 건드려 런타임 심볼 해석 과정에 개입, RSA_public_decrypt 심볼이 백도어 코드를 가리키게 만듭니다.
  • sshd의 공개키 인증 과정에서 이 심볼이 호출되면 공격자 코드가 실행됩니다. 이 코드는 인증에 사용된 공개키에서 페이로드를 추출해 검증·서명 확인을 거친 뒤, 통과하면 libc의 system() 함수로 넘겨 실행시킵니다. 원문은 이를 인증 우회가 아니라 **원격 코드 실행(RCE)**이라고 명시합니다.
  • 백도어 실행에는 여러 런타임 조건이 필요했습니다: TERM 환경변수 미설정, 실행 바이너리 경로가 /usr/sbin/sshd, LD_DEBUG/LD_PROFILE 미설정, LANG 환경변수 설정, 그리고 gdb·rr 같은 디버깅 도구 탐지 시 미동작(안티디버깅) 등입니다.
  • Wiz의 후속 리버스엔지니어링에 따르면, 이 백도어는 RSA_public_decrypt 외에도 EVP_PKEY_set1_RSA, RSA_get0_key를 대체 후킹 지점으로 갖고 있었고, 공격자가 만든 접속을 verbose 로그에서 숨기기 위한 방법을 최소 3가지(가짜 공개키 삽입·특정 로그 라인 필터링·성공 로그를 실패 로그로 치환) 갖추고 있었습니다.
  • Wiz 자체 클라우드 데이터 기준으로는 취약 버전을 가진 인스턴스 비율이 전체 클라우드 환경의 약 2%에 그쳤다고 밝혔습니다. 영향받은 배포판은 Fedora 41/Rawhide, Debian(비-stable 브랜치), 특정 기간 업데이트된 Kali Linux, openSUSE Tumbleweed, Alpine, Arch Linux, Gentoo 등이며, RHEL·FreeBSD·Amazon Linux는 영향이 없다고 원문에 정리돼 있습니다. CISA는 5.6.0 이전 버전으로 다운그레이드하고 의심 활동을 점검하라고 권고했습니다.
  • ⚠️미확인(팩트체크 대상) — @JiaT75(Jia Tan)의 실명·소속, 신뢰를 쌓기까지의 구체적 기여 이력·시간대, 백도어 삽입 커밋의 실제 diff는 이 원문(Wiz 블로그)만으로는 확증되지 않으며 별도 1차출처 대조가 필요합니다.

짧은 논평

이 사건이 무서운 지점은 코드가 정교해서가 아니라, 시간을 들여 신뢰를 산 뒤 그 신뢰를 한 번에 현금화하는 방식이었다는 데 있습니다. 취약한 코드 한 줄을 찾는 것과, 몇 년에 걸쳐 정상적으로 기여하다 결정적인 순간에만 악성 로직을 끼워 넣는 계정을 걸러내는 것은 전혀 다른 문제입니다. 그리고 이번엔 그 악성 로직조차 검토가 활발한 git 이력이 아니라, 상대적으로 눈이 덜 가는 릴리스 tarball 빌드 과정에만 심었습니다 — 저희가 필터 우회 사례들에서 반복해서 보는 원칙과 같은 결입니다. 검증이 집중되는 지점과 실제로 결과물이 만들어지는 지점이 다르면, 공격자는 항상 검증이 약한 쪽을 고른다는 것. 오픈소스 공급망에서는 “누가 이 코드를 검토했는가”만큼 “이 코드가 정말 검토된 그 코드로 빌드됐는가”도 물어야 한다는 교훈을 남긴 사례입니다.

References / 참고자료

  1. Wiz, “CVE-2024-3094: Critical RCE Vulnerability Found in XZ Utils” — 이 글이 재구성한 원 분석. 백도어의 발견 경위, 빌드 트리거 조건, 실행 흐름, 영향받는 배포판 목록을 다룸. https://www.wiz.io/blog/cve-2024-3094-critical-rce-vulnerability-found-in-xz-utils

이 글은 위 원 분석을 우리 관점에서 다시 쓰고 짧은 논평을 더한 정보성 초안입니다. 특정 문장·코드·명령어를 그대로 옮기지 않았으며, 작동하는 백도어 코드나 재현 절차는 싣지 않았습니다. ⚠️미확인 표시 항목은 발행 전 독립 팩트체크에서 확증·정정되어야 합니다.