PHP 핵심 원격 코드 실행 취약점(PHP2Shell) 대응 권고


개요

PHP 핵심(core)에서 원격 코드 실행(RCE)이 가능한 심각한 취약점 두 건(CVE-2026-109618, CVE-2026-109619)이 공개됐습니다. PHP는 웹 서비스에 널리 쓰이는 범용 스크립트 언어로, WordPress, Drupal, Magento(Adobe Commerce), WooCommerce, Shopware 등 PHP 기반 웹 서비스가 영향을 받습니다. PHP를 운영하는 조직은 PHP 자산을 바로 식별하고 패치를 적용해야 합니다.

PHP2Shell로 불리는 두 취약점은 PHP 보안팀이 10월 21일 14:00 UTC(한국시간 23:00) 정기 외 보안 릴리스를 예고한 상태에서, 패치 공개 전인 10월 20일 취약점 정보와 익스플로잇 도구 스크린샷이 외부로 유출됐습니다.


그림 1. 보안 연구자 J4ck3LSyN이 X에 재현 주장을 게시했습니다. 연구자는 원인을 session.upload_progress 핸들러의 힙 Use-After-Free로 추정했으나, PHP 보안팀이 공식 확인한 내용은 아닙니다.

보안 기업 watchTowr가 CVE-2026-109618 재현에 성공했다고 밝혀 취약점의 실재가 확인됐으며, PHP 보안팀은 두 취약점을 모두 CVSS v4.0 기준 9.2점(Critical)으로 평가했습니다. 일부 매체에서 언급된 10.0점은 공식 점수가 아닙니다.

2026년 10월 21일 기준 실제 침해 사례와 CISA KEV 등재는 보고되지 않았으나, 패치 전 정보 유출로 공격 코드가 빠르게 완성될 가능성이 있습니다. 또한 PHP 5.x, 7.x, 8.0, 8.1 등 지원이 종료된(EOL) 버전에는 공식 패치가 제공되지 않습니다.

항목내용
CVECVE-2026-109618, CVE-2026-109619
공개명PHP2Shell
유형힙 Use-After-Free(CWE-416) → 원격 코드 실행 (추정)
CVSSv4.0 9.2 (Critical), PHP 보안팀 평가
인증 필요 여부불필요 (CERT-EU 평가)
발생 위치ext/session, 세션 업로드 진행률(session.upload_progress) 핸들러 (추정)
정보 유출일2026-10-20
패치 공개2026-10-21 14:00 UTC
실제 악용미보고 (2026-10-21 기준)

영향을 받는 버전

유출된 익스플로잇 도구의 배너와 공개 보고에 따르면 PHP 5.4.0 이후 모든 버전이 영향을 받습니다. PHP는 영향 버전과 수정 버전을 10월 21일 보안 릴리스와 함께 공개한다고 밝혔습니다. 패치는 현재 지원 중인 8.2, 8.3, 8.4, 8.5 브랜치에만 제공될 예정입니다. 아래 패치 버전은 보안 연구자들이 예측한 다음 포인트 릴리스 번호입니다. 적용 전에 php.net 공식 공지와 대조하시기 바랍니다.

브랜치취약한 버전패치 버전비고
8.5.x8.5.0 ~ 8.5.118.5.12지원 중
8.4.x8.4.0 ~ 8.4.268.4.27지원 중
8.3.x8.3.0 ~ 8.3.358.3.36지원 중
8.2.x8.2.0 ~ 8.2.348.2.35보안 지원 2026-12-31 종료
8.0.x, 8.1.x전체없음EOL, 상위 브랜치로 업그레이드 필요
7.x전체없음EOL, 상위 브랜치로 업그레이드 필요
5.4 ~ 5.6전체없음EOL, 상위 브랜치로 업그레이드 필요

