2026년 10월 27일 화요일
미단재

AI [긴급] PHP RCE(CVE-2026-109618/109619) & CI4 업로드 취약점 대응 가이드

작성자 웅파 작성일 2026-10-26 20:18:29 조회수 29

2026년 10월 26일 · @martin · CI Korea

요약: 지금 당장 할 일

10월 21일 PHP 코어에서 인증 없이 원격 코드 실행이 가능한 취약점 2건이 공개됐고, 7월에는 CI4 파일 업로드 검증을 우회해 웹셸을 올릴 수 있는 취약점이 공개됐습니다. 웹에 노출된 PHP 서버라면 아래 세 가지를 오늘 안에 처리하세요.

  1. PHP 런타임 업데이트: 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 이상, 또는 배포판 보안 패키지(Ubuntu는 USN-8948-1)로 올리고 PHP-FPM·Apache를 재시작합니다.
  2. 바로 못 올리면 완화 설정: session.upload_progress.enabled = 0 적용 후 모든 워커 재시작, 요청 크기 제한. 완화는 노출을 줄일 뿐 해결책이 아닙니다.
  3. CI4는 4.7.4 이상으로: 업로드 처리 코드에서 ext_in 병행, 랜덤 파일명 저장, 업로드 폴더 PHP 실행 차단을 확인합니다.

점검은 이 글 하단의 자가진단 스크립트(ci-security-check.php)로 한 번에 할 수 있습니다.

이슈 개요

두 갈래입니다. PHP 런타임 자체의 결함(모든 PHP 사이트 해당)과, CI4 프레임워크의 업로드·HTTPS 판별 결함(CI4 사용 사이트 해당)입니다.

구분

CVE

내용

심각도

수정 버전

PHP 코어

CVE-2026-109618

메모리 부족(OOM) 처리 중 반쯤 초기화된 요청 데이터를 정리 과정에서 유효한 것으로 취급 → RCE

CVSS 4.0 9.2

8.5.12 / 8.4.27 / 8.3.36 / 8.2.35

PHP 코어

CVE-2026-109619

해제된 메모리를 가리키는 요청 상태가 다음 요청까지 남음 → RCE

CVSS 4.0 9.2

위와 동일

CI4

CVE-2026-48062

ext_in 규칙이 클라이언트 파일명이 아닌 MIME 추정 확장자를 검사 → 이미지 위장 웹셸 업로드

Critical

4.7.3

CI4

CVE-2026-63223

is_image, mime_in 규칙이 확장자를 따로 강제하지 않음 → 웹셸 업로드

CVSS 4.0 9.3

4.7.4

CI4

CVE-2026-63222

UploadedFile::move()를 파일명 인자 없이 호출하면 클라이언트 파일명을 그대로 사용 → 경로 탐색

CVSS 4.0 8.7

4.7.4

CI4

CVE-2026-63220

isSecure()가 X-Forwarded-Proto 등 헤더를 무조건 신뢰 → HTTPS 강제 우회

HTTPS 우회 (CWE-348)

4.7.4

PHP 코어 취약점은 PHP-FPM, mod_php, php-cgi, FrankenPHP, LiteSpeed 등 웹 요청을 처리하는 모든 설치가 대상이며, PHP 팀은 mod_php를 가장 위험하다고 봅니다. 애플리케이션 코드가 실행되기 전에 공격이 들어오므로 "우리 코드는 안전하다"는 판단이 통하지 않습니다.

주의: 공개된 PoC를 사칭한 악성코드가 함께 돌고 있습니다. 출처 불명의 익스플로잇 코드는 실행하지 마세요.

내 서버가 영향받는지 확인하기

php -v의 버전 번호만 보고 판단하면 틀립니다. Ubuntu·Debian은 버전 번호를 그대로 두고 패치만 백포트하기 때문에, 패치된 Ubuntu 24.04도 8.3.6으로 표시됩니다. 반드시 패키지 리비전을 확인하세요.

# 1) 웹에서 실제 쓰는 PHP 버전 (CLI와 FPM이 다를 수 있음)
php -v
ls /etc/php/            # 설치된 버전 목록

# 2) Ubuntu/Debian 패키지 리비전
dpkg -l | grep -E 'php[0-9.]+-(fpm|cli|common)|libapache2-mod-php'
apt-cache policy php8.3-fpm

