Back
Featured image of post Spring4Shell 취약점 정리

Spring4Shell 취약점 정리

1. Spring4Shell 개요

  • Spring Core 프레임워크에서 특정 조건 하에 RCE(Remote Code Execution)가 가능한 취약점
  • Spring 프레임워크가 매개변수를 바인딩하는 과정에서 ‘class’ 객체가 노출되어 발생
  • 공격자는 해당 ‘class’ 객체에서 로깅 관련 기능을 사용해 웹 쉘 코드를 업로드하여 명령어를 실행 가능

2. 취약점 POC

(1) 테스트 환경

  • JDK 11
  • tocat-9.0.59
  • Spring Framework 5.3.15

(2) 매개변수 바인딩과 사용자 접근

Spring에서는 POJO(Plain Old Java Object)라고 불리는 일반 자바 객체의 속성에 URL을 통해 입력된 매개변수를 매핑하여 사용할 수 있습니다.

// 객체클래스
public class Greeting {
	private long id;
	private String content;
	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;
	}
}
//컨트롤러
@Controller
public class HelloController {
    @GetMapping("/greeting")
    public String greetingForm(Model model) {
        model.addAttribute("greeting", new Greeting());
        return "hello";
    }
    @PostMapping("/greeting")
    public String greetingSubmit(@ModelAttribute Greeting greeting, Model model) {
        return "hello";
    }
}

위와 같이 Greetring이라는 객체와 Controller를 생성하면 가정한다면 일반적인 사용자는 “http:///greeting?id=test&content=test”과 같은 URL로 접근할 수 있습니다.

(3) 취약점 공격

해당 취약점은 특정 상황에서 ‘class’라는 특수한 변수가 사용자에게 노출될 때 발생합니다. 현재 공개된 방식은 ‘classLoader’를 사용하여 Tomcat 로그를 이용하여 JSP 웹 쉘을 생성하는 방식입니다.

1) 취약한 도커 이미지 실행

docker build . -t spring4shell && docker run -p 8080:8080 spring4shell

2) POC 코드 실행

python exploit.py --url "http://localhost:8080/helloworld/greeting"
2-1) POC 코드 실행 시 Body에 class의 로깅 관련 객체가 사용되는 것을 확인할 수 있습니다. ‘class.module.classLoader.resources.context.parent.pipeline.first.pattern’ 매개 변수에 웹 쉘 코드를 담아 보내는 것을 확인할 수 있습니다.

2-2) POC 코드가 정상적으로 실행이 됐을 경우 웹 쉘 파일이 서버에 생성되는 것을 확인할 수 있습니다.

$ find -name shell.jsp
./usr/local/tomcat/webapps/ROOT/shell.jsp

3) 웹쉘 접속 * 명령어 실행

생성한 웹 쉘에 원하는 명령어를 파라마터에 대입하여 요청할 경우 실행되는 것을 확인할 수 있습니다.

3. 영향받는 버전

CVE-2022-22965(Spring4Shell) ■ JDK 9 이상의 Spring 프레임워크 사용하는 경우

  • Spring Framework 5.3.0 ~ 5.3.17
  • Spring Framework 5.2.0 ~ 5.2.19
  • 및 이전 버전 ※ JDK 8 이하의 경우 취약점의 영향을 받지 않음

4. 취약한 버전 확인 방법

(1) Java 버전 확인

: java -version

(2) Spring 버전 확인

1) pom.xml 내 확인

2) getVersion() 메서드를 사용 확인

public class CheckSpringVersion{
	@Test
	public void versionTest() throws Exception{
		String test=org.springframework.core.SpringVersion.getVersion();
		System.out.println(test);
	}
}

5. 대응방안

  • 제조사 홈페이지를 통해 최신버전으로 업데이트 적용
    • 제조사 홈페이지에 신규버전이 계속 업데이트되고 있어 확인 후 업데이트 적용 필요
  • CVE-2022-22965(Spring4Shell)
    • Spring Framework 5.3.18, 5.2.20 버전으로 업데이트
  • 신규 업데이트가 불가능할 경우 아래와 같이 조치 적용
  • CVE-2022-22965(Spring4Shell) ※ 프로젝트 패키지 아래 해당 전역 클래스 생성 후 재 컴파일(테스트 필요)
import org.springwork.core.Ordered;
import org.springwork.core.annotation.Order;
import org.springwork.web.bind.WebDataBinder;
import org.springwork.web.bind.annotation.ControllerAdvice;
import org.springwork.web.bind.annotation.InitBinder;
 
@ControllerAdvice
@Order(10000)
public class BinderControllerAdvice {
	@InitBinder
	public setAllowedFields(WebDataBinder dataBinder) {
		String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};
		dataBinder.setDisallowedFields(denylist);
	}
}

※ 참고 ※

https://uxicode.tistory.com/entry/%EB%B0%94%EC%9D%B8%EB%94%A9%EC%9D%B4%EB%9E%80
https://velog.io/@thelm3716/spring4shell-%EB%B6%84%EC%84%9D-%EA%B8%80-%EC%A0%95%EB%A6%AC-CVE-2022-22965
https://www.fastly.com/blog/spring-has-sprung-breaking-down-cve-2022-22963-and-spring4shell-cve-2022
https://unit42.paloaltonetworks.com/cve-2022-22965-springshell/
https://www.krcert.or.kr/data/secNoticeView.do?bulletin_writing_sequence=66592
https://javamana.com/2022/04/202204022300005716.html
https://www.lunasec.io/docs/blog/spring-rce-vulnerabilities/
https://hackyboiz.github.io/2022/04/03/l0ch/2022-04-03/
https://snyk.io/blog/spring4shell-zero-day-rce-spring-framework-explained/
https://github.com/reznok/Spring4Shell-POC

comments powered by Disqus