Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095 — Struts2 취약성 S2-045, S2-055 및 Jackson 취약성 CVE-2017-7525, CVE-2017-15095 조사 보고 | Kitploit
도구
/
GitHubGitHub
/secureskytechnology
/study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095
Vulnerability AnalysisCode AnalysisWeb Application ExploitationPapers & ResearchLearning & EducationArchived
GitHubsecureskytechnology/study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095

study-struts2-s2-054_055-jackson-cve-2017-7525_cve-2017-15095

Struts2 취약성 S2-045, S2-055 및 Jackson 취약성 CVE-2017-7525, CVE-2017-15095 조사 보고

저장소 보기
10621148년 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Struts2의 취약성 S2-054, S2-055 및 Jackson의 취약성 CVE-2017-7525, CVE-2017-15095 조사 보고

요점만 정리하여 읽기 쉽게 만든 요약 기사를 공개했습니다. 먼저 개요를 알고 싶거나 시간이 없는 분들께 추천합니다.

  • SSTtechlog 08 S2-054, S2-055 및 jackson-databind의 취약성 CVE-2017-7525, CVE-2017-15095에 대해 | SST 주식회사 시큐어스카이 테크놀로지
    • https://www.securesky-tech.com/column/techlog/08.html

2017년 12월 1일에 Struts2의 보안 업데이트가 공개되었습니다. 공개 전부터 Jackson(Java에서 인기 있는 JSON 라이브러리)의 취약성이 관련되어 있다는 이야기가 메일링 리스트에 흘러, 사내 시스템이나 도구에서 Jackson을 사용하고 있는 필자도 구체적으로 어떤 내용인지 신경 쓰고 있었습니다.

  • https://lists.apache.org/thread.html/ed74083f2d7187e71ee5ed644c5e45ba58d0792b515d1d1cc28bfadf@%3Cdev.struts.apache.org%3E

