PHP2Shell 온라인 취약점 검사기

소유하거나 테스트 권한을 받은 URL을 입력하세요. PHP 특징, 버전 단서, 폼 응답을 순서대로 확인해 PHP2Shell 노출 위험과 후속 조치를 판단합니다.

2

PHP 코어 취약점

9.2

CVSS v4.0 점수(심각)

4

업스트림에서 수정된 8.2~8.5 브랜치

취약점 개요

PHP2Shell이란 무엇이며 왜 신속한 점검이 필요한가요?

PHP2Shell은 PHP 코어의 메모리 안전성 취약점 CVE-2026-109618과 CVE-2026-109619를 통칭하며, 두 취약점 모두 CVSS v4.0 9.2점입니다. 인증 없는 원격 코드 실행이 가능할 수 있으며 영향은 버전, 배포 환경, 공격 경로에 따라 달라집니다.

PHP 공식 권고 읽기

개별 애플리케이션뿐 아니라 PHP 엔진 자체의 문제

웹 요청을 처리하는 PHP-FPM, Apache mod_php, php-cgi, FrankenPHP, LiteSpeed 등을 모두 점검해야 합니다. PHP는 mod_php를 가장 위험한 구성으로 보며, 애플리케이션 코드 실행 전 공격이 실증되었습니다. 단순한 페이지나 안전한 애플리케이션 코드도 노출을 배제하지 못합니다.

웹사이트 소프트웨어와 실행 환경을 함께 확인

WordPress, Drupal, 프레임워크, 플러그인을 업데이트해도 기반 PHP가 함께 업데이트되는 것은 아닙니다. 각 사이트의 PHP 버전, FPM 풀, 컨테이너 이미지, 서비스 노드, 관리 패널이나 장비에 내장된 PHP를 각각 확인하세요. 공식 수정 버전은 2026년 10월 21일에 배포되었습니다.

검사 항목

PHP 특징, 요청 응답, 패치 상태 점검

7개 요청이 점검에 어떻게 도움이 되나요?

기준 GET을 먼저 보낸 뒤 세 가지 메서드마다 URL 인코딩 폼과 multipart 폼을 전송합니다. 각 응답을 확인한 다음 요청을 보냅니다. 동작 비교를 위한 일반 요청이며 코드 실행이나 메모리 고갈 페이로드는 포함하지 않습니다.

PHP2Shell 점검에 사용하는 7개 HTTP 요청
순서 요청 메서드 전송 내용 관찰할 내용
01GET요청 본문 없음접근 가능 여부, 리디렉션, 공개 PHP 버전 표시, 응답 헤더.
02POSTapplication/x-www-form-urlencodedPOST 대조용 일반 텍스트 필드 1개.
03POSTmultipart/form-dataPOST 대조 요청과 비교하는 텍스트 필드 1개. 파일 부분이나 업로드 진행 필드는 추가하지 않습니다.
04PUTapplication/x-www-form-urlencoded해당 경로의 PUT 처리를 확인하는 일반 텍스트 필드 1개.
05PUTmultipart/form-data일반 PUT 폼과 비교해 콘텐츠 유형에 따른 응답 차이를 확인합니다.
06PATCHapplication/x-www-form-urlencodedPATCH 대조용 일반 텍스트 필드 1개.
07PATCHmultipart/form-dataPATCH 대조 요청과 비교하며 POST만으로 다른 메서드의 동작을 추정하지 않습니다.

X-Powered-By나 Server의 PHP 표시와 PHPSESSID 같은 세션 쿠키는 실행 환경의 단서일 뿐입니다. 숨기거나 수정하거나 사용자 정의할 수 있습니다. 쿠키가 있어도 PHP가 요청 본문을 파싱했다는 증거는 아닙니다.

검사는 입력한 URL과 경로만 대상으로 합니다. 다른 경로, CDN 규칙, 직접 접근 가능한 원본 서버는 다르게 동작할 수 있습니다. 홈페이지 결과를 전체 사이트에 일반화하지 마세요. 권한이 있고 폼 요청에 적합한 경로에서만 검사하세요.

검사 결과 해석 방법

노출 단서와 확인된 수정을 구분하세요

