( 1 ) 취약점 정의
CVE-2022-42889 취약점은 2022년 10월 13일 Apache 사의 개발자 목록 게시판에 기재되었으며 최초로 Alvaro Munoz 님께서 발견 및 보고함.
해당 취약점은 Apache Commons Text 라이브러리 1.5 ~ 1.9 버전에서 원격코드 실행 취약점으로 안전하지 않은 변수 보간 기능으로 인해 취약점이 발생함.
Apache Commons Text 라이브러리는 변수 보간을 수행하여 속성을 동적으로 평가하고 확장할 수 있음.
보간을 위한 표준 형식은 "${prefix:name}" 이며 여기서 "prefix" 는 보간을 수행하는 org.apache.commons.text.lookup.StringLookup의 인스턴스를 조회하는 데 사용됨.
이러한 조회는 "script", "dns", "url" 보간기 개체를 기본값으로 사용하는 응용 프로그램에 악의적인 코드 삽입 시 원격코드 실행 취약점이 가능함.
"script" - JVM 스크립트 실행 엔진(javax.script)을 사용하여 표현식 실행
"dns" - dns 레코드 확인
"url" - 원격 서버를 포함하여 URL 에서 값 로드
CVSS3 9.8 점으로 위험한 취약점으로 분류되었으며 기본적으로 문제가 있는 보간기 개체를 비활성화되어 패치된 Apache Commons Text 1.10.0 으로 업그레이드를 권장함.
여기서 변수 보간(Variable Interpolation)이란 대체로 문자열 보간(string interpolation)으로 명명하며 ${변수명} 의 형식을 사용하여 문장에서 변수에 할당된 값이 들어가 출력되게 되는 프로그래밍 문법을 말함.
참고 사이트 :
https://en.wikipedia.org/wiki/String_interpolation
https://lemonlemon.tistory.com/m/153
영향받는 버전 :
Apache Commons Text 라이브러리 1.5 ~ 1.9 버전
( 2 ) 취약점 분석
시스템 자체에서 아래와 같이 "script" 보간기 개체를 이용한 계산기 프로그램을 실행하는 PoC 를 통해 디버그 과정 중 취약점 실행 분석함.
import
org.apache.commons.text.StringSubstitutor;
class Demo{
public static void main(String[] args){
StringSubstitutor stringSubstitutorInterpolator =
StringSubstitutor.createInterpolator();
String payload = "${script:js:new
java.lang.ProcessBuilder(\"calc\").start()}";
stringSubstitutorInterpolator.replace(payload);
} } |
< 테스트 PoC 실행 화면 >
먼저 StringSubstitutor.replace 메소드에서 후속 조치를 진행함.
public String replace(final String
source) {
if (source == null) {
return null;
}
final TextStringBuilder buf = new TextStringBuilder(source);
if (!substitute(buf, 0, source.length())) {
return source;
}
return buf.toString(); } |
Substitute 메소드는 들어오는 문자열을 구분 분석을 위해 호출함.
< Substitute 메소드 >
이 메소드는 처음과 끝 부분에서 ${} 문자열로 구문 분석하고 추가 분석을 위해 값을 추출함.
protected String resolveVariable(final
String variableName, final TextStringBuilder buf, final int startPos, final int
endPos) {
final StringLookup resolver = getStringLookup();
if (resolver == null) {
return null;
}
return resolver.lookup(variableName); } |
여기서 얻은 StringLookup 은 인스턴스화된 객체가 StringSubstitutor.createInterpolator() 를 사용하여 생성된 값임.
public static StringSubstitutor createInterpolator()
{
return new
StringSubstitutor(StringLookupFactory.INSTANCE.interpolatorStringLookup()); } |
그리고 생성자에서 this.setVariableResolver(variableResolver) 를 호출하여 VariableResolver 를 InterpolatorStringLookup 클래스로 설정한 후 계속해서 InterpolatorStringLookup 의 lookup 메소드를 추적함.
@Override public String lookup(String var)
{ //var="script:js:new
java.lang.ProcessBuilder("calc").start()"
if (var == null) {
return null;
}
final int prefixPos = var.indexOf(PREFIX_SEPARATOR);
if (prefixPos >= 0) {
final String prefix = toKey(var.substring(0, prefixPos));
final String name = var.substring(prefixPos + 1);
final StringLookup lookup = stringLookupMap.get(prefix);
String value = null;
if (lookup != null) { value = lookup.lookup(name);
}
if (value != null) { return value;
}
var = var.substring(prefixPos + 1);
}
if (defaultStringLookup != null) {
return defaultStringLookup.lookup(var);
}
return null; } |
이 lookup 메소드는 ":" 앞의 스크립트 문자열을 가로채 이를 인덱스로 사용하여 해당하는 StringLookup 개체를 가져옴.
< StringLookup 개체 >
시스템에서 지원하는 작업 유형이 18 가지임을 알 수 있음.
그런 다음 ScriptStringLookup.lookup 메소드를 호출함.
@Override public String lookup(final String key)
{
if (key == null) {
return null;
}
final String[] keys = key.split(SPLIT_STR, 2);
final int keyLen = keys.length;
if (keyLen != 2) {
throw IllegalArgumentExceptions.format("Bad script key format
[%s]; expected format is EngineName:Script.",
key);
}
final String engineName = keys[0];
final String script = keys[1];
try {
final ScriptEngine scriptEngine = new
ScriptEngineManager().getEngineByName(engineName);
if (scriptEngine == null) { throw new
IllegalArgumentException("No script engine named " + engineName);
}
return Objects.toString(scriptEngine.eval(script), null);
} catch (final Exception e) {
throw IllegalArgumentExceptions.format(e, "Error in script engine
[%s] evaluating script [%s].", engineName,
script);
} } |
다음은 js 스크립트 엔진을 가져와서 ScriptEngine.eval 메소드를 통해 코드를 실행시킴.
< ScriptEngine.eval 메소드 >
마지막으로 Apache Commons Text 1.10.0 버전으로 업데이트 시 "script", "dns", "url" 등 보간기 개체가 삭제됨을 확인함.
< Apache Commons Text 1.10.0 버전으로 업데이트 시 지원되는 보간기 개체 >
( 3 ) 취약점 방어
1. 최신 패치로 업그레이드함.
Apache Commons Text 1.10.0 버전으로 업그레이드
2. 보안장비에 Snort 패턴을 등록하여 모니터링 및 대응함.
현재 공개된 PoC 는 자체 시스템 내에서 프로그램을 실행하는 PoC 임.
그러나 외부에서 공격자가 악의적인 코드를 요청할 경우를 대비하고자 아래와 같이 패턴 등록이 필요함.
HTTP 요청 시 아래와 같은 문자열이 URL 에 들어갈 경우 탐지하는 패턴들임.
참고로 HTTP Header 와 Body 부분까지도 탐지하고자 한다면 Snort 옵션 http_uri; 를 빼면 되지만 오탐 가능성이 있음.
위험한 보간기 개체 문자열 리스트는 아래와 같음.
${script:
${url:UTF-8:
${dns:
${script:JEXL:
%24%7Bscript%3A
%24%7Burl%3AUTF-8%3A
%24%7Bdns%3A
%24%7Bscript%3AJEXL%3A
< 현개 공개된 PoC 모음 >
alert tcp any any -> any any (msg:"KOROMOON_Text4Shell_Vulnerability_URL_Access_1"; content:"${script:"; http_uri; nocase;)
alert tcp any any -> any any (msg:"KOROMOON_Text4Shell_Vulnerability_URL_Access_2"; content:"${url:UTF-8:"; http_uri; nocase;)
alert tcp any any -> any any (msg:"KOROMOON_Text4Shell_Vulnerability_URL_Access_3"; content:"${dns:"; http_uri; nocase;)
alert tcp any any -> any any (msg:"KOROMOON_Text4Shell_Vulnerability_URL_Access_4"; content:"${script:JEXL:"; http_uri; nocase;)
alert tcp any any -> any any (msg:"KOROMOON_Text4Shell_Vulnerability_URL_Access_5"; content:"%24%7Bscript%3A"; nocase;)
alert tcp any any -> any any (msg:"KOROMOON_Text4Shell_Vulnerability_URL_Access_6"; content:"%24%7Burl%3AUTF-8%3A"; nocase;)
alert tcp any any -> any any (msg:"KOROMOON_Text4Shell_Vulnerability_URL_Access_7"; content:"%24%7Bdns%3A"; nocase;)
alert tcp any any -> any any (msg:"KOROMOON_Text4Shell_Vulnerability_URL_Access_8"; content:"%24%7Bscript%3AJEXL%3A"; nocase;)
참고 사이트 :
https://nvd.nist.gov/vuln/detail/CVE-2022-42889
https://securitylab.github.com/advisories/GHSL-2022-018_Apache_Commons_Text/
https://lists.apache.org/thread/n2bd4vdsgkqh2tm14l1wyc3jyol7s1om
https://www.rapid7.com/blog/post/2022/10/17/cve-2022-42889-keep-calm-and-stop-saying-4shell/
https://www.cnblogs.com/wh4am1/p/16795499.html
https://attackerkb.com/topics/98L4lvgOD1/cve-2022-42889/rapid7-analysis?referrer=activityFeed
https://www.tarlogic.com/blog/cve-2022-42889-critical-vulnerability-affects-apache-commons-text/
https://twitter.com/pwntester/status/1582321752566161409
https://github.com/apache/commons-text/commit/b9b40b903e2d1f9935039803c9852439576780ea
https://github.com/karthikuj/cve-2022-42889-text4shell-docker
https://github.com/ClickCyber/cve-2022-42889/blob/main/CVE-2022-42889.php
https://en.wikipedia.org/wiki/String_interpolation
https://lemonlemon.tistory.com/m/153
댓글 없음:
댓글 쓰기