RHEL, Ubuntu, Debian, SUSE 등 리눅스 배포판은 자체 패키지 버전에 수정 사항을 백포트합니다. 배포판 패키지를 쓰는 경우 위 업스트림 버전 번호가 아니라 각 배포판의 보안 공지(CVE 트래커)를 기준으로 패치 여부를 판단합니다. Docker 공식 php 이미지는 php.net 원본 소스로 빌드되므로, 수정 버전 태그가 나오면 그 태그로 다시 빌드합니다.

취약점 분석

PHP는 영향 버전과 기술 설명을 패치와 함께 발표할 예정입니다. 아래 분석은 유출 자료와 보안 연구자들의 공개 분석을 바탕으로 한 추정입니다.

공개 분석은 취약 지점을 PHP 세션 확장(ext/session)의 업로드 진행률 추적 기능(session.upload_progress)으로 봅니다. 이 기능은 브라우저가 multipart/form-data 형식으로 파일을 보낼 때 업로드 진행 상황을 사용자 세션에 기록합니다. PHP는 애플리케이션 코드가 실행되기 전에 요청 본문을 직접 파싱합니다. 따라서 추정 원인이 맞다면, 취약한 코드는 어떤 PHP 스크립트가 올라가 있는지와 관계없이 웹 서버에 도달한 요청만으로 실행됩니다.

근본 원인(추정)

보안 연구자 J4ck3LSyN의 분석(미확인)에 따르면 ext/session/session.c의 php_session_rfc1867_callback 함수가 진행률 값(post_bytes_processed, current_file_bytes_processed)을 가리키는 원시 zval 포인터를 세션 해시테이블에 캐싱합니다. 업로드 처리 중 세션 데이터가 다시 디코딩되면 기존 트리가 zval_ptr_dtor로 해제됩니다. 캐싱된 포인터는 그대로 남아 이미 해제된 메모리를 참조합니다(힙 Use-After-Free). 공격자는 조작한 multipart 요청으로 해제된 메모리 영역을 자신의 데이터로 다시 채운(heap grooming) 뒤, zend_call_function 경로로 실행 흐름을 빼앗아 system() 등 임의 함수를 호출할 수 있습니다. 두 CVE 가운데 하나는 업로드 진행률 핸들러, 다른 하나는 multipart 파서에 있는 것으로 추정됩니다.

추정 원인이 맞다면 취약점을 유발하는 데 필요한 설정은 모두 PHP 기본값입니다.

설정기본값의미
session.upload_progress.enabled1 (On)업로드 진행률 추적 활성화
session.upload_progress.namePHP_SESSION_UPLOAD_PROGRESS추적을 시작하는 POST 필드명
session.upload_progress.freq1%진행률 갱신 주기
session.upload_progress.min_freq1최소 갱신 간격(초)

추정 원인이 맞다면 설정을 바꾸지 않은 PHP 웹 서버는 모두 공격 대상입니다. 공격자는 인증 없이, 파일 업로드 폼이 없는 경로에도 PHP_SESSION_UPLOAD_PROGRESS 필드를 넣은 multipart POST 요청을 보내 취약 코드를 실행할 수 있습니다.

공격 성공 시 영향

  • 임의 명령 실행: PHP-FPM 또는 웹 서버(www-data, apache, nginx 등) 권한으로 시스템 명령어 실행
  • 웹쉘 설치: 웹 루트에 PHP 웹쉘을 기록해 지속적인 접근 경로 확보
  • 정보 유출: DB 접속 정보가 담긴 설정 파일(wp-config.php, .env, env.php 등), 세션 데이터, 고객 정보 탈취
  • 결제 정보 탈취: 전자상거래 사이트 결제 페이지에 카드 정보 스키머(Magecart) 삽입
  • 내부망 공격: 웹 서버를 거점으로 DB 서버 등 내부 시스템으로 측면 이동(Lateral Movement)
  • 권한 상승: 커널 또는 로컬 취약점과 연계해 root 권한 획득

탐지 방안

1. 취약 자산 식별

운영 중인 모든 웹 서버에서 PHP 버전과 업로드 진행률 기능 활성화 여부를 확인합니다.