공개 응답은 일부 증거만 제공합니다. 버전이 숨겨지거나 변경될 수 있고 구버전에도 공급업체 백포트가 포함될 수 있습니다. 증거 부족을 안전으로 판단하지 말고 실제 실행 환경을 확인하세요.

흔한 판단 오류 알아보기

수정 버전 단서가 확인됨

공개 버전이 해당 브랜치의 수정 기준 이상이면 유용한 단서지만 프록시가 헤더를 바꿀 수 있습니다. 서버에서 모든 인스턴스가 수정 코드를 로드했는지 확인하세요.

구버전 위험 단서가 확인됨

업스트림 수정 기준보다 낮은 버전을 우선 점검하되 배포판이나 LTS 공급업체의 백포트도 확인하세요. 백포트 상태가 불명확하면 원격 코드 실행이 검증되었다고 하지 말고 확인 필요로 기록하세요.

요청이 거부되거나 응답이 다름

일반 폼은 성공하고 multipart가 4xx라면 콘텐츠 유형 제한 때문일 수 있습니다. 둘 다 405이면 해당 경로에서 메서드를 지원하지 않을 수 있습니다. 상태 코드만으로 CDN, 웹 서버, 애플리케이션 중 어느 계층이 거부했는지 구분할 수 없습니다.

PHP 단서가 없거나 유효한 응답을 받지 못함

숨겨진 버전, 프록시 캐시, 사용자 정의 쿠키, 연결 실패, 시간 초과는 평가를 제한합니다. 부족한 증거를 녹색 안전 판정으로 대체하지 말고 정보 부족 또는 평가 불가로 기록하세요.

검사 절차

URL 입력부터 증거 확인까지

1

대상 URL 입력

소유하거나 테스트 권한을 받은 사이트 주소와 확인할 경로를 입력합니다.

2

순차 검사 및 응답 확인

GET 기준 응답을 확인한 뒤 POST, PUT, PATCH의 일반 폼과 multipart 응답을 요청별로 비교합니다.

3

위험 안내 및 수정 권고 확인

상태 코드와 버전 단서를 해석하고 실제 PHP 환경 및 공급업체 권고와 대조해 패치 상태를 확인합니다.

서버 측 점검

웹사이트가 수정된 PHP로 실행 중인지 어떻게 확인하나요?

외부 검사는 단서 파악에 유용하지만 패치 상태는 호스트, 컨테이너, 호스팅 패널에서 확인해야 합니다. 실행 환경, 패키지 출처, 수정 버전, 업데이트 후 프로세스 상태를 순서대로 기록하세요.

1. 실제 요청을 처리하는 PHP 확인

사이트에 지정된 PHP, 웹 서버 모듈, FPM 풀을 확인하세요. 공존하는 버전, 여러 사이트, 컨테이너, 부하 분산 노드를 각각 조사해야 합니다. php -v는 현재 CLI 버전만 보여 주며 웹 실행 버전과 다를 수 있습니다. 확인을 위해 phpinfo 페이지를 공개하지 마세요.

php -v

2. 전체 패키지 버전 및 공급업체 권고 확인

실제 설치 패키지를 조회하고 전체 버전을 배포판 보안 권고와 비교하세요. Ubuntu 24.04의 8.3.6-0ubuntu0.24.04.13 패키지에는 이미 수정이 포함됩니다. PHP 8.3.6만 보면 백포트 정보가 누락됩니다. 아래에서 시스템에 맞는 예시를 선택하고 실제 패키지명으로 바꾸세요.

dpkg-query -W php8.3-fpm
rpm -q php-fpm
Ubuntu 공식 수정 패키지 목록 보기

3. 해당 브랜치의 수정 버전 적용

해당 브랜치의 업스트림 수정 버전, 이후 보안 버전 또는 확인된 공급업체 백포트를 사용하세요. 패널, 장비, 컨테이너에 포함된 PHP는 각 공급업체 방식으로 업데이트해야 합니다. PHP 8.1 이하는 정규 업스트림 지원이 종료되어 LTS 수정을 확인하거나 이전해야 합니다. 이번에는 7.4, 8.0, 8.1용 최소 소스 백포트도 제공되었습니다.

4. 재시작 후 모든 인스턴스 재점검

