상세 컨텐츠

본문 제목

PHP 취약점(PHP2Shell) 긴급 보안 업데이트, 내 PHP 버전 확인법과 대안 | CVE-2026-109618

IT

by Admimistrator 2026. 10. 22. 12:57

본문

728x90
반응형

📌 10월 23일 업데이트: 정부가 사이버위기 '주의' 경보까지 냈어요

PHP 취약점(PHP2Shell) 판이 하루 만에 더 커졌어요. 과기정통부가 10월 22일 낮 12시부로 민간 분야 사이버위기 '주의' 경보를 발령했고, KISA도 영향받는 버전은 바로 PHP 보안 업데이트를 하라고 권고했어요. 국내 보안업체 티오리는 공식 권고보다 먼저 공격 시연 영상이랑 패치된 파일이 밖으로 새어 나갔다고 밝혔고요.

실제로 뚫린 곳이 있는지는 아직 말이 갈려요. watchTowr는 공격 시도를 봤다고 하고, 미국 CISA랑 캐나다 사이버보안센터는 확인된 악용이 없다고 해요. 근데 공격 방법이 이미 돌아다니는 상황이라 "아직 괜찮겠지"는 안 통하는 단계죠.

아래 표에서 내 PHP 버전이 해당되면 오늘 안에 올리시고, 당장 못 올리면 "당장 못 올리면? 대안 4가지"부터 보세요. 저도 어제 회사 NAS 구석에 숨어 있던 PHP 7.4 옮기느라 오후를 통째로 날렸거든요…

어제(10월 21일) PHP 쪽에서 꽤 큰 게 터졌어요. 

PHP2Shell이라는 취약점인데, PHP 공식 사이트가 "지금 바로 업데이트하라"는 공지를 올렸을 정도예요.

PHP는 생각보다 여기저기 숨어 있어요. 해당되는지는 홈페이지나 사내 도구를 어떤 방식으로 돌리고 있느냐에 따라 갈려요.

환경 PHP 패치는 누가 위험도
워드프레스·그누보드·XE 홈페이지
(서버나 VPS를 직접 운영)
사용 내가 직접 높음
같은 홈페이지인데 웹호스팅 이용 사용 호스팅 업체 업체에 패치 여부 확인
phpMyAdmin, 웹메일(Roundcube), Nextcloud 같은 사내 웹 도구 사용 내가 직접 높음 (외부에 열려 있으면 특히)
NAS 웹 기능에 올린 사이트·관리 페이지 사용 NAS 패키지 업데이트 중간~높음
블로그 플랫폼·사이트 빌더
(티스토리, 네이버 블로그 등)
플랫폼이 관리 플랫폼 할 일 없음
자바(스프링)·Node.js·ASP.NET으로 만든 사이트 안 씀 - 해당 없음
개발용으로 PC에 깐 XAMPP·APM 사용 내가 직접 외부에 안 열려 있으면 낮음

표에서 "내가 직접"이 하나라도 걸리면 이 글을 끝까지 보시면 돼요. 그래서 제일 궁금할 두 가지만 추려 봤어요. "내가 쓰는 버전도 위험한가?" 그리고 "당장 못 올리면 뭘 해야 하나

?"

얼마나 심각한 건데요?

CVE-2026-109618, CVE-2026-109619 두 건이고 심각도는 둘 다 9.2점이에요. 로그인도 필요 없고, 요청 한 번만 잘 보내면 서버에서 공격자 코드를 실행할 수 있다고 해요. 게다가 홈페이지 프로그램이 실행되기도 전에 공격이 들어온다는 게 문제예요.

원리를 식당에 비유하면 이해가 쉬워요. PHP는 요청 하나를 처리할 때 쓸 수 있는 메모리 양이 정해져 있어요. 공격자는 일부러 무거운 요청을 보내서 이 한도를 넘기게 만들어요. 그러면 PHP가 처리를 급하게 멈추는데, 이때 쓰던 자리를 다 치우지 못하고 일부 데이터를 그대로 남겨 둬요. 손님이 급하게 나가서 테이블에 접시가 그대로 있는 상태인 거죠.

문제는 다음 손님, 그러니까 다음 요청이 같은 테이블에 앉는다는 거예요. 공격자가 바로 이어서 보낸 두 번째 요청이 남아 있던 데이터를 건드리게 만들고, 그걸 이용해 서버에서 원하는 명령을 실행하는 방식이에요.

원 연구팀은 워드프레스, Drupal, Joomla, phpMyAdmin, Nextcloud, Roundcube 같은 유명한 프로그램에서 실제로 공격이 되는 걸 확인했대요. 기본 설정 그대로여도요.