# 3) 업로드 진행 기능 설정값 (FPM 기준으로 확인)
php-fpm8.3 -i | grep session.upload_progress.enabled

환경

안전한 기준

php.net 공식 빌드

8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 이상

Ubuntu 26.10 (php8.5)

8.5.9-0ubuntu2.1 이상

Ubuntu 26.04 LTS (php8.5)

8.5.4-0ubuntu1.5 이상

Ubuntu 24.04 LTS (php8.3)

8.3.6-0ubuntu0.24.04.13 이상

Ubuntu 22.04 LTS (php8.1)

8.1.2-1ubuntu2.28 이상

Ubuntu 20.04 이하 (php7.x, php5)

Ubuntu CVE 페이지에서 상태 확인 필요 → 사실상 업그레이드 대상

PHP 8.1 이하 (공식)

공식 업데이트 없음. 배포판/LTS 벤더 백포트 확인 또는 업그레이드

CI4 버전은 프로젝트 루트에서 composer show codeigniter4/framework | grep versions로 확인합니다. 4.7.4 미만이면 업그레이드 대상입니다.

표의 Ubuntu 패키지 버전은 USN-8948-1 기준입니다(출처). 적용 전 ubuntu.com/security/notices에서 최신 리비전을 다시 확인하세요.

조치 1: PHP 런타임 업데이트

업데이트만이 완전한 해결책입니다. 패키지를 올린 뒤 모든 PHP 워커를 재시작해야 적용됩니다.

Ubuntu 기본 패키지 (php8.1 / 8.3 / 8.5)

sudo apt update
sudo apt install --only-upgrade 'php8.3*'      # 사용 중인 버전으로
sudo systemctl restart php8.3-fpm               # FPM
sudo systemctl restart apache2                  # mod_php 사용 시
dpkg -l | grep php8.3-common                    # 리비전 재확인

Ondrej PPA(ppa:ondrej/php) 사용 서버

sudo apt update && sudo apt upgrade
php -v      # PPA는 업스트림 버전을 따르므로 8.x.xx 숫자로 확인
sudo systemctl restart php8.4-fpm

Docker

컨테이너 재시작이나 앱 파일 교체만으로는 PHP가 바뀌지 않습니다. 패치된 베이스 이미지로 다시 빌드하고 컨테이너를 재생성하세요.

docker pull php:8.4-fpm
docker compose build --no-cache && docker compose up -d --force-recreate
docker compose exec app php -v