# PHP 버전 확인
php -v

# 업로드 진행률 기능 활성화 여부 확인 (1 또는 On 이면 추정 취약 경로 활성)
php -i | grep -i "session.upload_progress"

# 배포판 패키지 버전 확인
dpkg -l | grep php          # Debian/Ubuntu
rpm -qa | grep php          # RHEL/Rocky/Alma

2. 웹 액세스 로그 점검

공개 분석에 따르면 이 취약점은 PHP_SESSION_UPLOAD_PROGRESS 필드가 들어간 multipart POST 요청으로 유발됩니다. 파일 업로드 기능이 없는 URL이나 정적 리소스 경로로 들어온 multipart POST 요청, 특히 같은 출발지 IP에서 짧은 시간에 반복된 요청이 있는지 확인합니다. 액세스 로그에는 요청 본문이 남지 않으므로 WAF나 리버스 프록시의 본문 로깅 또는 패킷 캡처를 함께 씁니다.

# 확인 대상: /var/log/nginx/access.log, /var/log/apache2/access.log 등
# 업로드 기능이 없는 경로에 대한 multipart POST 요청 식별
# (아래는 형태를 보여 주는 예시이며 실제 확인된 공격 로그가 아닙니다)
"POST /index.php HTTP/1.1" 500 ... "python-requests/2.x"
"POST /wp-login.php HTTP/1.1" 502 ... "curl/8.x"

3. PHP-FPM / 웹 서버 에러 로그 점검

힙 UAF 익스플로잇은 메모리 배치 조작에 실패하면 워커 프로세스가 비정상 종료됩니다. 평소와 다른 빈도의 세그멘테이션 폴트나 워커 재시작 로그는 공격 시도의 지표가 될 수 있습니다.

# 확인 대상: /var/log/php-fpm/error.log, /var/log/php8.x-fpm.log
# (아래는 형태를 보여 주는 예시입니다)
WARNING: [pool www] child 12345 exited on signal 11 (SIGSEGV - core dumped) after 3.214 seconds from start
WARNING: [pool www] child 12346 exited on signal 6 (SIGABRT) after 0.812 seconds from start

# 확인 대상: /var/log/nginx/error.log
upstream prematurely closed connection while reading response header from upstream

4. 비정상 프로세스 점검

PHP 워커가 셸이나 시스템 명령을 자식 프로세스로 실행한 흔적이 있는지 확인합니다. 정상 운영 환경에서 php-fpm 워커는 셸을 실행하지 않습니다.

# php-fpm 또는 apache 워커의 자식 프로세스 확인
ps -ef --forest | grep -A3 -E "php-fpm|apache2|httpd"

# 의심 패턴: php-fpm 하위의 sh, bash, curl, wget, nc, python, perl 프로세스

5. 웹쉘 및 파일 변조 점검

웹 루트와 업로드, 캐시, 임시 디렉터리에 최근 생성되거나 변경된 PHP 파일이 있는지 확인합니다.

# 최근 7일 내 생성·변경된 PHP 파일
find /var/www -type f -name "*.php" -mtime -7 -ls

# 쓰기 가능한 디렉터리에 생성된 PHP 파일 (업로드·캐시·tmp)
find /var/www /tmp /var/tmp -type f -name "*.php" -newermt "2026-10-20"

# 웹쉘 시그니처 탐색
grep -rlE "eval\(base64_decode|system\(\$_(GET|POST|REQUEST)|passthru\(|shell_exec\(" /var/www

6. 비정상 외부 통신 확인

웹 서버에서 외부로 나가는 연결, 특히 php-fpm이나 apache 프로세스가 만든 리버스 셸이나 C2 통신이 있는지 확인합니다.

# php-fpm / 웹 서버 프로세스의 외부 연결 확인
ss -tnp | grep -E "php-fpm|apache|httpd" | grep -v ":80 \|:443 "

# 방화벽·프록시 로그에서 웹 서버 출발 아웃바운드 연결 중 비정상 포트(4444, 1337 등) 및 미등록 목적지 확인