그리고 이게 중요한데, 워드프레스나 플러그인을 업데이트해도 안 막혀요. 구멍이 PHP 자체에 있어서 PHP를 올려야 해요.

내 버전도 위험한가요?

웹 요청을 처리하는 PHP라면 사실상 다 대상이에요. PHP-FPM이든 아파치 mod_php든 LiteSpeed든 상관없고, 그중에서도 mod_php가 제일 위험하다고 공식 공지에 나와 있어요. 버전으로 보면 PHP 5.4 이후 거의 전부가 걸려요. 판정은 표 하나로 끝나요.

8.2~8.5를 쓰고 있다면 표에 있는 버전 이상으로만 올리면 돼요. 7.4~8.1은 PHP 쪽 공식 지원이 이미 끝나서, 우분투나 레드햇 같은 배포판이 따로 패치를 넣어 줬는지 확인해야 하고요. 5.x는 패치 자체가 없어요.

버전 확인은 서버에서 한 줄이면 돼요.

📋 PHP 버전 확인 (리눅스)
php -v

근데 여기서 한 번 속기 쉬운 게, 터미널에서 나오는 버전이랑 웹에서 실제로 쓰는 버전이 다를 수 있어요. 워드프레스라면 관리자 화면 → 도구 → 사이트 상태 → 정보 → 서버에 웹에서 쓰는 PHP 버전이 나와요. 이쪽을 기준으로 보는 게 정확해요.

숫자가 낮다고 무조건 위험한 건 아니에요

우분투, 데비안, 레드햇 계열 패키지는 버전 숫자는 그대로 두고 보안 패치만 끼워 넣는 경우가 많거든요. 그래서 php -v에 8.1이 찍혀도 이미 패치됐을 수 있어요. 이럴 땐 패키지 변경 기록에 CVE 번호가 있는지를 보면 돼요. 뭔가 나오면 패치된 거예요.

📋 데비안·우분투: 패치 여부 확인
apt changelog php8.1 | grep CVE-2026-109618
📋 레드햇·록키·알마: 패치 여부 확인
rpm -q --changelog php | grep CVE-2026-109618

php8.1 부분은 쓰는 버전에 맞게 바꾸면 돼요. 참고로 remirepo 저장소에서 PHP를 받아 쓰는 경우엔 공지 시점에 아직 패치가 안 올라와 있었다고 하니 따로 확인해 보세요.

헷갈리면 이 순서대로

웹호스팅을 쓰고 있다면 PHP는 보통 업체가 관리하니까 업체에 패치했는지 물어보는 게 제일 빨라요. 서버를 직접 운영한다면 홈페이지 서버만 보지 말고 PHP가 숨어 있는 곳도 같이 떠올려 보세요. NAS의 웹 기능, phpMyAdmin, 사내 그룹웨어나 웹메일, 업체가 설치해 준 관리 페이지 같은 것들요. 이런 데가 의외로 오래된 PHP로 돌아가는 경우가 많거든요.

업데이트했으면 재시작까지

패키지만 올리고 끝내면 안 돼요. 이미 떠 있는 PHP 프로세스는 옛날 코드를 그대로 물고 있어서, php-fpm이나 아파치를 재시작해야 패치가 실제로 적용돼요.

📋 재시작 (서비스 이름은 환경에 맞게)
sudo systemctl restart php8.3-fpm
sudo systemctl restart apache2

우리 서버가 mod_php인지 PHP-FPM인지 모르겠으면 아래로 확인할 수 있어요. 첫 줄에 php 모듈이 보이면 mod_php, 두 번째에서 서비스가 돌고 있으면 FPM이에요.

📋 구동 방식 확인
apachectl -M | grep php
systemctl status 'php*-fpm'

당장 못 올리면? 대안 4가지

솔직히 운영 서버는 오늘 당장 PHP 버전을 못 올리는 경우도 많죠. 호환성 테스트도 해야 하고요. PHP 공식 공지에도 "완전한 대책은 없고 업데이트만이 안전하다"고 못 박혀 있긴 한데, 그 사이에 위험을 줄일 방법은 있어요.

임시 설정은 php.ini에 두 줄을 넣는 방법이에요. 업로드 진행률 기능을 끄고 메모리 한도를 풀어서, 공격이 이용하는 "메모리 초과로 요청이 끊기는 순간" 자체를 줄이는 거죠. 대신 메모리 상한이 없어지니까 서버 메모리가 바닥날 수 있어요. 패치 전까지 잠깐만 쓰는 용도예요.