관련 PHP-FPM, Apache, 기타 워커가 재시작되고 컨테이너와 다중 노드가 교체되었는지 확인하세요. 디스크 파일 업데이트만으로 기존 프로세스 교체를 보장할 수 없습니다. 이상 요청, 메모리 부족, 워커 충돌 기록은 조사에 유용하지만 기록이 없다고 영향이 없었다고 판단할 수는 없습니다.

직접 점검하기: curl로 7개 항목 검사

스크립트는 GET 1회에 이어 POST, PUT, PATCH의 URL 인코딩 및 multipart 폼 요청을 하나씩 보냅니다. 일반 텍스트 필드만 사용하며 파일이나 업로드 진행률 필드는 보내지 않습니다. 허가받은 테스트 폼 경로에서만 실행하세요. 일반 요청도 애플리케이션 동작을 유발할 수 있습니다.

Bash / curl
#!/usr/bin/env bash
# PHP2Shell HTTP observations: 7 sequential requests, no exploit payload.
set -u

URL="${1:-https://example.com/}"
case "$URL" in
  http://*|https://*) ;;
  *) printf 'ERROR=HTTP(S)_URL_REQUIRED\n' >&2; exit 2 ;;
esac

if ! command -v curl >/dev/null 2>&1 || ! command -v awk >/dev/null 2>&1; then
  printf 'ERROR=CURL_AND_AWK_REQUIRED\n' >&2
  exit 127
fi

probe() {
  printf '\n[%s/7] %s %s\n' "$1" "$2" "$3"
  local method="$2"
  shift 3
  curl -q --globoff --proto '=http,https' --silent --show-error \
    --connect-timeout 5 --max-time 15 --request "$method" \
    --dump-header - --output /dev/null \
    --write-out '\nHTTP_CODE=%{http_code} TOTAL_SECONDS=%{time_total}\n' \
    "$@" --url "$URL" |
  awk '{
    sub(/\r$/, "")
    line = tolower($0)
    if ($0 ~ /^HTTP\// || line ~ /^(server|x-powered-by|content-type):/ || $0 ~ /^HTTP_CODE=/) {
      print
    } else if (line ~ /^set-cookie:[ \t]*phpsessid[ \t]*=/) {
      print "PHPSESSID=present; value hidden"
    }
  }'
  local curl_status="${PIPESTATUS[0]}"
  if [ "$curl_status" -ne 0 ]; then
    printf 'CURL_EXIT=%s\n' "$curl_status"
    FAILED=1
  fi
}

FAILED=0
probe 1 GET baseline
probe 2 POST urlencoded --data-raw 'php2shell_check=1'
probe 3 POST multipart --form-string 'php2shell_check=1'
probe 4 PUT urlencoded --data-raw 'php2shell_check=1'
probe 5 PUT multipart --form-string 'php2shell_check=1'
probe 6 PATCH urlencoded --data-raw 'php2shell_check=1'
probe 7 PATCH multipart --form-string 'php2shell_check=1'
exit "$FAILED"

Linux/macOS의 Bash 또는 Windows의 WSL이나 Git Bash를 사용하세요. php2shell-self-check.sh로 저장한 뒤 아래 명령의 URL을 허가받은 테스트 페이지로 바꿔 실행하세요. Bash 스크립트 전체를 PowerShell에 직접 붙여 넣지 마세요.

bash php2shell-self-check.sh https://example.com/test.php

연결 제한은 5초, 요청별 전체 제한은 15초입니다. 개인 curl 설정을 무시하고 TLS를 검증하며 리디렉션이나 재시도를 하지 않습니다. 3xx를 받으면 최종 URL도 허가 범위인지 확인한 뒤 해당 주소에서 다시 실행하세요. PHPSESSID는 존재 여부만 표시하며 쿠키 값과 응답 본문은 출력하지 않습니다.

HTTP_CODE는 응답 상태, TOTAL_SECONDS는 전체 소요 시간입니다. CURL_EXIT가 0이 아니면 해당 전송에 실패했지만 나머지 검사는 계속됩니다. 스크립트의 0이 아닌 종료 코드는 입력, 의존 명령 또는 전송 문제를 의미합니다. HTTP 4xx/5xx는 정상적으로 기록되며 종료 코드로 취약점이나 패치 상태를 판단할 수 없습니다.

