PHP 개발팀은 2026년 10월 21일(한국 시각 21일 밤 11시 무렵) PHP 코어의 원격 코드 실행 취약점 2건, CVE-2026-109618과 CVE-2026-109619(통칭 PHP2Shell)를 고친 8.5.12·8.4.27·8.3.36·8.2.35를 배포했다. 웹 요청을 처리하는 모든 PHP가 대상이고 로그인 없이 공격할 수 있다. 오늘 할 일은 네 가지다. 웹 서비스가 실제로 쓰는 PHP 버전을 확인하고, 재시작 전에 흔적을 짧게 점검하며 로그를 남기고, 수정 버전 설치 뒤 PHP를 실행하는 서비스를 모두 재시작하고, 10월 17일 이후 로그를 끝까지 점검한다.

CVE 번호는 배포 하루 전에 유출됐고, AWS는 공개 4일 전인 10월 17일에 공격 시도를 관측했다. 과학기술정보통신부는 10월 22일 12:00부로 민간 분야 사이버위기 경보를 '관심'에서 '주의'로 올렸다. 22일 낮 기준 국내 접수 침해 사례는 확인되지 않았다(연합뉴스 보도). 워드프레스·라라벨 업데이트로는 PHP 런타임이 바뀌지 않는다.

한눈에 보기

항목 내용
이름·CVE PHP2Shell. CVE-2026-109618(메모리 부족 처리 중 상태 손상), CVE-2026-109619(해제된 메모리를 가리키는 낡은 전역 상태)
원인 한 줄 요청 처리가 오류로 끊길 때 정리가 덜 된 내부 메모리를 PHP가 다시 써서, 공격자가 그 메모리를 조작해 코드를 실행한다
영향 버전 8.2.35 미만 8.2.x, 8.3.36 미만 8.3.x, 8.4.27 미만 8.4.x, 8.5.12 미만 8.5.x(PHP 공식). 8.1 이하는 공식 지원이 끝나 수정 릴리스가 없을 뿐 영향 범위로 봐야 한다. PHP 보안팀이 7.4·8.0·8.1용 소스 백포트를 냈고, 발견자 Wiz는 5.4까지 지난 10년의 모든 버전이 둘 중 하나 이상에 영향을 받는다고 밝혔다
수정 버전 8.5.12, 8.4.27, 8.3.36, 8.2.35. 배포판 패키지는 옛 번호를 유지한 채 수정(백포트)되기도 한다
심각도 CVSS 4.0 9.2(PHP 평가, 치명적). NVD 자체 평가는 CVSS 3.1 9.8
공격 조건 인증과 사용자 동작 없이 네트워크로 공격한다. 워커 상태 같은 조건이 붙어(AC:H, AT:P) 여러 번 시도해야 할 수 있다. 위험이 가장 큰 곳은 앱 코드 실행 전 공격이 시연된 Apache mod_php다
실제 공격 정황 AWS가 10월 17일 첫 시도를 관측했고 공개 뒤 '광범위한 실제 악용'을 발표했다. 성공한 침해 사례를 밝힌 1차 자료는 아직 없다. CISA KEV(10월 21일 판)에는 없다
국내 대응 KISA 보호나라 10월 21일 업데이트 권고, 22일 기업 보안 대응 수칙. 과기정통부 22일 12:00 사이버위기 경보 '주의' 상향. 개인정보위 phpMyAdmin 등 DB 관리도구 노출 점검 당부
지금 할 일 실제 동작 서버 기준 PHP 목록 작성 → 재시작 전 흔적 점검·로그 보존 → 인터넷 공개 서버부터 수정 버전 설치·재시작 → 10월 17일 이후 로그·웹셸 점검 → 노출됐던 서버의 인증정보 교체

무엇이 문제인가

PHP는 요청을 처리하다 메모리 한도(memory_limit)를 넘으면 longjmp()로 처리를 바로 끊는다. CVE-2026-109618은 이 중단이 내부 데이터가 반쯤만 초기화된 순간에 일어나면, 요청 정리 단계가 덜 채워진 데이터를 정상 값으로 보고 쓰는 문제다. 공격자는 빈 업로드 필드나 헤더를 잔뜩 넣은 multipart 요청으로 한도를 일부러 넘긴다. 발견자 Calif의 분석으로는 기본 메모리 128MiB를 넘기면서도 요청 본문은 기본 post_max_size 8MiB 아래로 맞출 수 있어, 크기 제한만으로는 막히지 않는다.