📋 php.ini 임시 설정 (PHP-FPM 기준, 적용 후 재시작)
session.upload_progress.enabled = 0
memory_limit = -1

mod_php는 memory_limit = -1만 해당돼요. 지금 설정값이 뭔지는 이걸로 볼 수 있어요.

📋 현재 설정값 확인
php -i | grep -E "upload_progress|memory_limit|post_max_size|opcache.enable"

WAF는 클라우드플레어를 쓰고 있다면 따로 할 게 없어요. 무료 요금제에도 차단 규칙이 자동으로 들어가 있어요. 다만 공격자들이 우회하려고 요청 모양을 계속 바꾸고 있다고 하니, 이것만 믿고 패치를 미루면 안 돼요. 업로드 크기 제한도 같이 걸어 두면 좋아요.

외부 노출 차단은 마지막 카드예요. phpMyAdmin 같은 관리 화면은 원래 바깥에 열어 둘 이유가 없으니 이참에 내부망에서만 열리게 막아 두세요. 너무 오래된 버전이라 패치할 방법이 없는 서버라면 잠시 내리는 것도 방법이에요. 영국 국가사이버보안센터(NCSC)도 패치 못 하는 시스템은 오프라인까지 고려하라고 했더라고요.

하고싶지 않았지만 찐 작업 사례 : 구형 시놀로지 NAS에서 PHP 7.4 빼기

이 글을 올리고 나서 저도 회사 장비를 하나씩 확인해 봤는데, 딱 하나가 걸리더라고요. 사내 점검표 웹 하나 돌리려고 시놀로지 NAS에 Web Station이랑 PHP 7.4를 올려 둔 게 있었거든요. 위 판정표로 보면 빨간 줄, 공식 패치가 없는 버전이에요.

문제는 업데이트 버튼이 아예 없다는 거였어요. 이 NAS는 DSM 6.2인데, 6.2 패키지 센터에서 받을 수 있는 PHP가 7.4까지예요. 더 높은 PHP를 쓰려면 DSM부터 7.2로 올려야 하는데 그게 말처럼 간단하지가 않죠.

작은 회사다 보니 NAS 한 대가 파일 서버에 백업, 부서별 공유 폴더까지 다 떠안고 있어요. DSM을 메이저 버전으로 올리면 설치된 패키지가 그대로 도는지, 공유 폴더 권한이 유지되는지, 백업 작업과 직원 PC 연결은 괜찮은지 전부 다시 봐야 하는데 그 영향도 검토가 아직 끝나지 않았어요. 검토도 안 된 상태에서 보안 패치라고 덜컥 올렸다가 파일 서버가 멈추면 보안취약점 보다 제가 먼저 머리 구멍 뚫릴 것 같아서  DSM은 그대로 두고 PHP만 바꾸는 쪽으로 방향을 잡았어요.

방법 판단
그대로 두고 임시 설정 이번 CVE는 버틸 수 있어도 지원 끝난 PHP가 계속 남아요
DSM 7.2로 업그레이드 영향도 검토가 끝나야 할 수 있어서 보류
남는 PC로 옮기기 후보가 출입 보안 장비를 관리하는 PC뿐이었어요. 점검표 때문에 보안 장비 PC를 사내 전체에 여는 꼴이라 뺐어요
NAS에 Docker로 PHP만 최신 DSM은 그대로 두고 PHP는 8.4.27. 이걸로 결정

Docker로 옮기다 걸린 함정

처음엔 금방 끝날 줄 알았어요. 공식 php 아파치 이미지 하나 띄우면 되겠지 했는데, 컨테이너가 켜지자마자 꺼지고 다시 켜지기를 계속 반복하더라고요. 로그에는 이 줄만 찍혀 있었어요.

📋 컨테이너 로그에 반복된 오류
AH00141: Could not initialize random number generator

원인은 DSM 6.2의 리눅스 커널이었어요. 커널이 3.10으로 꽤 오래된 버전이라, 최신 아파치가 켜질 때 쓰는 난수 기능을 지원하지 않거든요. 재밌는 건 PHP는 같은 커널에서 멀쩡히 돈다는 거예요. PHP는 그 기능이 없으면 다른 방법으로 알아서 넘어가는데, 아파치는 그냥 포기하고 꺼져 버리는 거죠. DSM 6.2를 쓰는 시놀로지라면 똑같이 겪을 거예요.

그래서 아파치를 빼고 nginx 컨테이너 하나, PHP-FPM 컨테이너 하나로 나눴어요. 둘 다 alpine 이미지라 용량도 합쳐서 60MB 남짓밖에 안 되더라고요.

