1. SAP NetWeaver Visual Composer

- SAP NetWeaver : SAP의 애플리케이션 통합 및 실행 플랫폼으로, 다양한 SAP 모듈과 시스템 간 연결을 지원 [1]
- SAP NetWeaver Visual Composer : NetWeaver 상에서 동작하는 시각적 UI 개발 도구로, 코드 없이 SAP 비즈니스 앱의 화면을 설계할 수 있음 [2]

2. CVE-2025-31324

[사진 1] CVE-2025-31324 [3]

- Metadata Uploader 컴포넌트에서 접근 제어가 제대로 이루어지지 않아 임의의 파일 업로드가 가능한 취약점 (CVSS: 10.0)

> /developmentserver/metadatauploader 엔드포인트에서 접근 제어가 제대로 이루어지지 않아, 공격자가 인증 없이 JSP 웹셸 파일을 서버에 업로드 가능

> SAP Visual Composer는 기본 설치 항목은 아니지만, 다수의 시스템에서 활성화되어 있음

> 공격자가 JSP 웹쉘을 서버의 퍼블릭 디렉터리에 업로드해 인증 없이 원격 제어하는 등 활발히 악용 중이므로, 긴급 패치 권고

 -영향받는 버전
SAP NetWeaver VCFRAMEWORK 7.50

[사진 2] 실제 공격에 악용된 HTTP POST 요청 [4]

2.1 취약점 스캐너

- 보안 기업 Onapsis는 취약점을 확인할 수 있는 스캐너를 제공 [5]

> GitHub에서 스캐너의 최신 버전을 확인한 후 지정한 SAP 서버의 취약점 여부 확인

① 대상 SAP 서버의 /developmentserver/metadatauploader URL로 HEAD 요청 전송

 ⒜ 200 응답Set-Cookie 헤더가 없는 경우 취약

 ⒝ 404 응답 또는 다른 응답의 경우 취약하지 않음

사전 정의된 웹쉘 목록(KNOWN_WEBSHELLS)경로(/irj)를 대상으로 업로드된 웹쉘 확인

 ⒜ 200 응답일 경우 웹쉘 존재

※ 사전 정의된 웹쉘 목록과 특정 경로만을 대상으로 스캔을 수행하므로 정의되지 않은 웹쉘명과 경로에대한 검증은 불가

import requests
import argparse
import json
from packaging.version import parse as parse_version

__version__ = "1.0.2"
KNOWN_WEBSHELLS = ["cache.jsp", "helper.jsp"]
GITHUB_REPO = (
    "Onapsis/Onapsis_CVE-2025-31324_Scanner_Tools"
)


def check_cve_2025_31324(hostname, port, use_ssl):
    protocol = "https" if use_ssl else "http"
    url = f"{protocol}://{hostname}:{port}/developmentserver/metadatauploader"

    try:
        response = requests.head(url, timeout=10, verify=False)
        status_code = response.status_code
        if status_code == 200 and 'Set-Cookie' not in response.headers:
            print(
                f"[CRITICAL] SAP System at {url} appears to be vulnerable to "
                "CVE-2025-31324."
            )
        elif status_code == 404:
            print(
                f"[INFO] Visual Composer SAP System at {url} appears to not "
                "be installed or unavailable."
            )
        else:
            print(
                f"[INFO] The SAP system at {url} does not appear to be "
                "vulnerable to CVE-2025-31324."
            )
    except requests.exceptions.RequestException as e:
        print(f"Error connecting to {url} for vulnerability testing: {e}")


def test_webshell(hostname, port, use_ssl):
    webshell_found = False
    for webshell_filename in KNOWN_WEBSHELLS:
        protocol = "https" if use_ssl else "http"
        url = f"{protocol}://{hostname}:{port}/irj/{webshell_filename}"
        try:
            response = requests.get(url, timeout=10, verify=False)
            if response.status_code == 200:
                print(f"[CRITICAL] Known webshell found at: {url}")
                webshell_found = True

        except requests.exceptions.RequestException as e:
            print(
                f"[ERROR] Error connecting to {url} for webshell testing: {e}"
            )
    if not webshell_found:
        print("[INFO] No known webshells found.")


def check_for_updates():
    try:
        url = f"https://api.github.com/repos/{GITHUB_REPO}/releases/latest"
        response = requests.get(url)
        response.raise_for_status()
        release_info = response.json()
        latest_version = release_info.get("tag_name")
        if latest_version:
            latest_version = latest_version.lstrip("v")
            current_version = parse_version(__version__)
            latest_parsed_version = parse_version(latest_version)
            if latest_parsed_version > current_version:
                print(f"[WARNING] There is a newer version, {latest_version}.")
                print(f"You are currently using version {__version__}.")

        else:
            print("Could not retrieve the latest release information.")
    except requests.exceptions.RequestException as e:
        print(f"Error checking for updates: {e}")
    except json.JSONDecodeError:
        print("Error decoding release information.")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description=(
            "Onapsis Scanner for Vulnerability CVE-2025-31324 (SAP Security "
            "3594142) - CVSS 10 (Critical). This tool checks for the presence "
            "of the vulnerability and known webshells in the SAP system. \n\n"
            "DISCLAIMER: This tool is provided from Onapsis via open source "
            "license Apache 2.0, as a contribution to the security, incident "
            "response, and SAP communities to aid in response to active "
            "exploitation of CVE-2025-31324. This tool is under development "
            "and will continue to iterate rapidly as more information becomes "
            "available either from Onapsis Research Labs or publicly. "
            "This is a best-effort development and offered as-is with no "
            "warranty or liability."
        )
    )
    parser.add_argument(
        "hostname",
        help=(
            "Hostname or IP address of the SAP system."
        )
    )
    parser.add_argument(
        "port",
        type=int,
        help="Port number of the SAP system (i.e. 50000)."
    )
    parser.add_argument(
        "--ssl",
        action="store_true",
        help="Use SSL/TLS for the connection."
    )

    args = parser.parse_args()
    check_for_updates()
    check_cve_2025_31324(args.hostname, args.port, args.ssl)
    test_webshell(args.hostname, args.port, args.ssl)