SAPI(웹서버와 PHP를 잇는 방식)에 따라 위험이 다르다. Apache mod_php는 요청 시작이 실패해도 정리 절차를 항상 실행하므로, 애플리케이션 코드가 돌기 전 자동 본문 파싱만으로 취약 상태에 닿는다. PHP 공식 권고(GHSA)는 기본 설정의 mod_php에서 인증 없는 원격 코드 실행을 검증했다. PHP-FPM은 이 경로는 막히지만, PHP 재단은 FPM에서도 애플리케이션 수준 경로로 원격 코드 실행을 확인했다고 밝혔다(GHSA 기준 FPM용 완전한 익스플로잇은 미시연).

CVE-2026-109619는 요청 메모리를 잠시 가리키는 PHP 전역 상태가 요청이 끝난 뒤에도 남는 문제다. 파싱 실패, require 실패, 실행 시간 초과, 메모리 부족 같은 치명적 오류로 정리가 건너뛰어지면 해제된 메모리를 가리키는 값이 남고, 같은 워커의 다음 요청이 그 값을 읽는다(해제 후 사용). 확인된 경로 하나는 기본으로 켜진 세션 업로드 진행 기능(session.upload_progress)이고, session_start()를 부르지 않는 앱에서도 동작한다. 이 경로의 원격 코드 실행은 mod_php와 FPM에서 모두 검증됐다. error_reporting을 바꾸거나 display_errors를 꺼도 막히지 않는다.

확인된 영향은 웹 워커 계정 권한의 원격 코드 실행이다. KISA는 공격에 성공하면 웹셸 설치, 고객정보 유출, 홈페이지 변조, 내부망 침투가 가능하다고 밝혔다. Wiz는 WordPress·Drupal·Joomla 최신 컨테이너 이미지에서 인증 없는 원격 코드 실행을, 별도로 프로세스 메모리 속 비밀번호·토큰·API 키를 PHPSESSID 응답 쿠키로 빼내는 공격을 시연했다. 앱을 안전하게 짰어도 PHP 자체의 결함이라 영향을 받는다(과기정통부).

문제의 첫 징후는 2024년 외부 보안 감사 결과를 고치던 중 나왔지만 수정이 미뤄졌다(PHP 재단은 '구조적 실패'라고 인정). 2026년 8월 11일 Calif가 원격 코드 실행으로 보고했고 같은 날 오픈AI가 같은 원인을 따로 보고했으며, 8월 24일 Wiz가 추가 공격 경로를 보고했다. Wiz는 AI로 찾았다고 밝혔다. 안랩은 취약 버전 PHP가 설치된 것으로 추정되는 국내 호스트를 약 11만 건(세계 6번째)으로 집계했다(업체 집계·연합뉴스 보도, 패치 전 추정치).

우리 서버가 해당되는지 확인하는 법

기준은 '설치된 PHP'가 아니라 '지금 웹 요청을 처리하는 PHP'다. KISA는 php -v의 CLI 버전과 웹 서비스의 실제 버전이 다를 수 있다고 경고했다. 목록은 자산 대장이 아니라 실제 동작 서버 기준으로 만들고 외주·방치·테스트 서버, 관리자 페이지, 장비 관리 화면, 외부 컨테이너 이미지까지 넣는다.