옮기면서 챙긴 것들

  • 내부망 NAS라면 이미지를 손으로 옮겨야 해요. 인터넷 되는 PC에서 이미지를 tar 파일로 받아 File Station으로 올리고, Docker 이미지 메뉴의 "파일에서 추가"로 불러왔어요.
  • PHP는 Web Station이 쓰던 계정 번호로 돌렸어요. 제 NAS에선 http 계정이 1023번이었는데, 컨테이너 PHP도 이 번호로 실행하니 기존 기록 파일 권한을 하나도 안 건드려도 되더라고요. 번호는 File Station에서 파일 소유자를 보면 나와요.
  • nginx는 .htaccess를 읽지 않아요. 아파치 시절 .htaccess로 막아 두던 설정 파일이나 기록 폴더는 nginx 설정에 따로 막아 줘야 해요. 이걸 빼먹으면 기록 파일이 주소만 치면 그대로 열려요.
  • 코드 폴더는 읽기 전용으로 연결했어요. 쓰기는 기록 폴더만 열어 뒀어요. 혹시 뚫리더라도 코드를 바꿔치기할 수는 없게요.
📋 nginx: .htaccess 대신 막는 규칙 (경로는 환경에 맞게)
location ~ /\. { deny all; }
location ^~ /app/data/ { deny all; }
location ~ ^/app/(config|lib)\.php$ { deny all; }

다 띄운 다음엔 기존 주소랑 새 주소 화면을 비교해 보고, 막아야 할 파일이 정말 403으로 막히는지까지 확인했어요. 그러고 나서 Web Station이랑 PHP 7.4 패키지를 중지했고요. 삭제는 안 하고 중지만 해 뒀어요. 문제가 생기면 "실행" 한 번으로 되돌릴 수 있게요.

아쉬운 점도 있어요. DSM 6.2용 Docker 패키지도 업데이트가 끝난 버전이라, PHP는 최신이 됐어도 그 밑의 DSM이랑 Docker는 옛날 그대로예요. 내부망이라 다음 패치 때도 이미지를 또 손으로 옮겨야 하고요. 그래도 패치할 방법이 없는 PHP를 계속 열어 두는 것보단 훨씬 마음이 편하더라고요. DSM 업그레이드는 영향도 검토가 끝나면 그때 다시 정하려고요.

혹시 이미 당했으면 어떡하죠?

실제 공격이 있었는지는 아직 말이 좀 엇갈려요. 클라우드플레어는 고객사를 노린 공격 트래픽을 봤다고 했고, 다른 보안업체도 자기 미끼 서버에서 공격을 관측했다고 했어요. 반면 미국 CISA의 실제 악용 목록에는 아직 안 올라왔고요. 어느 쪽이든 10월 21일 전후 로그는 한번 훑어보는 게 마음 편해요.

특히 업로드 폴더에 모르는 .php 파일이 생겼다면 웹셸일 가능성이 높아요. 최근 며칠 사이에 바뀐 PHP 파일은 이렇게 찾을 수 있어요.

📋 최근 3일 사이 바뀐 PHP 파일 찾기
find /var/www -name "*.php" -mtime -3

수상한 게 나오면 서버를 바로 내리고, wp-config.php에 들어 있는 DB 비밀번호나 API 키부터 바꾸세요. 공격 코드는 웹서버 계정 권한으로 돌아가서 바로 관리자 권한을 따는 건 아니지만, 그 계정이 읽을 수 있는 파일은 다 봤다고 생각하는 게 안전해요.

1인 전산팀 체크리스트

  1. PHP가 돌아가는 서버, NAS, 관리 화면 목록 만들기
  2. 버전 확인. 배포판 패키지는 CVE 번호로 패치 여부 확인
  3. mod_php 서버부터 업데이트하고 재시작
  4. 못 올리는 곳은 임시 설정 + WAF + 외부 노출 차단
  5. 10/21 전후 로그에서 메모리 초과 오류, 프로세스 종료 확인
  6. 업로드 폴더 웹셸 점검하고 결과는 점검 기록으로 남기기

마지막 줄은 은근히 중요해요. 나중에 보안 점검이나 감사 때 "그때 뭐 했냐"는 질문이 꼭 나오거든요. 확인한 날짜랑 버전만 적어 둬도 할 말이 생겨요. 저도 이번에 옮긴 날짜랑 버전, 확인 결과를 문서 한 장으로 남겨 뒀어요.

참고한 곳

728x90
반응형

관련글 더보기