실습 전용 — 이 앱은 보안 통제를 의도적으로 비활성화합니다. 일회용 구독에서만 구동하고 실습 후 삭제하세요.
ADFS SAML Lab판별 중…Host 192.168.4.110:3000PUBLIC_BASE_URL https://adfs-lab.prism-proxy.localtest.me:8443base 소스 요청 유도X-Forwarded-* 있음피어 192.168.4.100경고 1요청 인스펙터 →

절대 URL 하네스

내부 절대 URL 이 박힌 앱을 프록시로 게시하면 무엇이 깨지는지 카테고리별로 재현합니다. 대상은 두 번째 내부 호스트(더미 API)입니다 — 자기 자신을 가리키면 프록시가 아무것도 안 해도 통과해 버려 측정이 무의미해집니다.

읽는 법

prism-proxy 에 재작성기가 들어오기 전에는 프록시 경유에서 대부분 실패하는 것이 정상입니다.

  • [1] 본문 재작성 — responseInterceptor 로 HTML/JS/CSS 텍스트를 훑어 문자열을 바꾼다. 응답 전체를 메모리에 버퍼링하므로 큰 파일·스트리밍 분기가 필수다.
  • [2] Service Worker — 실제 요청을 가로챈다. 런타임에 조립된 URL 까지 잡는 유일한 방법이다.
  • 재작성 불가 — SAML assertion 처럼 서명이 URL 을 덮는 경우. 고치면 서명이 깨지고 안 고치면 앱이 거부한다.
통과 0 · 실패 0 · 수동 0 / 전체 16대상 http://192.168.4.110:4200
#1

HTML 속성 — <img src>

[1] 본문 재작성미실행

서버가 렌더한 HTML 안에 내부 절대 URL 이 박힌 이미지.

http://192.168.4.110:4200/assets/pixel.png

#1

HTML 속성 — <script src>

[1] 본문 재작성미실행

내부 절대 URL 스크립트. 로드되면 __absProbe 콜백이 불린다.

http://192.168.4.110:4200/assets/probe.js

#1

HTML 속성 — <iframe src>

[1] 본문 재작성미실행

내부 절대 URL 프레임. 로드되면 postMessage 로 알린다.

http://192.168.4.110:4200/frame.html

#2

meta http-equiv=refresh

[1] 본문 재작성미실행

<meta refresh> 의 url= 에 박힌 절대 URL. 정규식 기반 재작성기가 흔히 놓친다.

http://192.168.4.110:4200/meta-refresh.html

#3

CSS 의 url() 과 @import

[1] 본문 재작성미실행

스타일시트 안의 절대 URL. @import 는 중첩이라 한 단계 더 들어가야 잡힌다.

http://192.168.4.110:4200/assets/probe.css

#4

인라인 이벤트 핸들러

[1] 본문 재작성미실행

onclick 안의 문자열 URL. HTML 파서로는 속성값 안의 JS 라 접근이 애매하다.

자동 판정 불가 — 버튼을 눌러 새 창이 열리는지 사람이 확인한다.

http://192.168.4.110:4200/frame.html

새 창에서 직접 열어보기 →
#5

비압축 JS 안의 문자열 리터럴

[1] 본문 재작성미실행

번들에 평문으로 남은 절대 URL. 레거시 앱에서 [1] 이 가장 잘 먹는 경우.

http://192.168.4.110:4200/assets/probe.js

#6

gzip 압축 응답 안의 같은 문자열

[1] 본문 재작성미실행

동일 내용을 Content-Encoding: gzip 으로 전달. responseInterceptor 가 자동 해제한다고 레포 주석에 적혀 있으나 검증 항목이다.

압축 해제 후 재작성하고 다시 압축하는지 확인. Content-Length 재계산도 함께.

http://192.168.4.110:4200/assets/probe-gz.js

#7

JSON 설정 응답 안의 절대 URL

[1] 본문 재작성미실행

/api/config 가 돌려주는 JSON 에 apiBase 가 절대 URL 로 들어있다. 중첩 필드에도 하나 숨겨 뒀다.

content-type 분기가 없으면 HTML 만 태우다가 이걸 놓친다.

http://192.168.4.110:4200/api/config

#8

fetch/XHR 하드코딩 절대 URL

[1] 또는 [2]미실행

코드에 박힌 절대 URL 로의 fetch. 소스 재작성 또는 SW 인터셉트 둘 다 가능.

http://192.168.4.110:4200/api/report

#9

런타임 조립 URL

[2] Service Worker미실행

'http://' + host + '.corp.local' + path 처럼 실행 시점에 문자열을 합쳐 만든다. 소스에 완성된 URL 이 없으므로 [1] 은 원리적으로 못 잡는다.