환경 확인 방법 판단 기준
리눅스 직접 설치·소스 빌드 php -v, php-fpm -v(배포판에 따라 php-fpm8.3 -v), Apache는 apachectl -M에서 php 모듈 로드 여부 8.5.12, 8.4.27, 8.3.36, 8.2.35 이상. 8.1 이하는 공식 릴리스가 없다
Debian·Ubuntu 패키지 dpkg -l 'php*'로 설치 버전 확인, 설치본 변경 이력은 zcat /usr/share/doc/php8.3-common/changelog.Debian.gz | grep CVE-2026-109618(apt changelog는 설치 후보의 이력이라 판정에 쓰지 않는다) 배포판 공지의 수정 패키지 이상. 예: Ubuntu 24.04 php8.3 8.3.6-0ubuntu0.24.04.13, 22.04 php8.1 8.1.2-1ubuntu2.28, Debian 12 php8.2 8.2.35-1~deb12u1, Debian 13 php8.4 8.4.27-1~deb13u1
RHEL·Rocky·Alma 계열 rpm -q --changelog php-common에서 CVE 번호 검색, dnf updateinfo list --all --cve CVE-2026-109618(설치된 수정은 i 표시) Red Hat 공지 기준. RHEL 9.8 기본 php는 8.0.30-8.el9_8.1에서 백포트 수정, RHEL 9 php:8.4 모듈은 10월 22일 현재 수정 전
Alpine apk info -v의 php 패키지 3.24 기준 php83 8.3.36-r0, php84 8.4.27-r0, php85 8.5.12-r0
Docker 컨테이너 docker exec 컨테이너이름 php -v, 이미지 태그와 빌드 날짜 공식 php 이미지 8.5.12·8.4.27·8.3.36·8.2.35 태그. php:8.1·7.4 태그는 갱신이 없다
Windows(IIS 등) php.exe -v, IIS FastCGI 설정의 php-cgi.exe 경로 php.net Windows 바이너리의 수정 버전
호스팅·관리형 관리 화면의 PHP 버전, 업체 공지 업체의 패치·재시작 확인

명령은 일반 점검, 버전 기준은 php.net·배포판 공지·Docker Hub 값이다.

  • 배포판 백포트 주의: Ubuntu 24.04의 8.3.6이나 RHEL 9의 8.0.30처럼 번호가 낮아 보여도 수정된 패키지가 있다. 버전 문자열이 아니라 배포판 공지의 정확한 패키지 버전이나 변경 이력의 CVE 번호로 판단한다.
  • phpinfo 페이지 주의: 웹 루트의 phpinfo()로 실제 SAPI와 버전을 볼 수 있지만 설정·환경 변수가 드러나니 내부 IP만 허용하고 즉시 지운다(일반 점검).
  • X-Powered-By는 참고만: curl -sI https://도메인/으로 보이는 버전은 노출 서버 찾기에만 쓴다. 백포트 패키지는 옛 번호를 보이고 expose_php=0이면 안 나온다(일반 점검).
  • 재시작 확인: PHP-FPM은 실제 쓰는 유닛(예: systemctl status php8.3-fpm), Apache는 systemctl status apache2(RHEL 계열은 httpd)로 각각 조회해 시작 시각이 수정 패키지 설치 시각보다 늦은지 본다(일반 점검).

공격 정황과 타임라인

시각은 UTC, 괄호 안은 한국 시각(KST)이다.

  • 10-17: AWS 허니팟(MadPot)에 첫 공격 시도. 공개 4일 전, 상용 익명화 네트워크 IP였다.
  • 10-20 15:00(10-21 00:00): 두 CVE 번호가 잘못된 CVSS 10.0과 함께 퍼졌다(기술 세부는 미유출).
  • 10-20 19:30(10-21 04:30): PHP가 사전 공지를 게시하고 배포를 22일에서 21일 14:00으로 당겼다. 20:00(05:00) 무렵에는 보고자 Calif가 개념증명(PoC) 동작 영상을 실수로 올려 PoC 개발이 빨라졌다(PHP 재단).
  • 10-21 02:00 무렵(11:00): AWS가 최초 PoC 여러 개를 확인했다. 03:02(12:02) Cloudflare가 무료·유료 WAF에 방어 규칙을 기본 적용했다.
  • 10-21 13:34~14:00(22:34~23:00): GHSA 권고 게시(13:34)와 수정 버전 배포(PHP 재단 기준 14:00).
  • 10-21: 미국 CISA가 즉시 패치를 촉구하는 경보를 냈다(게시 시점 악용 미관측). KISA 보호나라가 업데이트 권고를 게시했다.
  • 10-21 22:36 무렵(10-22 07:36): AWS가 위협 분석 글에서 엠바고 해제 몇 시간 안에 PoC가 더 나와 센서에 바로 쓰였고 'PHP2Shell은 광범위하게 실제 악용 중'이라고 발표했다.
  • 10-22(KST): KISA 기업 보안 대응 수칙 게시, 과기정통부 12:00부 '주의' 경보, 개인정보위 유출 예방조치 당부.

