
Java JAR/WAR 아티팩트에서 취약한 Apache Commons Text를 감지하고 패치하며, 클래스 핑거프린팅 및 바이트코드 스캔을 통해 CVE-2022-42889(Text4Shell) 호출 지점을 식별합니다.
클릭하여 다음을 찾으세요:
CVE-2022-42889는 광범위한 Java 기반 애플리케이션에 심각한 위협이 될 수 있습니다. 개발자가 이 맥락에서 물어볼 수 있는 중요한 질문은 다음과 같습니다:
commons-text가 포함되어 있나요? 어떤 버전인가요?배포된 코드에 commons-text가 포함되어 있나요? 어떤 버전의 라이브러리가 포함되어 있나요? 다음 두 가지 요인 때문에 이러한 질문에 즉시 답하기 어려울 수 있습니다:
전이적 의존성: commons-text가 프로젝트의 직접 의존성 목록에 없을 수 있지만, 다른 일부 의존성에 의해 간접적으로 사용될 수 있습니다.
이 라이브러리의 코드는 별도의 파일로 직접 나타나지 않고 다른 코드 jar 파일에 번들로 포함될 수 있습니다.
JFrog는 이 문제를 해결하는 데 도움이 되는 도구를 공개합니다: scan_commons_text_versions. 이 도구는 StringLookupFactory의 클래스 코드를 찾아(포함된 .jar 파일 이름 및 pom.xml 파일 내용과 무관하게) 객체의 버전을 핑거프린팅하여 포함된 commons-text 버전이 취약한지 여부를 보고하려고 시도합니다.
commons-text 함수를 사용하나요?이 질문은 개발자가 코드베이스에서 commons-text 호출이 잠재적으로 공격자가 제어하는 데이터를 전달할 수 있는지 확인하려는 경우에 관련이 있습니다. 권고에서 논의된 대로 취약점을 해결하는 가장 안전한 방법은 적절한 패치를 적용하는 것이지만, 패치되지 않은 commons-text를 가정하고 잠재적 영향을 제어하고 검증하는 것은 많은 상황에서 유용할 수 있습니다.
scan_commons_text_calls_jar.py는 컴파일된 .jar 파일에서 취약한 함수에 대한 호출을 찾아 각 호출이 나타나는 클래스 이름 및 메서드 이름으로 결과를 보고합니다.
commons-text jar 파일이 있는데, 위험한 동작을 빠르게 비활성화하려면 어떻게 해야 하나요?업데이트가 여전히 최선의 해결책입니다. 이 솔루션은 빠른 핫 패치를 위한 것입니다.
CVE-2022-42889 취약점의 맥락에서, commons-text의 클래스 org/apache/commons/text/lookup/ScriptStringLookup은 공격자가 제어하는 소스에서 ${script}를 통해 수신된 문자열에 포함될 수 있는 스크립트의 실행을 가능하게 합니다. 따라서 ScriptStringLookup.lookup 함수의 호출은 해당 기능이 활성화되었음을 나타냅니다.
우리는 이 특정 호출을 패치하여 스크립트 실행 기능을 사용할 수 없도록 하는 도구 Text4ShellPatch를 제공합니다. 패치를 적용하면 라이브러리는 (잠재적으로 공격자가 제어하는 코드 대신) 경고 메시지를 반환하는 스크립트를 항상 실행합니다.
마찬가지로 DNS 및 URL 조회는 공격자가 ${dns}와 ${url}을 통해 제어하는 경우 신뢰할 수 없는 콘텐츠를 로드할 수 있습니다. 따라서 각각의 조회 클래스인 DnsStringLookup과 UrlStringLookup은 경고 메시지를 반환하도록 패치를 통해 비활성화할 수 있습니다.
패치는 특정 jar 파일에 적용할 수 있으며, script 조회만 또는 애플리케이션에서 사용하지 않을 경우 더 나은 보호를 위해 script, dns, 조회를 패치할 수 있습니다.
commons-text jar의 스캔 및 패치를 자동화할 수 있나요?우리의 두 도구가 함께 취약한 commons-text jar 파일을 스캔하고 패치하는 기능을 제공합니다.
이 GitHub 리포지토리에는 scan_and_patch.sh라는 이름의 예제 bash 스크립트가 있습니다. 기본적으로 scan_commons_text_versions.py 스크립트를 사용하여 특정 root-folder 아래에서 취약한 버전의 commons-text jar 파일을 찾은 다음 Text4ShellPatch 도구를 다음과 같이 실행합니다.

