2021년 3월 28일, git.php.net의 php-src 마스터 브랜치에 두 개의 커밋이 나타났는데, 이는 PHP의 창시자인 Rasmus Lerdorf와 핵심 개발자 Nikita Popov의 이름으로 푸시된 것이었다. 커밋 제목은 '[skip-ci] Fix typo'였는데, 이는 검토를 건너뛸 만큼 사소한 주제였고, skip-ci 접두사와 함께 지속적 통합까지 우회하도록 설계된 것이었다. 널리 포함되는 헤더에 가해진 이 변경은 서버 변수에서 HTTP User-Agent를 확인하고, 그것이 'zerodium' 문자열로 시작하면 헤더의 나머지 부분을 PHP 코드로 실행했다. 즉, 오염된 인터프리터를 실행하는 모든 서버에서 원격 코드 실행이 가능했다.
그것은 작동하지 않았고, 그 이유는 시사하는 바가 크다. 커밋은 공개 피드를 읽던 커뮤니티 구성원들에 의해 몇 시간 안에 발견되었다. 한 논평자가 커밋 자체에 그 변경을 지적했고, PHP 개발자 Jake Birchall은 그것이 user-agent 헤더에서 코드를 실행한다는 것을 확인했다. Popov는 같은 날 저녁, 모든 정황이 개별 계정이 아니라 git.php.net 서버의 침해를 가리킨다고 발표했다. 커밋 텍스트 자체에는 'REMOVETHIS: sold to zerodium, mid 2017'이라는 줄이 있었는데, 이는 그 백도어가 몇 년 전에 익스플로잇 판매업체에 중개되었음을 암시한다.
프로젝트의 대응은 자산을 수리하는 것이 아니라 제거하는 것이었다. git.php.net은 즉시 중단되었고, 그때까지 부차적이었던 GitHub 미러가 표준 저장소가 되었다. 쓰기 권한은 php GitHub 조직으로 이전되었으며 멤버십에는 2단계 인증이 요구되었다. 그리고 저장소의 추가 오염 여부를 감사하는 동안 모든 PHP 릴리스가 2주간 보류되었다. 그 두 커밋은 최종 사용자에게 단 한 번도 도달하지 않았다.
무엇을 치렀나
최종 사용자 영향은 없었다. 두 커밋 모두 어떤 릴리스 전에도 되돌려졌다. 실제 비용은 프로젝트 자체의 git 인프라와 모든 PHP 릴리스에 대한 2주간의 동결이었다
왜 일어났나
프로젝트는 쓰기 권한을 위해 자체 제작한 karma 시스템을 갖춘 자체 git 서버를 운영했다. 이는 소규모 핵심 팀이 전적으로 스스로 방어해야 했던 맞춤형 인증 표면이었다.
그 서버에서의 커밋 신원은 암호화 서명이 아니라 푸시 시점의 승인에 의존했으므로, 서버를 통제하는 누구든 프로젝트에서 가장 신뢰받는 이름으로 커밋할 수 있었다.
위장은 검토 과정에 맞춰 조정되었다. 거의 모든 곳에 포함되는 헤더에서 한 단어짜리 'typo' 수정이었고, CI를 완전히 건너뛰도록 접두사가 붙었다.
프로젝트를 구한 GitHub 미러는 수년간 이류 복사본이었다. 팀이 비상 상황에서 이를 승격하기로 선택했기 때문에야 복구할 수 있었다.
교훈
버전 관리를 자체 호스팅하는 것은 프로젝트에 아무것도 주지 않는다. 다만 혼자서 방어해야 하는 공격 표면만을 줄 뿐이다. 미러는 그것이 필요해지는 바로 그 시간에 진실의 원천이 될 준비가 되어 있을 때만 가치가 있다.
후속 상황
php.net은 조사가 진행되는 동안 공식적으로 2주간 릴리스를 보류하며, 악성 커밋이 '즉시 발견되어 되돌려졌고 따라서 최종 사용자에게는 결코 도달하지 않았다'고 밝혔다. 저장소는 두 커밋 외의 오염 여부를 검토했고, GitHub는 php-src의 영구적인 표준 홈이 되었으며, 조직 멤버십에는 이제 2FA가 필요하다. 백도어의 코드 주석인 'sold to zerodium, mid 2017'은 커밋 기록에 여전히 공개되어 있다. 그 판매업체는 구매를 결코 확인하지 않았다.
근거 확인하기
출처
- Changes to Git commit workflow (php.internals #113838) news-web.php.net · news-web.php.net ·
- PHP releases on hold php.net · php.net ·
- [skip-ci] Fix typo (commit c730aa26) GitHub php/php-src · github.com ·
- PHP's Git server hacked to add backdoors to PHP source code BleepingComputer · bleepingcomputer.com ·