조사 시작점은 공개일이 아니다. AWS는 최소 10월 17일부터, KISA는 최소 10월 20일(정보 유출일) 이후 기록 전체를 보라고 했으니 넓은 쪽인 17일부터 본다. 인터넷에 도는 PoC는 악성코드를 숨긴 가짜가 많으니 취약 여부는 PoC 실행이 아니라 버전 확인과 기록 점검으로 판단한다(KISA).

대응 순서

오늘

  1. 보안·인프라 담당: PHP 목록을 만들고 인터넷 공개 서버를 맨 위에 둔다. SAPI, 버전, 패키지 출처, 담당자를 적는다. 밖에서 보이는 서버를 찾는 방법은 ASM 자가점검 5단계에 있다.
  2. 인프라 담당: 재시작 전에 5분 점검부터 한다. 웹 계정이 띄운 셸 프로세스와 10월 17일 이후 새로 생긴 PHP 파일을 본다(명령은 '흔적 점검'). 명령 출력과 웹서버·PHP 로그는 파일로 남긴다. 이상이 보이면 재시작 말고 7번으로 간다. 재시작하면 메모리의 흔적이 사라진다(KISA).
  3. 인프라 담당: 수정 버전을 설치하고 PHP를 실행하는 서비스를 모두 재시작한다. PHP-FPM, Apache, 장시간 실행 PHP 워커까지 재시작한다. 컨테이너는 수정된 베이스 이미지로 다시 빌드해 교체한다. 수정 버전은 메모리가 더 높은 2차 한도에 닿으면 프로세스를 바로 끝내므로 메모리를 많이 쓰는 기능을 확인한다(PHP 공식, 발견자 안내).
  4. 패치가 오늘 안 되는 서버: 임시 조치를 건다. 공격을 완전히 막지는 못한다. php.ini나 FPM 풀 설정에 session.upload_progress.enabled=0, 애플리케이션이 못 바꾸게 php_admin_value로 memory_limit=-1, 업로드가 없으면 post_max_size=8M(있으면 32M, upload_max_filesize는 그보다 작게), PHP 8.5는 fatal_error_backtraces=0을 넣고 모든 워커를 재시작한다. memory_limit=-1을 쓰면 컨테이너나 cgroup v2 memory.max 같은 운영체제 한도로 서버 전체가 멈추지 않게 한다. ini_set()이나 FPM .user.ini로 넣지 않는다. 메모리 한도를 RLIMIT_AS·RLIMIT_DATA로 대신하면 취약 경로를 부르니 쓰지 않는다(PHP 공식).
  5. 웹서버·WAF 담당: PHP 앞단에서 줄인다. Content-Length가 없는 요청까지 포함해 본문 크기를 제한하고, 업로드가 필요 없는 서비스는 multipart 요청을 막는다(PHP 공식). AWS는 PHP_SESSION_UPLOAD_PROGRESS 필드가 든 multipart POST 차단 규칙을 안내하며, 업로드를 쓰는 서비스에서는 위험을 줄일 뿐이라고 했다. 새 규칙은 Count 모드로 오탐을 본 뒤 차단하고, Cloudflare 유료 플랜은 관리형 규칙셋 차단 모드를 확인한다.
  6. 8.1 이하 서버: 백포트, 차단, 이전 중 하나를 오늘 정한다. 배포판·LTS 업체 패치가 있으면 적용하고, 소스 빌드라면 PHP 보안팀의 7.4·8.0·8.1용 소스 백포트를 쓴다. 둘 다 없고 임시 조치도 어려우면 외부 접속을 막거나 서비스를 잠시 내린다(KISA, CISA).
  7. 침해 대응 담당: 흔적이 보이면 KISA 순서대로 한다. 서버를 끄거나 재시작하지 말고 외부 접속만 차단 → 보호나라에 침해사고 신고 → 웹서버·PHP 로그, 실행 중 프로그램 목록, 네트워크 연결 정보 확보 → 업데이트·재시작, 웹셸 제거, 인증정보 교체. 첫 1시간 역할 분담은 침해사고 1시간 골든타임 액션북을 쓴다.