scan_commons_text_versions.pypython scan_commons_text_versions.py root-folder [-quiet] [-exclude folder1 folder2 ..]
이 도구는 root_folder를 재귀적으로 스캔하여 .jar 및 .war 파일을 찾습니다. 각 파일에서 도구는 StringLookupFactory.class를 찾습니다(각 .jar 파일 내에서 재귀적으로). 클래스가 하나 이상 발견되면 도구는 코드가 취약한지 여부를 보고하기 위해 해당 버전의 핑거프린트를 시도합니다(패치 및 백포트 패치에서 발견된 일부 변형 포함).
-quiet 플래그를 사용하면 버전 결론만 출력되고 다른 메시지(파일을 찾을 수 없음/아카이브를 열지 못함/비밀번호로 보호된 아카이브)는 표시되지 않습니다.
-exclude(선택 사항) 뒤에 나타나는 폴더는 건너뜁니다.
scan_commons_text_calls_jar.py이 도구는 python 3와 다음 타사 라이브러리가 필요합니다: jawa, tqdm, easyargs, colorama
pip install -r requirements.txt
기본 사용 사례:
python scan_commons_text_calls_jar.py root-folder
는 root-folder의 모든 .jar 파일을 재귀적으로 스캔하여 각 파일에 대해 StringSubstitutor/StringLookup의 lookup/replace/replaceIn 메서드 호출 위치(클래스 이름 및 메서드 이름)를 출력합니다.
다음 명령줄 플래그를 사용하여 추가 사용 사례에 맞게 도구를 구성할 수 있습니다.
text_4_shell_patchjava -jar Text4ShellPatch.jar TARGET_JAR [PATCHING_MODE]
Where TARGET_JAR is the application to patch and PATCHING_MODE is
0 (default): Patch Script lookup
1: Patch Script + DNS + URL lookups
[Note: The original Jar will be kept in the same folder with the .orig.jar extension]
이 도구는 주어진 commons-text jar에서 org/apache/commons/text/lookup/ScriptStringLookup 클래스를 찾아 lookup() 함수의 내용을 경고 메시지로 대체하고 함수에서 반환합니다. 따라서 새 ScriptStringLookup 클래스에는 eval이 존재하지 않게 됩니다.
또한 PATCHING_MODE 옵션을 1로 설정하면 DnsStringLookup 및 URLStringLookup 클래스를 패치하고 lookup() 함수를 비활성화할 수 있습니다.
이 과정에서 백업 파일이 .orig.jar 확장자로 동일한 경로에 생성됩니다.
Text4ShellPatch는 다음 간단한 명령으로 Maven을 사용하여 편집 및 컴파일할 수 있습니다:
mvn clean assembly:single. 그러면 target/ 폴더에 Text4ShellPatch.jar 파일이 생성됩니다.
url패치된 jar로 교체되기 전에 원본 jar와 같은 위치에 백업이 생성됩니다. 백업 파일 이름은 <original_jar_name>_YYYY.MM.DD_HH.mm.ss.orig.jar 패턴을 따릅니다. 여기서 YYYY, MM, DD는 각각 연도, 월, 일이고, HH, mm, ss는 각각 시, 분, 초입니다.
다음 질문에서 답하는 것처럼 취약한 버전의 commons-text를 찾아 자동으로 패치하는 것도 가능합니다.
| Flag | Default value | Use |
|---|
--class_regex | (.*StringSubstitutor|.*StringLookup) | 필수 클래스 이름에 대한 정규식 |
--method_regex | (lookup|replace|replaceIn) | 필수 메서드 이름에 대한 정규식 |
--quickmatch_string | (StringLookup|StringSubstitutor) | 파일 분석을 위한 사전 조건: 지정된 정규식을 포함하지 않는 .jar 파일은 무시됩니다. |
--class_existence | Not set | 설정되지 않으면 정규식으로 지정된 class::method 호출을 찾습니다. 설정되면 --method_regex는 무시되고 도구는 jar에서 --class_regex로 지정된 클래스의 존재를 찾습니다. |
--no_quickmatch | Not set | 설정되면 --quickmatch_string 값은 무시되고 모든 jar 파일이 분석됩니다. |
--caller_block | .*org/apache/commons/text | 호출자 클래스가 이 정규식과 일치하면 표시되지 않습니다. |