패치 발표 6시간 전 이미 시작된 공격: PHP 심각도 9.2 취약점 사태

패치 발표 6시간 전 이미 시작된 공격: PHP 심각도 9.2 취약점 사태

사이버보안취약점 분석PHP오픈소스 생태계

데이터 소스:HN + web research

보안 업계에는 오랜 기간 지켜져 온 암묵적인 규칙이 있다. 취약점이 발견되면 관계자들은 비밀유지 협약을 맺고, 방어 측이 물밑에서 수정 코드를 작성한 뒤 약속된 일시에 맞추어 동시 공개하며, 시스템 운영자들은 차례대로 패치를 적용한다. 이러한 협력 체계는 수십 년간 생태계의 안전판 역할을 해왔다.

그러나 2026년 10월 21일, 그 질서가 한순간에 무너졌다. 공식 보안 패치가 배포되기까지 아직 수 시간이나 남아 있던 시점에 Cloudflare의 모니터링 시스템에는 이미 대규모 실전 공격 트래픽이 포착되기 시작했다. 공격자들은 방어 측이 문을 걸어 잠글 때까지 기다려주지 않았다.

이보다 21시간 앞서 두 취약점의 기술적 세부 정보가 온라인 개발자 포럼에 유출되었다. ‘PHP2Shell’로 명명된 이번 사태는 전 세계 웹 관리자들을 깊은 혼란에 빠뜨렸다. 최초의 유출 게시물은 신속히 삭제되었으나 여러 보안 연구기관이 실효성을 즉각 확인했다. 방어 진영이 취약점의 실체를 파악했을 때는 이미 공격자들이 실전에 무기를 투입한 뒤였다.

패치가 나오기도 전에 시작된 공격

두 취약점의 공식 식별 번호는 CVE-2026-109618과 CVE-2026-109619이다. PHP 공식 팀은 CVSS v4.0 기준 9.2점을 부여했으며, 보안 전문 기관 watchTowr는 최고 위험 등급인 10.0점 만점을 매겼다. 이 등급 체계에서는 공용 인터넷에 노출된 장비라면 언제든 서버 제어권을 완전히 빼앗길 위험에 처한다.

정보 유출은 협정 세계시(UTC) 기준 10월 20일 15시 20분에 일어났다. petecooper라는 사용자가 커뮤니티에 패치 사전 공지를 올렸고, 뒤이어 Calif Research 명의의 검증 도구가 네트워크상에 확산되었다. 엔지니어들의 분석 결과 해당 코드가 실제 운영 환경에서 정상 작동하는 것이 입증되었다. 이어 10월 21일 07시 43분, Cloudflare는 공식 패치 공개 예정 시각보다 6시간 이상 앞선 시점에 공용 네트워크에서 초기 침투 시도를 감지했다고 공식 확인했다. 공식 패치는 예정대로 한국 시간 10월 21일 23시(베이징 시간 22시)에 공개되었다.

결국 취약점의 공격 기법이 유출된 후 첫 실전 공격이 도달하기까지 16시간 동안 방어자들은 아무런 대응 수단도 쥐지 못한 채 무방비로 노출되어 있었던 셈이다.

단 하나의 파일 업로드로 끝나는 서버 탈취

이번 결함은 웹 서비스의 가장 기본적인 상호작용 뒤편에 숨어 있었다. 사용자가 프로필 이미지를 등록하거나 첨부파일을 전송하고 양식 서류를 올릴 때 브라우저는 데이터를 multipart/form-data 형식으로 묶어 백엔드 런타임에 전달한다.

문제는 PHP 인터프리터가 이러한 요청 데이터를 구문 분석하는 핵심 코드 영역에서 발생했다. 공격자가 비정상적으로 조작된 패킷을 전송하면 하위 메모리 오염이 촉발되며, 이를 통해 대상 서버에서 임의의 명령을 실행할 수 있게 된다. 보안 기업 Sansec의 설명은 명료하다. 공격자에게 필요한 것은 단 한 번의 비인증 POST 요청뿐이며, 로그인 인증이나 사전 구성 조건은 일절 필요하지 않다.

핵심은 취약점이 실행되는 시점이다. 결함은 애플리케이션 계층의 비즈니스 코드가 동작하기 전에 먼저 터지기 때문에, WordPress, WooCommerce, Magento 같은 소프트웨어가 자체적으로 보안 코딩을 얼마나 철저히 구현했는지는 아무런 의미가 없다. 전 세계 웹사이트의 약 40%가 WordPress 기반으로 구동되는 현실에서 백엔드에 파일 업로드 기능이 켜져 있는 PHP 서버는 모두 표적이 된다.

Tenable의 취약점 분석 안내 이미지 그림: 두 건의 심각한 원격 코드 실행 취약점에 대해 Tenable이 공개한 공식 질의응답 문서. 출처: Tenable

점검 화면을 띄워두어도 소용없다

웹사이트에 비상 상황이 발생하면 관리자들은 흔히 서비스를 유지보수 모드로 전환하고 전면에 공사 중 안내 배너를 띄워 외부 접근을 차단한다. 하지만 이번 사태에서는 점검 화면조차 방패가 되지 못한다. 점검 화면 자체도 PHP 애플리케이션 엔진 위에서 렌더링되므로, 악성 요청은 웹 애플리케이션의 제어 흐름에 닿기도 전에 인터프리터 구문 분석 단계에서 취약점을 건드리기 때문이다. 백엔드에서 PHP 프로세스가 돌아가고 있는 한 공격은 그대로 유효하다.