업데이트 후 알려진 회귀: 8.4.27, 8.5.12에서 SimpleXML 관련 메모리 이중 해제 버그(php-src#24488)가 보고됐습니다. SimpleXML을 많이 쓰는 서비스는 업데이트 후 해당 기능을 테스트하고, 다음 정기 릴리스를 주시하세요.

조치 2: 바로 업데이트할 수 없을 때 완화 설정

PHP 보안팀이 제시한 완화책입니다. 특정 공격 경로만 막을 뿐 서버를 안전하게 만들지는 않으니, 업데이트까지의 시간 벌기로만 쓰세요.

CVE-2026-109619 대응 (가장 먼저 적용)

요청 파싱 전에 적용되는 위치(php.ini 또는 FPM 풀)에 넣어야 합니다. ini_set()이나 .user.ini로는 효과가 없습니다.

; /etc/php/8.3/fpm/pool.d/www.conf
php_admin_value[session.upload_progress.enabled] = 0

; PHP 8.5 사용 시 추가
php_admin_value[fatal_error_backtraces] = 0

CVE-2026-109618 대응

; 업로드가 없는 앱
php_admin_value[post_max_size] = 8M
; 업로드가 필요한 앱
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 30M   ; 항상 post_max_size보다 작게

PHP 팀은 memory_limit=-1(php_admin_value로 고정)도 제시했지만, 메모리 폭주 시 서버 전체가 영향을 받을 수 있습니다. 적용한다면 반드시 컨테이너나 cgroup 메모리 제한을 함께 거세요. RLIMIT_AS, RLIMIT_DATA로 대신하면 오히려 취약 경로를 유발하므로 쓰지 않습니다.

웹서버에서 요청 크기 제한

# nginx
client_max_body_size 32m;
large_client_header_buffers 4 8k;
# Apache
LimitRequestBody 33554432
LimitRequestFields 100

적용 후 반드시 재시작하고 확인합니다.

sudo php-fpm8.3 -t && sudo systemctl restart php8.3-fpm
grep -rn upload_progress /etc/php/8.3/fpm/   # 설정 위치 확인
# 실제 적용값은 웹으로 phpinfo()를 잠깐 띄워 Local Value 확인 후 즉시 삭제

애플리케이션 쪽에서는 공격자가 유발할 수 있는 fatal error와 실행 시간 초과(업로드·임포트 처리, 콜백 등)를 줄이고, 요청마다 경고를 내는 잘못된·폐기된 ini 설정을 정리하세요. @나 display_errors로 숨기는 것은 도움이 되지 않습니다.

조치 3: CI4 4.7.4 업그레이드와 업로드 코드 점검

4.7.4는 설정 파일과 프로젝트 파일 변경이 없는 릴리스라 composer 업데이트만으로 적용됩니다.

composer update codeigniter4/framework --with-dependencies
composer show codeigniter4/framework | grep versions   # 4.7.4 이상 확인
php spark cache:clear

업그레이드 후에도 아래 코드 패턴은 직접 확인하세요. 프레임워크 패치는 검증 규칙을 고칠 뿐, 클라이언트 파일명을 그대로 저장하는 앱 코드까지 바꾸지는 않습니다.

업로드 검증: 확장자 규칙을 항상 함께

// 위험: MIME/이미지 여부만 검사
'avatar' => 'uploaded[avatar]|is_image[avatar]|max_size[avatar,2048]',

// 안전: ext_in 으로 클라이언트 확장자를 별도 강제 (4.7.3+ 에서 동작)
'avatar' => 'uploaded[avatar]|is_image[avatar]|mime_in[avatar,image/jpeg,image/png]'
          . '|ext_in[avatar,jpg,jpeg,png]|max_size[avatar,2048]',

저장: 클라이언트 파일명을 쓰지 않기

// 위험: 두 번째 인자 없음 → 클라이언트 파일명 그대로 (경로 탐색 가능)
$file->move(WRITEPATH . 'uploads');

// 위험: 원본 이름을 명시적으로 사용
$file->move(FCPATH . 'uploads', $file->getClientName());

// 안전: 랜덤 이름 + 웹 루트 밖(writable/)에 저장
$newName = $file->getRandomName();
$file->move(WRITEPATH . 'uploads', $newName);

업로드 폴더에서 PHP 실행 차단

웹 루트(public/) 아래에 저장해야 한다면 해당 폴더에서 스크립트 실행을 막습니다.

location ^~ /uploads/ {
    location ~* \.(php|phtml|phar|php\d)$ { deny all; }
}
# public/uploads/.htaccess

    Require all denied

php_flag engine off

HTTPS 판별 (CVE-2026-63220)

패치 전에는 아무 요청이나 보낸 X-Forwarded-Proto 헤더를 믿었습니다. 업그레이드 후 프록시 뒤 환경에서 HTTPS 판별이 달라질 수 있으니, 4.7.4 변경 로그에서 동작을 확인하세요. 로드밸런서나 Cloudflare 뒤에 있다면 app/Config/App.php의 $proxyIPs에 프록시 IP 대역을 정확히 등록해야 forceGlobalSecureRequests가 정상 동작합니다.

CI3 / PHP 7 레거시 사이트 대응

PHP 7.x와 5.x는 php.net 공식 패치가 없습니다. CI3(최신 3.1.13)는 PHP 8.x에서도 대부분 동작하므로, 가장 현실적인 경로는 CI3를 유지한 채 PHP만 8.2 이상으로 올리는 것입니다.

선택지를 위험도 순으로 정리하면 다음과 같습니다.

선택지

효과

비고

PHP 8.3/8.4로 업그레이드 (CI3 유지)

근본 해결

CI3 3.1.13 필요. 동적 프로퍼티 deprecation 경고 정리 필요

배포판/LTS 벤더 백포트 패키지

근본 해결

Ubuntu 22.04 php8.1은 USN 패치 제공. 20.04 이하는 상태 확인

PHP 팀 소스 백포트 (7.4 / 8.0 / 8.1)

근본 해결

직접 소스 빌드 필요. php-src 브랜치

완화 설정만 적용

부분 완화

조치 2 참고. 업그레이드까지 임시

CI4 마이그레이션

근본 + 장기

시간이 걸리므로 PHP 업그레이드를 먼저

PHP 8.2는 2026년 12월 31일로 지원이 끝납니다. 지금 올린다면 8.3 또는 8.4를 권합니다.

CI3 사이트를 PHP 8으로 올릴 때 자주 걸리는 부분:

  • CI3 코어를 3.1.13으로 교체 (system 폴더)
  • 모델·라이브러리에 선언하지 않은 프로퍼티를 동적으로 붙이는 코드 → PHP 8.2 deprecation, 클래스에 프로퍼티 선언 추가
  • each(), create_function() 등 PHP 8에서 제거된 함수 사용 여부
  • mysql_* 드라이버 사용 시 mysqli로 변경

CI3 업로드 라이브러리도 allowed_types 지정, encrypt_name = TRUE, 업로드 폴더 PHP 실행 차단을 함께 확인하세요.

자가진단 도구 사용법 (이 글의 첨부파일 참고)

ci-security-check.php는 서버와 프로젝트를 한 번에 점검하는 단일 PHP 스크립트입니다. 읽기 전용이고 외부로 아무것도 전송하지 않으며, PHP 5.6 이상에서 동작하므로 레거시 서버에서도 그대로 실행할 수 있습니다. 본인이 관리하는 서버에서만 실행하세요.

# 서버 + 프로젝트 전체 점검
php ci-security-check.php /var/www/myproject

# 서버(PHP 런타임·설정)만
php ci-security-check.php --no-code

# 프로젝트만, JSON 출력 (CI 파이프라인·모니터링 연동)
php ci-security-check.php /var/www/myproject --no-server --json

# FPM 풀 설정을 정확히 읽으려면 sudo 권장
sudo php ci-security-check.php /var/www/myproject

점검 영역

내용

1. PHP 런타임

설치된 모든 phpX.Y-common 패키지 리비전을 USN-8948-1 / php.net 수정 버전과 비교. Ubuntu 백포트, Ondrej PPA, EOL 브랜치 구분

2. PHP 설정

FPM 풀별·Apache별로 session.upload_progress.enabled, post_max_size, upload_max_filesize, fatal_error_backtraces(8.5) 등 판정. php_value와 php_admin_value 구분

3. CI 버전

composer.lock 또는 CI_VERSION 상수로 CI4/CI3 판별, 4.7.4 미만이면 해당 CVE 표시. lock과 실제 vendor 버전 불일치도 경고

4. 코드 패턴

파일명 없는 move(), getClientName()으로 저장, ext_in 없는 is_image/mime_in, 런타임 session.serialize_handler 변경, CI3 encrypt_name 누락·allowed_types='*'

5. 업로드 경로

업로드 폴더 안 PHP 파일, 이중 확장자, 이미지로 위장한 PHP 코드, .htaccess 실행 차단 여부

종료 코드는 0(문제 없음), 1(높음·경고), 2(치명)입니다. cron이나 GitHub Actions에서 2가 나오면 알림을 보내는 식으로 쓸 수 있습니다.

한계도 분명히 적어 둡니다. 코드 점검은 정적 패턴 검사라 놓치거나 과탐할 수 있고, nginx 설정 안의 실행 차단 여부는 판정하지 않습니다. RHEL·Alpine·cPanel 등은 패키지 리비전을 읽지 못해 실행 중인 PHP 버전으로만 판정합니다. 업로드 폴더에서 치명 항목이 나오면 파일을 실행하지 말고 격리한 뒤 접근 로그부터 확인하세요.

참고 자료 및 업데이트 이력

공식 공지

보조 자료

업데이트 이력

날짜

내용

2026-10-26

초판 게시. PHP 코어 RCE 2건, CI4 업로드·HTTPS CVE 4건, 자가진단 도구 v1.0.0

이 문서와 도구의 기준 정보는 2026-10-26 시점입니다. php.net은 CVE-2026-115560 전체 권고를 다음 정기 릴리스에 공개한다고 밝혔으므로, 그때 이 문서와 도구를 갱신합니다. 내용 오류나 추가할 사례는 댓글로 알려 주세요.

 

첨부파일 실행결과 예시


댓글 0개