터미널 출력 해석 방법

버전 헤더는 단서입니다

Server나 X-Powered-By는 숨겨지거나 오래된 정보일 수 있습니다. 웹사이트에서 실제 실행되는 PHP를 확인하세요. 각 브랜치의 최초 공식 수정 버전은 8.2.35, 8.3.36, 8.4.27, 8.5.12입니다. 공급업체의 백포트는 전체 패키지 버전과 보안 공지로 확인해야 합니다.

같은 메서드의 두 인코딩을 비교하세요

같은 메서드에서 urlencoded는 2xx 또는 3xx, multipart는 403 또는 406을 반환해도 응답 차이만 확인됩니다. WAF 차단이나 PHP 도달 전 거부를 입증하지는 않습니다.

성공 응답이 PHP 파싱을 입증하지는 않습니다

multipart의 2xx 또는 3xx는 성공이나 리디렉션 응답을 받았다는 의미일 뿐입니다. 본문이 PHP에 도달해 파싱되었음을 입증하지 않으며 취약점 존재 여부도 판단할 수 없습니다.

405와 PHP 표시는 단독 판단 근거가 아닙니다

모두 405를 반환해도 수정이 입증되지 않습니다. PHP 표시가 없어도 PHP 미사용을 뜻하지 않습니다. PHPSESSID 쿠키가 있어도 multipart 파싱 여부나 어느 계층에서 응답했는지 확정할 수 없습니다.

공식 수정 버전과 업그레이드 안내 보기
업데이트 전 임시 완화 조치로 무엇을 할 수 있나요?

PHP는 완전한 수정에 업데이트가 필요하다고 명시합니다. 아래 설정은 일부 알려진 경로의 노출만 줄이며 미패치 환경을 안전하게 만들지 않습니다. 변경 전에 애플리케이션 요구 사항과 공식 지침을 검토하세요.

  • session.upload_progress.enabled를 비활성화하고 모든 워커를 재시작하세요. 요청 파싱 전에 php.ini, FPM 풀, 서버 설정으로 적용해야 하며 ini_set()이나 FPM의 .user.ini에 의존하면 안 됩니다. 확인된 session 경로만 차단합니다.
  • PHP 8.5에서는 공식 권고에 따라 fatal_error_backtraces를 비활성화하고 워커를 재시작할 수 있습니다. 확인된 fatal backtrace 경로에만 해당하며 다른 변종은 포함하지 않습니다.
  • 웹 서버나 프록시에서 본문 크기, 필드 수, multipart 부분 수 제한을 검토하고 CDN을 우회한 원본 접근 여부를 확인하세요. 오류 숨김, 특정 메서드만 차단, 단일 경로 점검은 수정을 대체하지 못합니다.

공식 수정 버전

PHP 8.2~8.5 브랜치별 수정 기준 확인

브랜치별로 버전을 비교하세요. 8.3 수정 기준으로 8.4 상태를 판단할 수 없습니다. 사전 릴리스나 알 수 없는 브랜치를 수정된 것으로 간주하지 마세요. 백포트와 자체 빌드는 전체 패키지 버전, 빌드 기록, 공급업체 권고로 확인해야 합니다.

공식 업데이트 권고 읽기

BaoTa 패널을 사용하시나요? 소프트웨어 스토어에서 PHP를 업데이트하세요

BaoTa의 2026-10-21 공지에 따르면 일부 PHP 보안 수정 버전이 패널에 제공됩니다. 실제 업데이트 가능한 버전은 사용 중인 패널의 소프트웨어 스토어에서 확인하세요.

BaoTa 업데이트 공지 보기

