기획10월 21일
PHP 취약점 PHP2Shell 정리
PHP가 10월 21일 인증 없이 서버에서 코드를 실행할 수 있는 결함 두 개(CVE-2026-109618·109619)를 고쳤다. 앱이 아니라 PHP 자체의 결함이라 워드프레스 같은 앱을 업데이트해도 막히지 않는다. 공격 시도는 공개 전부터 있었고, 정부는 22일 민간 사이버위기 경보를 '주의'로 올렸다. 무엇이 문제였고, 어느 판으로 올려야 하며, 당장 못 올리면 무엇을 할 수 있는지 정리했다.
먼저 요점만
- 10월 21일, 웹사이트의 앱을 돌리는 PHP에서 결함 두 개가 공개됐다. 인증 없이 서버에서 코드를 실행할 수 있는 결함이다. 앱이 아니라 PHP 자체에 있어서, 워드프레스 같은 앱만 업데이트해서는 막히지 않는다.
- PHP로 사이트를 운영한다면 PHP를 새 판으로 올려야 한다. 고친 판은 8.5.12, 8.4.27, 8.3.36, 8.2.35다. 웹호스팅을 쓴다면 호스팅 업체가 올렸는지 확인하면 된다.
- 공격 시도는 공개 전부터 있었다. 아마존은 공개 나흘 전인 17일에 시도를 잡았고, 과학기술정보통신부는 22일 민간 분야 사이버위기 경보를 ‘주의’로 올렸다.
영향 범위
웹 요청을 받는 PHP는 실행 방식과 상관없이 영향을 받는다. 웹서버가 PHP를 불러 쓰는 방식은 아파치 모듈(mod_php), PHP-FPM 등 여럿이지만 모두 대상이며, PHP 공지에 따르면 그 가운데 가장 위험한 것은 아파치 모듈이다. 인증 없는 요청 하나로 앱 코드가 돌기도 전에 공격이 일어나는 것이 시연됐기 때문이다. PHP 작업 프로세스를 따로 띄워 관리하는 PHP-FPM에서도 PHP 재단과 PHP 보안팀이 서버에서 코드를 실행하는 공격을 확인했다. 다만 결함 109618은 앱이 돌기 전부터 공격하는 방식이 FPM에서 끝까지 시연되지 않았다.
워드프레스 같은 앱을 고쳐서는 막히지 않는다. 결함이 앱이 아니라 그 아래 PHP에 있기 때문이고, 워드프레스도 이번 일로는 워드프레스 업데이트가 필요하지도, 계획되지도 않았다며 PHP를 올리라고 했다. 실제로 Wiz는 워드프레스·드루팔·줌라 최신 판에서 로그인 없이 서버 코드를 실행했고, Calif도 미디어위키, 마젠토 등 여러 앱에서 같은 위험을 확인했다.
PHP가 쓰이는 곳은 넓다. PHP 재단은 정부 서비스, 온라인 상점, 은행, 언론사 사이트를 포함해 웹의 큰 몫이 PHP로 돌아간다고 했고, 국내에서도 보안업체 안랩이 조사한 취약 추정 서버가 약 11만 대로 세계에서 여섯 번째로 많다고 세계일보가 전했다.
영향을 받는 판도 공식 기록보다 넓게 봐야 한다. PHP 보안 권고는 지원 중인 8.2~8.5만 영향 판으로 적었지만, Wiz와 Calif는 PHP 5.4부터 영향을 받는다고 했고 PHP 보안팀도 지원이 끝난 7.4·8.0·8.1용 최소 수정본을 따로 내놓았다.
업데이트와 임시 조치
먼저 사이트를 누가 운영하는지 본다. 웹호스팅을 쓰는 사이트는 호스팅 업체가 PHP를 올려 준다. 국내에서는 카페24가 21일 밤 11시 30분부터 PHP 8.2 이상에 공식 패치를 적용했고, 가비아는 22일 0시부터 3시까지 패치를 적용한 뒤 웹호스팅 고객은 따로 할 일이 없다고 알렸다. 다만 서버호스팅이나 클라우드처럼 서버를 직접 운영한다면 PHP도 직접 올려야 한다.
직접 올린다면 지금 쓰는 판부터 확인한다. 워드프레스는 관리 화면의 ‘도구 → 사이트 건강 → 정보 → 서버’에서 PHP 판을 보여 주고, 많은 호스팅 업체도 관리 화면에 보여 준다. 확인한 뒤에는 아래 표에서 쓰는 판에 맞는 새 판으로 올리고 PHP 프로세스를 다시 띄운다. 리눅스 배포판과 장기 지원 업체는 패치를 미리 받았으니 그쪽 업데이트를 확인하면 되고, 컨테이너로 배포했다면 고친 PHP 이미지로 다시 빌드해 배포해야 한다.
| 쓰는 판 | 올릴 판 |
|---|---|
| 8.5 | 8.5.12 |
| 8.4 | 8.4.27 |
| 8.3 | 8.3.36 |
| 8.2 | 8.2.35 |
| 8.1 이하 | 공식 판 없음 |
8.2는 2026년 12월 31일 보안 지원이 끝난다. 지원 기간은 PHP의 지원 판과 지원 종료 표(10월 22일 조회).
8.1 이하는 PHP 프로젝트의 업데이트를 받지 못한다. 그래서 배포판이나 장기 지원 업체가 내는 백포트(새 수정을 옛 판에 옮긴 것)를 쓰거나 지원 판으로 올려야 하는데, 보안팀이 GitHub에 올린 7.4·8.0·8.1용 수정본은 번호가 붙은 정식 판이 아니다. 미국 사이버보안·인프라보안청(CISA)은 당장 올릴 수 없거나 8.1 이하를 쓰는 곳에 PHP 시스템을 오프라인으로 돌리라고 권했다.
올린 뒤에는 기록을 점검한다. 이미 침해됐다면 새 판으로 올려도 흔적은 그대로 남기 때문이다. 아마존은 노출됐던 서버라면 최소 17일부터 웹서버 기록과, 예상치 못한 프로세스 실행이나 파일 변경을 살피라고 했고, KISA는 정보가 샌 20일 이후 기록 전체를, 가능하면 그 이전까지 점검하라고 했다.
당장 올릴 수 없을 때의 설정
이 설정은 서버 관리자가 바꾸며, 확인된 공격 경로만 막을 뿐 설치를 안전하게 만들지는 않는다. PHP 공지에 따르면 설정은 요청을 처리하기 전에 적용되는 php.ini나 FPM 풀, 웹서버 설정에서 바꾸고 실행 중인 PHP 프로세스를 모두 다시 띄워야 하며, 앱 코드의 ini_set()이나 FPM .user.ini로는 효과가 없다.
- 업로드 진행 상황 기능 끄기:
session.upload_progress.enabled=0으로 둔다. 이 기능은 기본값이 켜짐이며, 끄면 109619의 확인된 세션 경로를 막는다. - PHP 8.5는
fatal_error_backtraces=0: 치명적 오류 기록 경로를 막는다. - 메모리 한도 다루기:
memory_limit=-1을 앱이 덮어쓸 수 없게 걸고 요청 크기(post_max_size)를 낮춘다. 109618 쪽 경로를 줄인다. 다만-1은 PHP의 메모리 한도를 없애는 값이라 서버 메모리가 바닥날 위험이 커진다. 그래서 웹서버나 프록시에서도 요청 크기를 제한하고 컨테이너 메모리 한도를 함께 둔다. - 오류 표시를 숨기는 것은 효과가 없다.
display_errors나@로 경고를 감춰도 막히지 않는다.
웹 방화벽
웹 방화벽(WAF)은 서버 앞에서 수상한 요청을 걸러 내는 장치로, 패치할 시간을 벌어 준다. 업체마다 적용 방식이 달랐다.
| 업체 | 적용 방식 | 고객이 확인할 일 |
|---|---|---|
| 클라우드플레어 | 21일 오전 3시 2분(협정 세계시)부터 무료 요금제까지 자동 | 유료 요금제는 규칙이 차단 모드인지 |
| 버셀 | 모든 프로젝트에 자동 | 버셀을 거치지 않는 직접 요청은 막지 못한다 |
| 구글 클라우드 | 관리형 규칙을 쓰는 고객에게 자동 | 파일 업로드·원격 파일 포함 범주를 켜고, 시험한 뒤 차단 모드로 |
| 패스틀리 | 고객이 직접 켠다 | 가상 패치 규칙 켜기 |
| 아마존웹서비스(AWS) | 고객이 직접 규칙을 만든다 | 두 결함 가운데 하나는 웹 방화벽으로 거의 막지 못한다 |
출처: Cloudflare, Vercel, Google Cloud, Fastly, AWS.
공격 시도
공격 시도는 공개 나흘 전부터 있었다. 아마존은 공격자를 끌어들이려 둔 미끼 서버(허니팟)에서 17일 시도를 잡았다. 시도는 상업용 익명화 네트워크의 주소에서 들어왔고 공격자가 공개 전에 어떻게 정보를 얻었는지는 알 수 없다고 했는데, 공개 뒤에는 몇 시간 만에 시연 코드가 더 나와 지금은 널리 악용되고 있다고 평가했다. 클라우드플레어도 정보가 샌 뒤 고객을 노린 공격 트래픽을 봤고, 공격자가 방어 규칙을 피하려고 요청을 바꿔 가며 보내는 것도 관측했다.
다만 기관 발표로 실제 침해가 확인된 것은 아직 없다. CISA는 21일 경보를 낼 때까지 악용을 관측하지 못했고, KISA는 22일 해외 보안업체를 중심으로 공격 시도가 보고되고 있다고 했다. PHP 재단도 유출 뒤 나돈 시연 코드 가운데 공개 시점까지 작동하는 것은 확인하지 못했다.
해설 공격 시도가 공개 전부터 있었다는 것은 공개일을 기준으로 안심할 수 없다는 뜻이다. 패치가 공개되면 무엇을 고쳤는지 거꾸로 읽어 공격을 만들 수 있고, 아마존은 그 시간이 몇 시간으로 줄었다고 봤다. 그리고 앱이 아니라 PHP 자체를 올려야 하므로, 서버를 직접 운영하지 않는 사이트는 호스팅 업체가 언제 올리는지에 달려 있다.
국내 대응
과학기술정보통신부는 22일 낮 12시 민간 분야 사이버위기 경보를 ‘관심’에서 ‘주의’로 올렸다. 그보다 하루 앞선 21일 한국인터넷진흥원(KISA)은 보호나라에 보안 업데이트 권고를 올리고 정보보호최고책임자(CISO) 신고 기업과 주요정보통신기반시설, 웹호스팅사 등에 긴급 전파했다. 22일에는 기업 대응 수칙도 따로 내, 적용할 패치가 없고 임시 조치도 어려우면 외부 접속 차단이나 서비스 일시 중단을 검토하라고 했다.
결함의 원리
문제는 메모리가 바닥나는 순간에 생긴다. PHP는 웹 요청이 들어올 때마다 그 요청에 쓸 메모리를 잡았다가 끝나면 치우는데, 요청이 메모리 한도(memory_limit)를 넘기거나 치명적 오류가 나면 처리를 그 자리에서 끊는다. 이때 미처 치우지 못한 흔적이 남고, 두 결함은 이 흔적이 어디서 쓰이느냐로 갈린다.
- CVE-2026-109618: 요청 데이터가 반쯤 만들어진 채 메모리가 바닥나면, 그 요청을 마무리하는 단계가 덜 된 데이터를 멀쩡한 것으로 읽는다.
- CVE-2026-109619: 처리가 끊긴 뒤에도 이미 돌려준 메모리를 가리키는 내부 상태가 남는다. 서버의 PHP 작업 프로세스는 요청을 차례로 받아 처리하므로, 같은 프로세스가 다음 요청을 받으면 초기화하기 전에 그 상태를 쓰게 된다. 메모리 부족뿐 아니라 다른 치명적 오류나 경고로도 생긴다.
메모리는 요청 하나로 일부러 바닥낼 수 있다. 보안 권고에 따르면 파일 업로드 형식(multipart) 요청을 길이 표시 없이 보내거나 헤더나 필드 이름을 끝없이 늘리면 되고, 그러면 PHP는 공격자가 채워 둔 메모리를 자기 데이터로 쓰게 된다. 피해는 코드 실행에 그치지 않는다. Wiz는 다른 요청이나 서버의 메모리를 읽어 내는 공격도 보였는데, 그 메모리에는 비밀번호, 인증 토큰, API 키, 인증서가 들어 있을 수 있다.
PHP가 매긴 취약점 심각도 점수(CVSS)는 10점 만점에 9.2다. 공격이 얼마나 쉽고 피해가 얼마나 큰지를 매기는 점수로, 다른 판의 기준을 쓰는 미국 취약점 데이터베이스(NVD)에서는 109618과 109619 모두 9.8로 나온다.
발견과 공개 경위
문제가 처음 보인 것은 2024년이다. 독일 정부 기관 Sovereign Tech Agency의 지원으로 보안업체 Quarkslab이 PHP를 감사했는데, 그 결과를 고치던 PHP 핵심 개발자가 메모리 부족 처리 문제의 첫 징후를 찾았다. 다만 그때는 공격 가능성이 이론으로만 제기됐다.
고치기도 어려웠다. 메모리 관리와 오류 처리는 거의 모든 요청이 지나가는 PHP의 중심이라, 고치는 방안마다 하위 호환이 깨지거나 새 서비스 거부 공격 여지가 생기거나 외부 확장 기능을 많이 고쳐야 했다. 그렇게 수정은 몇 달씩 멈췄고, PHP 재단은 이 지연을 보안팀의 의사결정 방식과 자원 부족에서 온 “structural failure(구조적 실패)“라고 스스로 인정했다.
올해 8월에는 같은 뿌리의 공격이 실제로 통한다는 보고가 들어왔다. PHP 재단에 따르면 OpenAI의 보안 프로그램 ‘Patch the Planet’에 참여한 Calif가 7월 30일 PHP 감사를 시작했고, 8월 11일 Calif 연구원과 OpenAI가 같은 원인의 결함을 각각 보고했으며, 이어 Wiz가 8월 24일, OpenAI가 9월 18일 다른 공격 경로를 더 보고했다. Wiz는 연구에 자사 도구와 구글 Gemini 4 Argon, OpenAI GPT-5.6 Sol을 썼고, OpenAI는 Calif가 GPT-5.6 Sol로 결함을 찾았다고 했다.
공개는 계획보다 하루 당겨졌다. PHP 재단에 따르면 20일 오후 3시(협정 세계시) 무렵 두 CVE 번호가 틀린 공개 시각, 틀린 점수 10.0과 함께 온라인에 돌았고, 이에 PHP는 공개를 22일에서 21일 오후 2시(한국 시간 밤 11시)로 앞당겼다. 기술 세부는 새지 않았지만, 결함을 보고한 업체 한 곳이 시연 영상을 실수로 올렸다 지웠고 그 사본이 소셜미디어에 돌았다.
다음에 볼 것
- 시도가 실제 침해로 이어졌는지. 지금까지 보고된 것은 공격 시도이고, CISA와 KISA의 발표에는 침해가 확인됐다는 내용이 없다. CISA의 ‘악용이 확인된 취약점’ 목록(KEV) 등재와 KISA의 후속 공지를 보면 된다. 목록에 오르면 실제 악용이 확인됐다는 뜻이고, 패치하지 않은 서버는 침해를 전제로 기록을 살펴야 한다.
- 8.1 이하를 쓰는 서버가 어떻게 되는지. PHP 프로젝트는 8.1 이하에 정식 판을 내지 않았고, 최소 수정본만 GitHub에 올렸다. 배포판·장기 지원 업체·호스팅 업체가 백포트를 내는지 공지를 보면 된다. 백포트가 없으면 지원 판으로 올리거나, CISA와 KISA가 권한 대로 외부 접속을 막는 수밖에 없다.