파일 업로드 취약점 및 RCE 공격 원리: 서버 권한을 탈취하는 웹쉘의 치명적 메커니즘

파일 업로드 취약점을 이용한 RCE(원격 코드 실행) 공격은 공격자가 서버 측 검증 로직을 우회해 악성 스크립트(웹쉘)를 업로드하고, 이를 서버에서 실행시켜 시스템 명령어를 제어하는 과정이다. 전체 과정은 기능 탐지, 검증 우회, 웹쉘 업로드, 실행 트리거, 그리고 최종적인 권한 상승 단계로 이어진다.

파일 업로드 취약점의 정의와 영향도

파일 업로드 취약점은 사용자가 서버로 파일을 전송하는 기능에서 입력값 검증이 미흡할 때 발생한다. OWASP는 이 취약점을 심각도 High, 발견 가능성 High, 보편성 Common으로 분류하며, 이는 웹 애플리케이션에서 매우 빈번하게 발생하면서도 파급력이 크다는 뜻이다. 공격자가 이 취약점을 성공적으로 이용했을 때의 결과는 단순한 서비스 거부(DoS)나 클라이언트 사이드 공격을 넘어, 서버의 완전한 시스템 장악(complete system takeover)이라는 최악의 시나리오로 이어진다.

최근 보안 사례를 보면 이 취약점의 위험성이 명확히 드러난다. 2023년 7월 YouTube의 Exploits Simplified 채널에 보고된 Bug Bounty 사례에 따르면, 파일 업로드를 통한 RCE 공격으로 단일 건에 대해 $15,000의 바운티가 지급된 사례가 있다. 이는 기업들이 파일 업로드 취약점을 얼마나 심각한 보안 위협으로 간주하는지를 보여주는 구체적인 수치이다.

이 취약점은 단순히 RCE에만 그치지 않고 다양한 공격 벡터로 확장된다. 업로드된 파일 내에 악성 스크립트를 삽입해 Stored XSS를 유발하거나, XML 파일로 XXE 인젝션을 수행할 수 있다. 나아가 크로스사이트 콘텐츠 하이재킹이나 기존의 중요한 시스템 파일을 덮어쓰는 디렉토리 오버라이트 공격으로 이어져 백엔드 시스템 전체를 마비시킬 수 있다.

파일 업로드 및 RCE 공격 원리를 무력화하는 검증 우회 기법

서버는 보통 파일 확장자나 Content-Type으로 업로드 파일을 검증하지만, 공격자는 다양한 기법으로 이 방어 체계를 무력화한다. 가장 기초적인 방법은 Content-Type 헤더 변조이다. Burp Suite Repeater와 같은 도구를 사용해 multipart/form-data 요청 내의 Content-Type을 text/php에서 image/jpeg로 변경하면, 서버가 실제 파일 내용이 아닌 헤더 값만 검증할 때 공격에 성공한다.

확장자 검증을 우회하는 기법은 더욱 정교하게 발전해 왔다. PortSwigger와 OWASP의 자료를 종합하면 다음과 같은 구체적인 우회 전략이 사용된다.

  1. 대소문자 혼용: 검증 로직이 대소문자를 구분(case-sensitive)하지만 실행 로직이 구분하지 않는 경우 exploit.pHp와 같이 업로드한다.
  2. 이중 확장자: Apache 서버 등 일부 환경에서 첫 번째 확장자를 기준으로 실행하는 특성을 이용해 exploit.php.jpg 형태로 전송한다.
  3. 후행 문자 삽입: Windows 환경에서 파일명 끝의 점(.)이나 공백을 자동으로 제거하는 특성을 이용하여 exploit.php. 또는 exploit.php로 업로드한다.
  4. URL 인코딩 및 Null 바이트: %2Ephp와 같이 인코딩하거나, C/C++ 기반 저수준 함수가 Null 문자 이후를 무시하는 점을 이용해 exploit.asp%00.jpg 형태로 전송한다.
  5. 대체 확장자 활용: .php5, .pht, .phtml, .shtml 등 블랙리스트에서 누락된 실행 가능 확장자를 탐색하여 업로드한다.
  6. 재귀적 치환 우회: 서버가 .php 문자열을 찾아 제거하는 로직을 가졌다면 exploit.p.phphp와 같이 구성하여 치환 후에도 .php가 남도록 설계한다.

고도화된 공격자는 파일 내용(Magic Bytes) 검증까지 우회한다. ExifTool 등을 사용해 JPEG 파일의 고유 헤더인 FF D8 FF를 유지하면서, 메타데이터 영역에 악성 PHP 코드를 삽입하는 폴리글롯(Polyglot) 파일을 생성한다. .htaccessweb.config 파일을 업로드해 서버 설정 자체를 변경함으로써 임의의 확장자를 실행 가능한 MIME 타입으로 매핑하는 서버 설정 오버라이드 기법을 사용하기도 한다.

우회 카테고리 주요 기법 공격 원리 및 타겟
헤더 변조 Content-Type 조작 MIME 타입 검증만 수행하는 서버를 대상으로 헤더를 image/jpeg 등으로 위장
확장자 조작 이중 확장자, Null 바이트 Apache의 확장자 해석 방식이나 C 언어의 문자열 처리 특성 이용
내용 위장 폴리글롯(Polyglot) 파일 파일 시그니처(Magic Bytes)를 유지하며 메타데이터에 페이로드 삽입
설정 변경 .htaccess 업로드 서버 구성 파일을 수정하여 특정 확장자의 실행 권한을 강제로 부여