실제로 공개된 내용으로는, 다음 2가지 보안 문제가 수정되었습니다. Jackson의 컴포넌트인 jackson-databind의 취약성이 영향을 미치는 것은 S2-055뿐입니다.

  • S2-055 : https://cwiki.apache.org/confluence/display/WW/S2-055
    • 이것이 jackson-databind의 CVE-2017-7525에 대응한 수정입니다.
    • Struts 측의 의존 관계에서 jackson-databind를 2.9.2로 업데이트했습니다. 이로서 후술할 CVE-2017-15095에도 대응합니다.
    • https://cwiki.apache.org/confluence/display/WW/Version+Notes+2.5.14.1
  • S2-054 : https://cwiki.apache.org/confluence/display/WW/S2-054
    • 이것은 REST 플러그인에서 JSON-lib(http://json-lib.sourceforge.net/)라는 오래된 JSON 라이브러리를 사용하고 있었지만, DoS 문제가 지적되어 Jackson으로 변경한 수정입니다.

REST 플러그인에서는 이전부터 JSON-lib을 사용한 handler와 Jackson을 사용한 handler가 내장되어 있어, 사용자가 선택할 수 있었던 것 같습니다. S2-054에서 기본 handler를 Jackson으로 전환하고,さらに S2-055에서 Jackson의 버전이 오래된 것을 최신으로 한 것이 이번 수정의 전모라고 생각됩니다.

그렇다면 CVE-2017-7525는 어떤 취약성일까요? 필자 자신도 평소 Java로 JSON 처리를 할 때 Jackson을 사용하고 있어, 12월 2, 3일 주말을 이용하여 이 문제를 조사해 본 것이 본 기사입니다.


샘플 코드 검증에 사용한 필자의 환경:

  • OS : Windows 10 Pro 64bit
  • Java : Oracle JDK 1.8.0_92 64bit
  • Groovy : 2.3.1

jackson-databind의 취약성 CVE-2017-7525에 대해

Adam Caudill 씨의 블로그에서 CVE-2017-7525의 해설이 공개되었습니다.

  • https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/

필자 자신의 말로 대략 정리하면, jackson-databind는 JSON을 Java 객체에 매핑하는 기능(ObjectMapper 클래스)을 제공합니다. 여기서 ObjectMapper.enableDefaultTyping()을 호출함으로써, JSON에 고유하게 내장된 클래스 이름으로 매핑하는 것이 가능해집니다. 「입력 JSON 중에서 클래스 이름을 지정 가능」이라는 시점에서 불길한 예감이 들었던 분도 있을 것이라고 생각합니다. 바로 그 나쁜 예감이 적중한 것이 CVE-2017-7525입니다.

취약성 설명에 들어가기 전에, 애초에 왜 그러한 기능이 구현되었는지 설명하겠습니다.

ObjectMapper.enableDefaultTyping() 기능에 대해

jackson-databind에 의한 deserialize의 기본적인 사용법은 다음 샘플 코드를 확인해 주십시오.(본 기사에서는 Jackson의 샘플 코드에 Groovy를 사용하고 있습니다. @Grab으로 jackson-databind의 버전을 간단히 전환할 수 있어 편리합니다.)

  • objectmapper-demo.groovy

위 샘플 코드에서는 단순히 "animal" 키가 그대로 Animal 클래스에 매핑 가능합니다. 그렇다면, 다음과 같은 경우는 어떨까요?```java class Zoo { Animal animal; }

abstract class Animal { String name; protected Animal() { } }

class Dog extends Animal { double barkVolume; Dog() { } }

class Cat extends Animal { boolean likesCream; int lives; Cat() { } }

この構成では、"animal"のキーの中身がDogクラスを指す場合と、Catクラスを指す場合の2種類が出てきてしまいます。したがって、どちらのクラスでマッピングするのか追加の情報が必要となります。

これを解決するため、jackson-databindではJSONにマッピングするクラス名を埋め込める独自処理を組み込みました。
例えば以下のように、"animal"キーの中身を配列にしてしまい、最初の要素にクラス名を指定します。```
{"animal":["Dog",{"name":"dog1","barkVolume":1.2}]}

これにより ObjectMapper.readValue() は "animal" キーの中身が Dog クラスだと認識してマッピングを行います。 もちろん、そのままでは "animal" キーの中身がもともと配列だったのか、jackson-databind独自のクラス名情報が含まれたものなのか、判別できません。 これを切り替えるのが ObjectMapper.enableDefaultTyping() メソッドになります。 他にも @JsonTypeInfo アノテーションをクラスに定義する方法もあります。詳細は以下のJacksonドキュメントを参照してください。

  • JacksonPolymorphicDeserialization
    • https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization

実際に ObjectMapper.enableDefaultTyping() メソッドを使ったサンプルコードを次に示します。

  • enable-default-type-demo.groovy

클래스명 black list 검사에 의한 CVE-2017-7525 대응

지금까지 살펴본 바와 같이, 클래스명에 이어 그 프로퍼티를 JSON으로 제공함으로써, 어느 정도 제한은 있지만 임의의 클래스를 임의의 프로퍼티로 생성하는 것이 가능합니다. 이를 악용한 것이 CVE-2017-7525 취약점이며, 계기가 된 것은 아마도 다음 보고서로 보입니다.

  • Java Unmarshaller Security - Turning your data into code execution
    • https://github.com/mbechler/marshalsec

Jackson 등 Java에서 자주 사용되는 serialize/deserialize 라이브러리에 대해, 클래스명 등의 조작으로 임의 코드 실행으로 이어질 위험이 보고되었으며, 실제로 어떤 클래스가 위험한지 구체적인 클래스명이 목록화되어 있습니다.

이에 따른 것인지는 모르겠지만, 날짜상으로는 위 저장소의 1st commit 직후, jackson-databind에서 다음 Issue가 제기되어 대응이 시작되었습니다.

  • Jackson Deserializer security vulnerability
    • https://github.com/FasterXML/jackson-databind/issues/1599

실제로 이 취약점을 찌르는 JSON 데이터와 Java 코드는 어떤 모습일까요? 이 Issue에서 대응된 jackson-databind 2.8.9의 테스트 코드에 힌트가 있습니다:

  • https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.8.9/src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java

이 테스트 코드를 바탕으로, 동작 확인이 가능하도록 조정한 샘플 코드를 다음에 나타냅니다.

  • cve-2017-7525-check.groovy

@Grab 에서 2.8.9를 지정하여 실행하면 your jackson version IS SAFE to CVE-2017-7525 라고 표시됩니다. 이는 2.8.9의 수정으로 인스턴스화되는 클래스명 지정에 blacklist 검사가 추가되었기 때문입니다. 여기서 @Grab 에 2.8.8을 지정하여 실행하면 다음과 같이 출력됩니다.``` your jackson version MAY NOT BE SAFE to CVE-2017-7525 com.fasterxml.jackson.databind.JsonMappingException: N/A at [Source: { "id" : 124, "obj" : [ "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl", { "transletBytecodes" : [ "AAIAZQ==" ], "transletName" : "a.b", "outputProperties" : { } } ] } ; line: 9, column: 28] (through reference chain: Bean1599["obj"]->com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl["outputProperties"]) at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:277) (...) at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:128) Caused by: java.lang.NullPointerException at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$1.run(TemplatesImpl.java:401) at java.security.AccessController.doPrivileged(Native Method) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.defineTransletClasses(TemplatesImpl.java:399) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance(TemplatesImpl.java:451) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:486) at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties(TemplatesImpl.java:507) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.fasterxml.jackson.databind.deser.impl.SetterlessProperty.deserializeAndSet(SetterlessProperty.java:116) ... 30 more null

출력 결과 중 `at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$1.run(TemplatesImpl.java:401)` 라는 행이 있습니다.  
이 샘플 코드에서는 NullPointerException이 throw되었지만, 메서드명으로 보아 무언가 부작용을 포함한 처리가 발생하고 있음을 알 수 있습니다.

실제로 코드 실행을 성공시키는 JSON을 구성하려면 추가 조사가 필요할 것으로 보입니다.  
본 글에서는 일단 여기까지만 소개하지만, 추가 조사 글이 다른 사이트에서 공개되면 여기에도 추가하도록 하겠습니다.

그런데 중요한 black list는 어디에서 구현되어 있을까요? 다음 클래스입니다.  
* https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.8.9/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java#L51

사실 2.8.9 시점에서는 이 black list에 누락이 있었던 것으로 보입니다. 그 문제가 CVE-2017-15095입니다.

### black list를 개선한 CVE-2017-15095 대응
도구 다운로드