업데이트 전에 웹사이트, 데이터베이스, 관련 설정을 백업하고 적절한 유지보수 시간을 선택하세요.

  1. 웹사이트에서 실제 사용하는 PHP 확인

    BaoTa 패널에 로그인한 뒤 소프트웨어 스토어 → 설치됨에서 현재 웹사이트가 사용하는 PHP 버전을 찾아 관리 페이지를 여세요.

  2. 해당 브랜치의 보안 버전으로 업데이트

    해당 PHP 관리 페이지에서 업데이트를 확인하고 안내에 따라 위에 표시된 동일 브랜치의 수정 버전 또는 해당 브랜치의 후속 보안 버전을 설치하세요.

  3. PHP 재시작 및 웹사이트 검증

    업데이트 후 해당 PHP 서비스를 재시작하고 모든 워커가 다시 로드되었는지 확인하세요. 웹사이트에서 실제 사용하는 PHP 버전을 확인한 뒤 페이지 접속, 파일 업로드, 데이터베이스 연결 등 주요 기능을 테스트하세요.

여러 PHP 버전이 설치되어 있다면 사용 중인 버전을 각각 점검하세요. 다른 버전을 새로 설치했다면 웹사이트가 수정된 PHP 실행 환경으로 전환되었는지도 확인하세요.

자주 묻는 질문

PHP2Shell 취약점 검사 및 수정 FAQ

버전 단서, 상태 코드, 공급업체 백포트의 차이를 이해해 결과를 과도하게 해석하지 마세요.

PHP2Shell이란 무엇이며 어떤 사이트를 점검해야 하나요?

PHP2Shell은 PHP 코어 취약점 CVE-2026-109618과 CVE-2026-109619를 말하며 인증 없는 원격 코드 실행을 허용할 수 있습니다. 애플리케이션 코드가 안전해도 웹 요청을 처리하는 미수정 PHP 환경은 모두 점검해야 합니다.

403, 405, 413 응답이면 보호되고 있다는 뜻인가요?

아닙니다. 인증 요구, 지원하지 않는 메서드, 크기 제한, 프록시도 이런 코드를 반환할 수 있습니다. multipart 거부는 현재 경로의 동작만 보여 주며 PHP 수정이나 모든 공격 경로 차단을 증명하지 않습니다.

PHP 응답 헤더가 없으면 영향이 없다는 뜻인가요?

그렇게 판단할 수 없습니다. 버전 공개가 비활성화되어 있거나 CDN, 역방향 프록시, 정적 홈페이지가 백엔드를 가릴 수 있습니다. 특징이 없으면 정보 부족으로 보고 실제 서버 실행 환경을 확인하세요.

어떤 버전으로 업데이트해야 하며 구버전은 항상 미수정 상태인가요?

업스트림 수정 버전은 PHP 8.2.35, 8.3.36, 8.4.27, 8.5.12입니다. 해당 브랜치의 수정 버전이나 이후 보안 버전을 사용하세요. 구버전에도 백포트가 있을 수 있으므로 전체 패키지 버전과 공급업체 권고를 대조해야 합니다. PHP 8.1 이하는 정규 업스트림 지원이 종료되었습니다. 업데이트 후 관련 워커를 재시작하세요.

POST 외에 PUT과 PATCH도 확인하는 이유는 무엇인가요?

메서드마다 경로와 필터 규칙이 다를 수 있습니다. PHP 8.4부터 request_parse_body()로 POST 이외의 multipart를 파싱할 수 있지만 모든 애플리케이션이 PUT이나 PATCH를 자동 파싱하는 것은 아닙니다. POST 동작만으로 다른 메서드나 경로의 보호를 판단할 수 없습니다.

POST는 200, PUT/PATCH는 405이고 PHP 표시가 없다면 어떻게 판단하나요?

PHP 실행 환경과 패치 상태를 미확인으로 기록하세요. POST 200은 응답했다는 뜻이며 405는 어느 계층에서 메서드를 거부했다는 의미입니다. 정적 페이지, 다른 실행 환경, 특징을 숨긴 PHP 모두 같은 패턴을 보일 수 있습니다. 안전이나 취약점 확인으로 단정하지 말고 서버에서 실행 환경을 검증하세요.

취약점 및 수정 자료 확인일은 2026-10-22입니다. 외부 관찰에는 한계가 있으므로 실제 대응은 최신 PHP 및 공급업체 권고를 따르세요.

웹사이트의 PHP2Shell 위험을 더 명확하게

공개 응답을 하나씩 확인하고 증거를 해석한 뒤 실제 서버 환경에서 패치와 수정을 검증하세요.

검사 항목 알아보기