웹쉘 업로드를 통한 RCE 실전 공격 과정

검증 우회에 성공했다면 다음 단계는 서버에서 실행될 악성 스크립트인 웹쉘(Web Shell)을 업로드하는 것이다. 웹쉘은 공격자가 원격에서 시스템 명령어를 실행할 수 있게 해주는 인터페이스 역할을 한다. 가장 단순한 형태의 웹쉘은 <?php echo file_get_contents('/path/to/target/file'); ?>와 같이 특정 경로의 파일을 읽어오는 코드이며, 본격적인 RCE를 위해서는 <?php echo system($_GET['command']); ?>와 같이 쿼리 파라미터로 시스템 명령어를 전달받아 실행하는 코드가 사용된다.

실제 공격 시나리오에서는 공격자가 파일명을 exploit.php로 설정하고 Content-Type을 text/php로 지정하여 업로드한 뒤, 서버 내 저장 경로인 /avatars/exploit.php 등을 확인한다. 이후 GET /avatars/exploit.php?command=id HTTP/1.1과 같이 HTTP 요청을 전송하면, 서버 컨텍스트에서 id 명령어가 실행되어 현재 서버의 사용자 권한 정보가 응답으로 돌아온다.

특이한 사례로 Synack Red Team 연구원은 파일명 필드 자체에 페이로드를 삽입하는 기법을 시연했다. 파일 업로드 요청 시 filename 필드에 명령어를 포함시키고, 서버가 이를 처리하는 과정(예: 빌드 버튼 클릭)에서 명령어가 실행되는 방식이다. 만약 명령 실행 결과를 직접 확인할 수 없는 Blind RCE 환경이라면, DNS 서브도메인 쿼리를 활용한 Out-of-Band(OOB) 데이터 유출 기법이 사용된다. 예를 들어 whoami 명령의 결과값이 DNS 쿼리의 서브도메인 형태로 전송되도록 설계하여 공격자의 DNS 서버에서 결과물을 확인하는 방식이다.

RCE 달성 이후의 Post-Exploitation 단계에서는 서버 내 구성 파일(config files)을 분석해 데이터베이스 연결 정보나 API 키를 획득한다. 이를 바탕으로 동일 서버에 호스팅된 다른 웹 애플리케이션으로 접근을 확대하거나, 해당 서버를 피봇 포인트(Pivot Point)로 활용해 내부 네트워크의 다른 시스템을 공격하는 측면 이동(Lateral Movement)을 수행한다.

파일 업로드 취약점 방어 및 예방 방법

파일 업로드 취약점을 원천적으로 차단하려면 단순한 블랙리스트 방식의 필터링에서 벗어나 다층 방어 전략을 구축해야 한다. 가장 핵심적인 수칙은 허용된 확장자만 받는 화이트리스트(Allowlist) 방식을 적용하는 것이다. 파일명에 포함된 ../와 같은 디렉토리 트래버설 시퀀스를 엄격히 제거해 의도치 않은 경로에 파일이 저장되는 것을 막아야 한다.

실무적인 방어 구현 가이드는 다음과 같다.

  1. 파일명 난수화: 사용자가 업로드한 파일명을 그대로 사용하지 않고, UUID나 해시값으로 변경하여 저장함으로써 기존 파일 덮어쓰기 공격을 방지한다.
  2. 임시 샌드박스 활용: 파일의 완전한 검증이 끝나기 전까지는 영구 파일시스템이 아닌 격리된 임시 디렉토리에 저장한다. 최근 모던 프레임워크들은 이 방식을 채택하고 있으나, 개발자가 자체 로직을 구현할 경우 Race Condition 기반 우회가 가능하므로 주의가 필요하다.
  3. 실행 권한 제거: 업로드 디렉토리에 대해 웹 서버의 실행 권한(Execute Permission)을 완전히 제거하고, 스크립트 핸들러가 동작하지 않도록 설정한다.
  4. 보안 헤더 적용: Content-Disposition: Attachment 헤더를 추가하여 브라우저가 파일을 실행하지 않고 다운로드하도록 강제하며, X-Content-Type-Options: nosniff로 MIME 타입 스니핑을 방지한다.
  5. 인프라 제어: 파일 크기의 상한 및 하한을 설정하여 서비스 거부(DoS) 공격을 예방하고, 가급적 프레임워크 내장 검증 메커니즘을 사용해 구현 실수로 인한 취약점을 최소화한다.

Synack 전문가는 모든 외부 입력은 신뢰할 수 없다는 전제하에 기능을 설계해야 한다고 강조한다. DevSec Hacker 역시 펜테스트 수행 시 파일 업로드 기능이 다양한 취약점을 동시에 가질 가능성이 매우 높으므로 최우선 타겟으로 삼아야 한다고 조언한다.

파일 업로드 취약점은 단순한 설정 오류를 넘어 서버 전체의 제어권을 넘겨줄 수 있는 치명적인 위협이다. 개발자와 보안 담당자는 화이트리스트 기반의 검증, 파일명 난수화, 실행 권한 제어라는 3대 원칙을 철저히 준수해 RCE 공격 경로를 차단해야 한다. 지금 운영 중인 서비스의 파일 업로드 로직이 단순 확장자 체크에 의존하고 있지는 않은지 점검해 보자.

댓글 남기기