
Snipe-IT PoC exploit for CVE-2025-59712 and CVE-2025-59713
이 PoC는 CVE-2025-59712(User-Agent 헤더의 XSS)와 CVE-2025-59713(안전하지 않은 역직렬화)을 악용하는 자동화 스크립트를 제공합니다.
이 두 취약점은 Snipe-IT 소프트웨어에 대한 취약점 연구 중 Synacktiv에 의해 발견되었습니다. Snipe-IT는 Laravel 기반의 오픈소스 자산 관리 시스템으로, 조직이 물리적 및 디지털 자산을 추적하고 관리할 수 있도록 설계되었습니다.
기술적인 분석 내용은 Synacktiv 웹사이트의 전용 보안 권고에서 확인할 수 있습니다.
이 스크립트는 공격 모드에 해당하는 세 가지 하위 명령어(xss, rce, fullchain)를 제공합니다.
이 하위 명령어는 CVE-2025-59712를 악용합니다. 이 취약점은 낮은 권한의 사용자가 /reports/activity 라우트를 호출할 때 렌더링되는 HTML 페이지에 임의의 JavaScript를 주입할 수 있게 합니다. 이는 관리자 사용자 또는 보고서에 대한 명시적 보기 권한이 있는 사용자만 수행할 수 있습니다. 주입은 사용자가 프로필 정보를 업데이트할 때 User-Agent 필드가 적절히 무해화되지 않기 때문에 가능합니다.
이를 위해 먼저 낮은 권한의 사용자로 로그인한 다음, --javascript 플래그를 통해 제공된 파일에 정의된 JavaScript 코드를 주입합니다.
$ python3 exploit.py xss --help
Usage: exploit.py xss [OPTIONS]
Execute XSS attack only with custom JavaScript payload
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --url -u TEXT Target Snipe-IT URL [required] │
│ * --login -l TEXT Low-privileged username [required] │
│ * --password -p TEXT Low-privileged password [required] │
│ * --new-name -n TEXT New name for low-privileged user [required] │
│ * --javascript -js TEXT Path to custom JavaScript file [required] │
│ --proxy -x TEXT HTTP proxy (http://ip:port) │
│ --verbose -v [quiet|normal|verbose] Logging verbosity [default: normal] │
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
[!IMPORTANT]
보안 연구 중 테스트는 악성 JavaScript가 주입되는User-Agent필드가 기본적으로 표시되는 Snipe-IT 버전에서 수행되었습니다. 커밋 10e5d88 이후로는 작업 로그 테이블이 렌더링될 때User-Agent속성이 기본적으로 표시되지 않습니다. 따라서 이 커밋 이후 버전의 Snipe-IT에서 XSS를 트리거하려면 관리자가 보기 옵션에서User-Agent항목을 체크해야 합니다.
이 하위 명령어는 CVE-2025-59713을 악용합니다. 이 취약점은 관리자 또는 슈퍼관리자 사용자의 자격 증명을 알고 있을 때 원격 코드 실행을 가능하게 합니다. 이를 위해 다음 단계가 수행됩니다:
db-dumps/mysql-snipeit.sql 파일에 추가 SQL 문이 포함되며, 이 SQL 문은 새 사용자 정의 필드를 생성하고 복원 시 Laravel pop chain을 포함한 JSON 객체로 마지막 작업 로그를 수정합니다.[!TIP] 기본적으로 Snipe-IT는 백업에
.env파일을 포함합니다. 스크립트가 이를 감지하면APP_KEY값을 표시하고.env파일을./output디렉터리에 저장합니다(해당 파일의 사용자 지정 위치는--output-dir로 지정할 수 있습니다).
[!CAUTION] 백업을 복원하면 인스턴스에 연결된 모든 사용자의 연결이 끊깁니다.
/api/v1/reports/activity 라우트가 호출되어 역직렬화를 트리거하고 Laravel pop chain을 실행합니다.$ python3 exploit.py rce --help
Usage: exploit.py rce [OPTIONS]
Execute RCE attack only (requires existing admin account)
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --url -u TEXT Target Snipe-IT URL [required] │
│ * --admin-user -au TEXT Admin username [required] │
│ * --admin-pass -ap TEXT Admin password [required] │
│ --output-dir -od PATH Output dir for .env file [default: /home/ninja/Téléchargements/snipe-it-advisory/exploit/output] │
│ --shell-ip -si TEXT Reverse shell IP address │
│ --shell-port -sp INTEGER Reverse shell port │
│ --command -c TEXT Custom command (overrides reverse shell) │
│ --proxy -x TEXT HTTP proxy (http://ip:port) │
│ --verbose -v [quiet|normal|verbose] Logging verbosity [default: normal] │
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
fullchain 하위 명령어는 XSS와 RCE 취약점을 함께 연결하는 것을 목표로 합니다. 이는 낮은 권한의 사용자만 접근할 수 있고 원격 코드 실행을 달성하려는 시나리오에 해당합니다. 이 공격은 /reports/activity 페이지를 방문하는 사용자가 관리자 또는 슈퍼관리자인 경우에만 동작합니다. 실제로 데이터베이스를 오염시키고 이후 Laravel pop chain을 트리거하는 데 필요한 백업 생성 및 복원 권한은 이들 역할만이 가지고 있습니다.
이를 위해 스크립트는 다음을 수행합니다:
--command 플래그로 이 옵션을 RCE 모드와 동일하게 변경할 수 있습니다).User-Agent 필드에 <scr> 태그를 주입하여 피해자의 브라우저가 악성 JavaScript 템플릿을 로드하도록 강제합니다./reports/activity 라우트를 방문하면 XSS가 트리거되고 피해자의 브라우저에서 악성 JavaScript가 로드되어 실행됩니다. 이후부터는 RCE 모듈에서 실행되는 것과 동일한 단계가 JavaScript로 수행됩니다.이 모드는 몇 가지 추가 JavaScript 라이브러리를 활용하며, 모든 크레딧은 해당 저자에게 있습니다:
$ python3 exploit.py fullchain --help
Usage: exploit.py fullchain [OPTIONS]
Execute full attack chain: XSS -> Backup manipulation -> RCE
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --url -u TEXT Target Snipe-IT URL [required] │
│ * --login -l TEXT Low-privileged user's username [required] │
│ * --password -p TEXT Low-privileged user's password [required] │
│ * --new-name -n TEXT New name for low-privileged user [required] │
│ --ip -i TEXT HTTP server IP address (default: auto-detect) │
│ * --port -P INTEGER HTTP server port [required] │
│ --admin-user -au TEXT Admin username to create [default: admin_rce] │
│ --admin-pass -ap TEXT Admin password to create [default: password123] │
│ --shell-ip -si TEXT Reverse shell IP address │
│ --shell-port -sp INTEGER Reverse shell port │
│ --command -c TEXT Custom command (overrides reverse shell) │
│ --proxy -x TEXT HTTP proxy (http://ip:port) │
│ --verbose -v [quiet|normal|verbose] Logging verbosity [default: normal] │
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
이 스크립트를 실행하려면 다음 명령어를 실행하세요:
$ git clone https://github.com/synacktiv/CVE-2025-59712_CVE-2025-59713
$ cd CVE-2025-59712_CVE-2025-59713
$ python3 -m venv .venv && source .venv/bin/activate
$ python3 -m pip install -r requirements.txt
스크립트를 시험하고 취약점 악용을 재현할 수 있도록 Dockerfile도 제공됩니다. 이 Dockerfile은 취약한 버전의 Snipe-IT를 가져와 php artisan으로 데이터베이스를 구성하고 두 명의 사용자를 설정합니다:
AdminPassword123!인 admin 사용자LowPrivUser123!인 lowpriv 사용자컨테이너를 실행하기 전에 .env 및 snipe-it.conf 파일을 Snipe-IT 인스턴스의 URL로 업데이트해야 합니다:
$ sed -i 's|^APP_URL=.*|APP_URL=http://<IP>:<PORT>|' .env
$ sed -i 's|\(ServerName\s*\).*|\1http://<IP>:<PORT>|' snipe-it.conf
그런 다음 컨테이너를 실행할 수 있습니다:
$ docker build . -t "snipe-it-cve"
$ docker run -p 80:80 --name "snipe-it-debian" snipe-it-cve:latest