7. 전자상거래 사이트 추가 점검

Magento, WooCommerce, Shopware 운영 조직은 결제 페이지에 스키밍 스크립트가 삽입됐는지, 관리자 계정이 비정상적으로 생성됐는지 추가로 점검합니다. 과거 PHP·플랫폼 취약점이 악용됐을 때 Magecart 계열 공격자가 수일 안에 대량 악용에 나선 전례가 있습니다.

대응 방안

1. 보안 릴리스 즉시 적용

운영 중인 PHP 버전을 모두 확인하고, PHP 공식 보안 릴리스가 나오는 즉시 지원 브랜치(8.2 이상)의 수정 버전으로 업데이트합니다. 배포판 패키지를 쓰는 경우 각 배포판의 백포트 패키지를 적용하고, Docker 이미지는 수정 버전 태그로 다시 빌드합니다. 업데이트 뒤에는 php -v로 모든 호스트의 버전이 실제로 바뀌었는지, PHP-FPM과 웹 서버가 재시작됐는지 확인합니다.

2. 패치 전 임시 완화 조치

패치를 적용하기 전까지 업로드 진행률 기능을 끕니다. 파일 업로드는 그대로 동작하고 진행률 표시만 멈춥니다. 다만 이 조치는 추정된 두 경로 가운데 업로드 진행률 핸들러 쪽 하나만 막는 것으로 보고됐습니다. 패치를 대신할 수 없습니다.

# php.ini (서버 전체 적용 후 PHP-FPM 또는 Apache 재시작)
session.upload_progress.enabled = 0

# .user.ini (PHP-FPM/CGI, user_ini.cache_ttl 기본 300초 후 반영)
session.upload_progress.enabled = 0

# .htaccess (mod_php, AllowOverride Options 필요)
php_flag session.upload_progress.enabled off

3. WAF·리버스 프록시 차단

WAF나 리버스 프록시에서 PHP_SESSION_UPLOAD_PROGRESS 필드명이 들어간 multipart 요청을 차단하거나, 업로드 기능이 없는 경로로 들어오는 multipart POST 요청을 차단합니다. 적용 전에 정상 서비스가 진행률 추적 기능을 쓰는지 확인합니다.

4. 지원 종료 버전

PHP 8.1 이하 등 지원이 종료된 버전에는 공식 패치가 나오지 않습니다. 임시 완화 조치를 바로 적용하고 지원 브랜치로 업그레이드할 일정을 세웁니다. 업그레이드가 어려우면 호스팅 사업자나 배포판 벤더에 백포트 패치를 제공하는지 확인합니다.

5. 침해 여부 점검

패치 전에 취약점 정보가 유출돼 공격 코드가 빠르게 나올 수 있습니다. 패치 적용과 별개로 위 탐지 방안에 따라 PHP-FPM 비정상 종료 로그, 웹쉘 존재 여부, 비정상 외부 통신을 반드시 점검하시기 바랍니다.

참고 자료

둘러보기

더보기

[로그프레소 CTI] OSINT를 활용한 ARTEX 캠페인 추가 분석 - 공격 집단 실체 검증

CrowdStrike가 10월 7일 국내 금융권을 노린 ARTEX 캠페인 분석을 공개한 데 이어, 로그프레소는 텔레그램, GitHub 커밋 기록, 인포스틸러 로그를 교차 분석해 공격 집단의 실체를 추가로 검증했습니다. 분석 결과 CrowdStrike가 지목한 텔레그램 계정은 DDoS 대행 조직 GodNet/VITAS의 운영진으로 활동했으며, 같은 조직 구성원의 인포스틸러 로그에서 클라우드 사업자 가입 정보와 대조할 수 있는 이메일, 도메인, M365 테넌트를 확인했습니다. 이번 공격이 개인의 단독 행위라기보다 조직을 배경으로 이루어졌을 가능성을 보여주는 결과입니다.

2026-10-09