이번 주

  1. 보안관제: 10월 17일 이후 로그를 '흔적 점검' 표대로 본다. 이상이 없으면 '지표 미발견'으로 남긴다.
  2. 인프라·개발 담당: 인증정보를 바꾼다. KISA는 업데이트 전까지 노출됐던 서버의 DB 비밀번호, 외부 연동 키, 관리자 비밀번호 교체를 권장했다(침해 흔적이 있으면 반드시).
  3. 개인정보 보호 담당: DB 접근 경로를 줄인다. 개인정보위 당부대로 phpMyAdmin 같은 DB 관리도구의 인터넷 직접 접근을 막고, 웹 서비스 계정의 개인정보 DB 권한을 최소로 줄이고, 대량 조회·반출 같은 비정상 접근을 점검한다.
  4. 운영 담당: 끌 수 있는 기능은 패치 뒤에도 끈다. PHP 공식 권고는 업로드 진행률을 안 쓰면 패치 뒤에도 끄는 편이 신중하다고 했다.

이번 달

  1. IT 책임자: 8.1 이하 서버의 이전 일정을 확정한다. PHP 8.2도 2026년 12월 31일 보안 지원이 끝나 KISA는 8.3 이상 전환을 권장했다.
  2. 보안 책임자: 인터넷 접점 자산의 패치 기한을 '시간' 단위로 바꾼다. AWS는 치명적 취약점에 7일·30일 기한은 맞지 않는다고 했다. 기준 정하는 법은 제로데이 패치 우선순위에 있다.
  3. 인프라 담당: 웹 워커가 할 수 있는 일을 줄인다. SELinux·AppArmor로 워커 권한과 다른 프로그램 실행을 제한하고(발견자 권고), 웹 서버의 바깥 연결은 필요한 곳만 허용한다(일반 점검).

흔적 점검

지표 하나로 침해를 확정할 수 없고, 없다고 안전한 것도 아니다. 취약 경로가 애플리케이션 아래에서 돌아 앱 로그에는 맥락이 거의 없으니 웹서버, PHP-FPM, 프록시, WAF 로그를 본다(발견자 안내).

확인할 곳 볼 내용 근거
WAF·요청 본문 기록 PHP_SESSION_UPLOAD_PROGRESS 필드가 든 multipart POST AWS
웹서버 접근 로그 이상한 multipart 요청 직후 반복되는 HTTP 500, PHP 페이지로 온 비정상적으로 큰 요청 발견자, KISA
응답·프록시 로그 예상보다 크거나 깨진 PHPSESSID 응답 쿠키 발견자
PHP-FPM·Apache 오류 로그 메모리 한도 오류, 원인 모를 워커 크래시·재시작·segfault, 스크립트 실행 전 반복 경고, Maximum execution time exceeded 발견자, PHP 공식, KISA
프로세스 PHP 워커가 sh·bash나 다운로드 도구를 실행 CISA, KISA
파일 웹 루트·업로드·임시 폴더의 새 PHP 파일, 홈페이지·결제 페이지에 추가된 외부 스크립트 KISA
네트워크 웹 서버에서 알 수 없는 외부 주소로 나간 새 연결 KISA
접근 로그의 IP 103.216.220.92, 31.223.184.166, 37.19.200.5, 134.209.159.64, 103.114.163.188, 95.217.98.37 AWS(공유 익명화 인프라라 차단 말고 조사용. 걸리면 전후 기록을 본다)

명령은 일반 점검이고 경로는 설정마다 다르다.

  • 오류 로그: zgrep -E "Allowed memory size|exited on signal|Segmentation fault" /var/log/php*-fpm.log* /var/log/apache2/error.log* /var/log/nginx/error.log*. 순환·압축된 로그까지 보고, 없는 경로라는 오류가 나면 실제 로그 경로로 고쳐 다시 본다. 평소에도 나오는 메시지이니 10월 17일 이후 급증했는지, multipart 요청과 시각이 겹치는지 본다.
  • 접근 로그의 500: combined 형식이면 zcat -f /var/log/nginx/access.log* | awk '$9 == 500'로 순환 로그까지 뽑아 IP·시각별로 모은다. 요청 본문은 접근 로그에 없으니 PHP_SESSION_UPLOAD_PROGRESS는 WAF 로그에서 찾는다.
  • 새 PHP 파일: find /var/www /tmp \( -name "*.php" -o -name "*.phtml" -o -name "*.phar" \) -newerct 2026-10-17 -ls(업로드 폴더 포함). 수정 시각(mtime)은 위조될 수 있어 ctime으로 찾는다.
  • 웹 계정 프로세스와 연결: ps -u www-data -o pid,ppid,lstart,cmd(RHEL 계열은 apache), ss -tnp에서 php-fpm·httpd의 바깥 연결.