패치가 나오기 전까지 서버를 온전히 지키기 위해서는 서비스 중단에 준하는 손실을 감내해야 했다. 실행 가능한 임시 대책은 극소수였다. Nginx나 Apache 같은 웹 프런트 계층에서 파일 업로드 요청을 일괄 차단하는 방식이 있으나 사용자의 프로필 수정이나 판매자의 상품 등록 등 모든 파일 기능이 마비된다. 오리진 서버의 방화벽을 Cloudflare 전용 출구 IP로만 한정하여 WAF를 거치도록 강제하는 방안도 있으나 서버의 실제 공인 IP가 이미 노출된 적이 있다면 공격자가 직접 침투하므로 무용지물이 된다. 가장 확실한 임시 조치는 PHP 구동을 완전히 중단하고 순수 정적 웹페이지로 버티는 것이었다.

php.ini 설정을 조정해 공격 접점을 줄이는 방안으로는 session.upload_progress.enabled 비활성화와 session.use_strict_mode 활성화가 제시되었다. 다만 PHP 릴리스 관리팀은 이러한 조치가 노출 위험을 부분적으로 낮출 뿐이며 PHP 자체의 버전 업데이트를 결코 대체할 수 없다고 강조했다.

패치 공개 몇 시간 전, 네덜란드 의회와 국가사이버보안센터(NCSC-NL), IT 전문 매체 Tweakers는 가장 강경한 조치를 선택했다. 바로 웹사이트 서비스를 전면 중단하고 오프라인으로 전환한 것이다. Cloudflare의 최고기술책임자(CTO) Dane Knecht가 지적했듯 WAF 규칙은 임시 지혈대에 불과하다.

수백만 대의 구형 서버는 패치를 받을 수 없다

버전 판올림만으로 모두 해결될 수 있는 문제였다면 사태가 이토록 험악해지지는 않았을 것이다. 보안 연구원 Silas Cutler의 추산에 따르면 공용 인터넷에서 직접 접근 가능한 PHP 인스턴스는 전 세계적으로 약 130만 대에 이르며, 이들은 자동화 스캐너의 최우선 타깃이 되고 있다.

진짜 위기는 이 중 상당수가 공식 보안 패치를 영원히 공급받을 수 없다는 현실이다. PHP 프로젝트의 공식 지원 정책은 현재 유지보수 중인 브랜치로 한정되며, 이번 보안 패치 역시 8.2 이상 버전에만 발행되었다. 반면 5.x, 7.x, 8.0, 8.1 같은 구형 버전들은 이미 오래전에 공식 수명이 종료(EOL)되었음에도 기업의 레거시 인프라와 컨테이너 이미지 속에 수없이 남아 방치되어 있다.

상위 프레임워크 진영은 신속히 대응했다. WordPress는 7.1.3, Drupal은 11.4.10, Laravel은 13.36.0 버전을 출시했고 MediaWiki, phpBB, Magento, Symfony 등도 같은 날 일제히 대응 패치를 선보였다. 그러나 밑바탕이 되는 인터프리터 자체를 교체하지 않는 한 상위 소프트웨어의 보수 작업만으로는 근본적인 침해를 막을 수 없다.

엔터프라이즈 리눅스 환경에서도 진통이 이어졌다. 기업 환경에서 널리 쓰이는 제3자 저장소인 Remi’s RPM repository는 당일 즉시 빌드를 제공하지 않겠다고 선언했다. RHEL 계열 운영체제를 사용하는 기업들은 배포판 자체의 백포트를 마냥 기다리거나 운영 서버에서 직접 소스코드를 컴파일해야 하는 곤란한 처지에 놓였다.

PHP 공식 로고 그림: 30년 역사 동안 전 세계 웹사이트의 40%를 지탱해 온 PHP. 핵심 요청 분석 처리 영역에서 치명적인 결함이 드러났다. 출처: BleepingComputer

신속한 배포 능력이 곧 새로운 보안 경계선이다

오픈소스 생태계의 보안 모델은 각 주체가 보조를 맞추고, 적시에 패치가 배포되며, 운영자들이 안정적으로 업데이트를 적용한다는 이상적인 전제 위에 서 있었다. PHP2Shell 사태는 그 취약한 균형을 산산이 부쉈다.

Sansec과 네덜란드 보안 당국은 패치 공개 전부터 엄중한 경고를 보냈다. 수정 소스코드가 열리면 공격자들은 15분 이내에 역공학을 끝내고 전역 스캔을 개시할 것이라는 예측이었다. 실상은 그보다 더 혹독했다. 세부 공격 경로가 사전에 유출되면서 첫 침투 시도가 공식 패치 도착보다 6시간이나 앞서 터져 나왔다.

반면 현실 세계의 소프트웨어 배포 속도는 지나치게 느리다. 업스트림에서 코드가 공개되더라도 운영체제 배포판이 패키징과 테스트를 거치고, 기업들이 심야 점검 시간을 잡아 실제 서버에 반영하기까지 며칠에서 수주가 걸리는 것이 다반사다. 이미 단종된 구형 브랜치의 경우 공식 코드조차 나오지 않는다.

방어 진영과 침투 세력 사이의 진정한 격차는 보안 패치를 작성하는 역량이 아니라, 그 패치를 현장에서 구동 중인 모든 장비에 도달시키는 물류 역량에 있다. 버전 단절과 운영 현장의 방치 문제를 근본적으로 해결하지 못한다면 아무리 빠른 패치라도 이미 뚫고 들어온 공격의 첫 파도를 뒤쫓는 데 그칠 뿐이다.

참고 링크:

  • PHP 공식 보안 권고문
  • Sansec 기술 분석 리포트
  • Tenable 보안 질의응답
  • watchTowr 취약점 연구 보고서
  • Cloudflare 위협 인텔리전스 브리핑