3. 대응방안

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

제품명 영향받는 버전 해결 버전
SAP NetWeaver VCFRAMEWORK 7.50 별도 보안 패치 제공 [6][7][8]

 

- 침해 여부 확인 방법 [9]

> 다음 OS 디렉토리의 루트에 'jsp', 'java', 'class' 파일 존재 여부 확인

① C:\usr\sap\<SID>\<InstanceID>\j2ee\cluster\apps\sap.com\irj\servlet_jsp\irj\root
② C:\usr\sap\<SID>\<InstanceID>\j2ee\cluster\apps\sap.com\irj\servlet_jsp\irj\work
③ C:\usr\sap\<SID>\<InstanceID>\j2ee\cluster\apps\sap.com\irj\servlet_jsp\irj\work\sync

[예시]
[root@sapserver irj]# pwd
/usr/sap/<SID>/<INSTANCE>/j2ee/cluster/apps/sap.com/irj/servlet_jsp/irj
[root@sapserver irj]# find . -type f -name “*.jsp” -ls
[root@sapserver irj]# find . -type f -name “*.java” -ls
[root@sapserver irj]# find . -type f -name “*.class” -ls

 

> SAP 악용에 사용된 웹쉘 및 악용 IP IOC 제공 [9]

① 몇 가지 예외를 제외하고 대부분 파일명은 "무작위 8자리.JSP" 형태

구분 SHA256
Helper.jsp 1f72bd2643995fab4ecf7150b6367fa1b3fab17afd2abed30a98f075e4913087
Cache.jsp 794cb0a92f51e1387a6b316b8b5ff83d33a51ecf9bf7cc8e88a619ecb64f1dcf
Random 8-character names ([a-z]{8}).jsp  b3e4c4018f2d18ec93a62f59b5f7341321aff70d08812a4839b762ad3ade74ee

 

 다음 디렉토리 내에 .jsp, .class, .java 확장자 파일은 악성으로 간주

⒜ /usr/sap/<SID>/<InstanceID>/j2ee/cluster/apps/sap.com/irj/servlet_jsp/irj/root
⒝ /usr/sap/<SID>/<InstanceID>/j2ee/cluster/apps/sap.com/irj/servlet_jsp/irj/work
⒞ /usr/sap/<SID>/<InstanceID>/j2ee/cluster/apps/sap.com/irj/servlet_jsp/irj/work/sync

 

- 탐지 규칙

[YARA]
rule detect_CVE202531324_webshells_by_name

{
    meta:
        description = “Detects the known webshell file names that are uploaded in the root directory”
        author = “Emanuela Ionas, Onapsis Research Labs”
        date = “2025-04-30”
        tags = “CVE-2025-31324”
    strings:
        $path_1 = “/irj/root/”
        $path_2 = “/irj/”

        $webshell_1 = “cache.jsp” nocase
        $webshell_2 = “helper.jsp” nocase
        $webshell_4 = “[a-zA-Z0-9]{8}\.jsp”

        $status = “HTTP/[1,2]\.[0,1,2] 200”
    condition:
        ($webshell_1 or $webshell_2 or $webshell_4) and ($path_1 or $path_2) and $status
}

[SNORT]

alert tcp any any -> any any (msg:"CVE-2025-31324";flow:to_server,established;content:"POST";content:"/developmentserver/metadatauploader";content:"multipart/form-data";content:"filename="; content:".jsp";nocase;)

4. 참고

[1] https://help.sap.com/docs/SAP_NETWEAVER_702/ff55ab4f6c5510149ce7df0d5dc0da07/4a24dbfa64550455e10000000a421937.html
[2] https://help.sap.com/docs/SAP_NETWEAVER_702/ff55ab4f6c5510149ce7df0d5dc0da07/48db676f63f45c97e10000000a42189d.html
[3] https://nvd.nist.gov/vuln/detail/CVE-2025-31324
[4] https://www.picussecurity.com/resource/blog/cve-2025-31324-sap-netweaver-remote-code-execution
[5] https://github.com/Onapsis/Onapsis_CVE-2025-31324_Scanner_Tools
[6] https://support.sap.com/en/my-support/knowledge-base/security-notes-news/april-2025.html
[7] https://accounts.sap.com/saml2/idp/sso
[8] https://www.boho.or.kr/kr/bbs/view.do?bbsId=B0000133&pageIndex=1&nttId=71729&menuNo=205020
[9] https://onapsis.com/blog/active-exploitation-of-sap-vulnerability-cve-2025-31324/
[10] https://www.rapid7.com/blog/post/2025/04/28/etr-active-exploitation-of-sap-netweaver-visual-composer-cve-2025-31324
[11] https://reliaquest.com/blog/threat-spotlight-reliaquest-uncovers-vulnerability-behind-sap-netweaver-compromise
[12] https://www.dailysecu.com/news/articleView.html?idxno=165680

+ Recent posts