원문 캡처 · github.com
원문 캡처 · github.com

PHP2ShellCheck는 웹 서버의 HTTP/HTTPS 응답 헤더에서 PHP 흔적을 찾고 버전을 알려진 수정 버전과 비교하는 Python 도구다. CVE-2026-109618과 CVE-2026-109619에 취약할 가능성을 나타내는 지표를 찾지만, 취약 여부를 확정하지는 않는다.

도구는 80, 443, 8080, 8443 포트를 확인한다. /에 요청을 보내고 같은 호스트·포트·스킴으로 향하는 리디렉션을 최대 3회 따라간다. PHP 흔적을 찾지 못한 응답 포트에는 /index.php도 요청한다. X-Powered-By 헤더의 PHP, Server 헤더의 PHP 버전 문자열, PHPSESSID 쿠키를 흔적으로 판별한다.

  • VULNERABLE: PHP 8.2.35, 8.3.36, 8.4.27, 8.5.12보다 낮은 해당 계열 버전이다. 관련 권고는 CVE-2026-109618과 CVE-2026-109619다.
  • END OF LIFE: PHP 8.1 이하로, 두 권고의 적용 대상은 아니며 수정 버전도 제공되지 않는다.
  • VERSION UNKNOWN: PHP 흔적은 있지만 버전·계열·패치 수준을 알 수 없거나, 권고에 명시되지 않은 계열이다.
  • PATCHED: 해당 계열의 수정 버전 이상이다.

호스트에 여러 포트의 결과가 있으면 가장 심각한 상태를 호스트 상태로 사용한다. 버전을 보여주는 흔적이 하나도 없을 때만 VERSION UNKNOWN을 표시한다. 배포판 버전 접미사가 붙은 경우 보고서에 메모를 남긴다. Debian, Ubuntu, RHEL 등은 업스트림 버전 문자열을 바꾸지 않고 수정 사항을 역이식할 수 있으므로 패키지 변경 이력으로 확인해야 한다.

Python 3.8 이상과 pip3가 필요하다. 의존성은 비동기 HTTP 클라이언트 aiohttp 하나이며, asyncio는 Python 표준 라이브러리에 포함된다.

pip3 install -r requirements.txt

대상은 한 줄에 하나씩 IP 주소, 호스트 이름 또는 CIDR 블록을 적은 파일로 지정하거나 -u 옵션으로 직접 입력한다. 결과 파일 기본값은 scan_results.txt다.

python php2shellcheck.py -t targets.txt
python php2shellcheck.py -u https://www.example.com/
python php2shellcheck.py -u example.com -u www.example.com
python php2shellcheck.py -t targets.txt -o audit.txt -q

빈 줄과 # 주석은 무시한다. 65,536개보다 큰 CIDR 블록은 건너뛰며, 중복 호스트는 한 번만 검사한다. URL·포트 등 호스트가 아닌 항목은 건너뛰고 요약에 집계한다. 요청은 최대 50개까지 동시에 실행하며, 연결 제한 시간은 5초, 요청 전체 제한 시간은 10초다. 시간 초과 뒤 한 번 재시도한다. -q를 쓰면 취약·지원 종료·버전 미확인 호스트만 터미널에 표시하지만, 패치된 호스트도 결과 파일에는 기록한다. 결과 파일은 권한 0600으로 생성하며, 대상 목록과 같은 파일 경로는 사용할 수 없다.

도구는 응답 본문을 내려받지 않고 헤더만 읽는다. 다른 호스트·포트·스킴으로 향하는 리디렉션은 따르지 않는다. TLS 인증서 검증은 비활성화되어 있고, 오래된 서버를 놓치지 않도록 TLS 1.0/1.1과 낮은 보안 수준의 암호군, 레거시 재협상을 허용한다. 검사 허가를 받은 호스트에만 사용해야 한다.

헤더가 숨겨졌거나 프록시가 제거하면 PHP를 실행하는 서버도 흔적이 없는 것으로 나올 수 있다. 검사 대상은 지정된 네 포트와 제한된 경로뿐이며, IP 주소로 검사하면 기본 가상 호스트만 보일 수 있다. 배포판의 역이식, 버전 위조 프록시, 여러 백엔드 앞의 로드밸런서도 배너와 실제 실행 버전의 차이를 만들 수 있다. 따라서 흔적이 없거나 PATCHED로 표시돼도 안전하다는 뜻은 아니다. 네트워크 공격자가 가짜 헤더를 보낼 수도 있으므로 결과는 단서로만 보고 신뢰할 수 있는 인벤토리로 버전을 확인해야 한다.

테스트는 python -m unittest discover -s tests로 실행한다. 버전 분류, 헤더 파싱, 대상 로딩, 보고서 요약과 로컬 테스트 서버 점검을 다루며 외부 네트워크 요청은 하지 않는다. 프로젝트는 MIT License로 배포된다.