★ [1] 만 구현하면 여기서 멈춘다. ※ 측정 이력(2026-09-22): [B]+[1] 구현 후 이 케이스만 실패했으나, 원인은 재작성기가 아니라 **이 케이스의 재현 실패**였다. 조립 재료로 쓰던 dummyOrigin 이 완전한 origin 문자열이라 [1] 이 정당하게 /__upstream/... 으로 바꿨고, 상대 경로를 new URL() 에 넣어 'Failed to construct URL' 로 터졌다. 2026-09-23 에 호스트·포트를 분해해 받도록 고쳤다 (absolute-harness.tsx). ※ 재측정(2026-09-23): 고친 뒤 이 케이스는 'fetch 타임아웃 8000ms' 로 실패한다 — 브라우저가 재작성되지 않은 내부 절대 주소로 직접 나가려다 못 간 것이고, 이 케이스가 재현해야 할 바로 그 상황이다. **측정이 유효해졌고 이것이 [2] 의 첫 유효한 근거다.** 이로써 [1]+[B] 의 천장이 확정됐다 — 자동 판정 14 건 중 13 건 통과, 못 잡는 것은 이 케이스 하나. 다만 착수 기준은 여전히 '런타임 조립 URL 을 쓰는 **실제 고객사 앱**이 발견되면' 이다(reverse-proxy.middleware.ts). 하네스는 합성 재현이지 발견 사례가 아니다. ※ [2] 의 근거는 이 케이스 하나가 아니다: [1] 은 URL 의 **값 자체**를 바꾸므로, 값을 fetch 말고 계산에 쓰는 앱(new URL(base), base.split("//"), location.origin 비교 등) 에서는 모두 깨진다. [2] 는 값을 건드리지 않고 실제 요청만 가로채므로 그 전부를 덮는다.

http://192.168.4.110:4200/api/report

#10

Web Worker 안의 fetch

[1] 또는 [2]미실행

워커 스크립트가 내부 절대 URL 로 fetch 한다.

★ 실측 확인(2026-09-17): 브라우저가 교차 오리진 Worker 생성을 원천 차단한다 ("cannot be accessed from origin"). 본문 재작성 [1] 로는 풀리지 않는다 — URL 을 same-origin 으로 끌어오는 [B] 경로 접두사 방식이 **필수**임을 증명하는 케이스. ※ 갱신(2026-09-22): [B]+[1] 구현 후 **통과**했다. 위 '필수' 조건이 충족된 것이다 — 접두사가 워커 스크립트를 same-origin 으로 끌어와 생성 차단이 풀렸고, worker.js 자체도 JS content-type 이라 그 안의 fetch URL 까지 [1] 이 재작성했다. 그래서 caughtBy 를 [2] 에서 [1] 또는 [2] 로 고쳤다. 직접 접속에서는 여전히 실패하므로 **프록시 경유가 직접 접속보다 높은 유일한 케이스**다.

http://192.168.4.110:4200/assets/worker.js

#11

http:// 절대 URL (혼합 콘텐츠)

[1] 또는 [2]미실행

https 페이지에서 http 서브리소스를 부른다. 브라우저가 DNS 시도 전에 차단하므로 실패하는 주체가 프록시가 아니라 브라우저다.

★ 미검증이었던 항목: 혼합 콘텐츠 차단이 SW 인터셉트보다 먼저 일어나면 SW 가 요청을 보지도 못해 [2] 가 무효다. ※ 이 케이스는 **HTTPS 페이지에서만** 성립한다. ※ 갱신(2026-09-22): [B]+[1] 구현 후 **통과**했고, 위 실험은 불필요해졌다 — http:// 절대 URL 이 상대 경로(/__upstream/...)로 바뀌면서 스킴이 사라져 **혼합 콘텐츠라는 상황 자체가 성립하지 않게** 됐다. 판정도 수동에서 자동으로 바뀌었다.

http://192.168.4.110:4200/assets/pixel.png

#12

Location 헤더의 절대 URL

헤더 재작성 (별도 축)미실행

302 응답의 Location 이 내부 절대 URL. 본문이 아니라 헤더 축이다.

본문 재작성기를 만들어도 이건 따로 손대야 한다.

http://192.168.4.110:4200/redirect-absolute

#13

큰 바이너리 응답 (8MB)

통과해야 정상미실행

재작성기가 텍스트만 태우고 바이너리는 통과시키는지. responseInterceptor 는 응답 전체를 메모리에 버퍼링하므로 분기가 없으면 여기서 메모리와 지연이 터진다.

★ 성공 = 빠르게 통과. 느려지거나 실패하면 버퍼링 분기가 없다는 뜻.

http://192.168.4.110:4200/assets/big.bin

#14

SAML assertion 안의 ACS URL

재작성 불가미실행

서명이 Destination · AudienceRestriction · Recipient 를 덮는다. 본문을 고치면 서명이 깨지고, 서명을 지키면 앱이 URL 불일치로 거부한다.

★★ 두 조건을 동시에 만족하는 재작성 전략은 존재하지 않는다. 재작성기가 SAML 응답을 **건드리지 않고 통과시키는지**가 필수 판정 항목. /lab/token 의 검증 ledger 로 확인한다.

http://192.168.4.110:4200/api/saml/acs

새 창에서 직접 열어보기 →