호스팅·워드프레스·외주 운영이라면

공유 웹호스팅은 PHP를 업체가 관리하므로, 과기정통부 안내대로 업체에 보안 업데이트 적용 여부를 확인한다. 보도에 따르면 카페24는 패치 적용 뒤 고객에게 공지했고, 가비아는 22일 새벽 패치 작업에 들어가 영향 버전 전반에 조치를 마쳤고 지원이 끝난 버전에는 백포트 패치나 완화 조치를 적용했다(연합뉴스). 업체·외주 운영사에는 아래를 서면으로 요청하고 회신 기한을 정한다.

  • 우리 계정·서버의 PHP 버전, 수정 반영 일시, 수정 뒤 재시작 여부
  • 8.1 이하라면 적용한 백포트·완화 조치와 상위 버전 전환 일정
  • 10월 17일 이후 우리 사이트 로그의 이상 징후 점검 결과
  • phpMyAdmin 같은 DB 관리도구의 인터넷 노출 여부, 장비·솔루션 제조사의 조치 계획

관리 화면에서 PHP 버전을 고를 수 있으면 8.3 이상을 고르되 테마·플러그인 동작부터 시험한다. 개인정보위도 외주·수탁·호스팅 환경의 PHP 확인을 당부했다.

자가점검

'아니오'가 나온 항목부터 대응 순서로 돌아간다.

1. 인터넷에 공개된 PHP 서버 목록이 실제 동작 서버 기준으로 있는가

외주·방치 사이트, 장비 화면이 자주 빠진다.

2. 서버마다 웹 서비스가 쓰는 PHP 버전과 SAPI를 확인했는가

CLI의 php -v는 FPM이나 Apache 모듈 버전과 다를 수 있다.

3. 배포판 패키지는 번호가 아니라 보안 공지·변경 이력으로 판정했는가

백포트 패키지는 옛 번호를 유지한다.

4. 수정 뒤 PHP-FPM, Apache, 장시간 실행 워커를 모두 재시작했는가

재시작 전에는 메모리의 옛 버전이 요청을 처리한다.

5. 컨테이너는 수정된 이미지로 다시 빌드해 교체했는가

공식 php:8.1·7.4 태그는 갱신되지 않았다.

6. 8.1 이하 서버마다 백포트, 차단, 이전 중 하나가 정해져 있는가

PHP 프로젝트는 8.1 이하 공식 릴리스를 내지 않는다.

7. 10월 17일 이후 로그와 웹 루트를 점검하고 결과를 기록했는가

AWS가 첫 공격 시도를 본 날이 10월 17일이다.

8. 업데이트 전 노출됐던 서버의 DB 비밀번호와 API 키를 바꿨는가

이번 취약점은 서버 메모리의 인증정보를 빼낼 수 있다.

밖에서 보이는 PHP 서버부터 무료로 확인하기

회사 밖에서 우리 PHP 서버가 어떻게 보이는지 먼저 알고 싶다면 보안 전문 기업 SENTRIX의 PHP2Shell 노출 무료 진단 신청 페이지에서 회사 도메인 이메일로 신청한다. 외부에서 보이는 PHP 서버와 버전 노출 여부를 공격 시도 없이 확인해 1장으로 알려 주며, 신청한 이메일과 같은 도메인만 확인한다. 밖에서 보이는 정보만 보므로 서버 안의 패치·재시작 여부를 대신 확인하지는 않는다. 새로 생기는 PHP 서버까지 계속 챙기려면 SENTRIX ASM이 밖에서 보이는 서버·서브도메인·관리 화면을 찾아 담당자와 조치 순서까지 상시 관리한다. 외부 노출 범위부터 상의하려면 외부 노출 자산 진단 문의하기로 연락한다.

참고 자료

우리 회사 PHP 서버 노출 범위 상담하기

보안 실무 10년 전문가가 기업 환경에 맞는 방안을 제시합니다.