예외 처리 미흡
점검 목적
잘못된 자료형, 누락된 값, 만료된 인증 정보 같은 비정상 상황에서도 애플리케이션이 안전하게 거절되는지 확인한다. 상세 오류가 외부에 노출되는지, 검증 예외가 권한 통과로 이어지는지, 오류 뒤 사용한 자원이 정상적으로 정리되는지가 핵심이다.
스택 트레이스나 디버그 정보의 일반적인 노출은 정보 노출, 계정 존재 여부 차이는 인증에서 더 넓게 다룬다. 결제 일부 처리, 포인트·사용 횟수 불일치, 허용되지 않은 상태 전이는 비즈니스 로직, 중복 callback과 동시 처리 문제는 Race Condition으로 분리한다. 이 문서는 예외가 발생했을 때 안전하게 실패하는지에 집중한다.
유형 구분
| 유형 | 특징 | 실무 판단 |
|---|---|---|
| 상세 오류 노출 | 스택 트레이스, 경로, 쿼리, 내부 주소가 응답에 포함됨 | 노출 값의 민감도와 실제 활용 가능성을 확인 |
| 예외 시 통과 | 검증 도중 오류가 나면 거부하지 않고 진행함 | 보호 데이터나 기능이 실제로 열리는지 확인 |
| 응답 불일치 | 같은 실패가 상태 코드·본문·시간에서 다르게 보임 | 사용자·자원 존재 여부를 안정적으로 구분할 수 있는지 확인 |
| 자원 정리 실패 | 오류 뒤 파일·세션·락·임시 상태가 남음 | 한 번의 통제된 실패 뒤 정상 요청 영향 확인 |
진단 절차
Step 1. 정상과 예상된 실패 기준 기록
- 정상 요청과 함께 필수 필드 누락, 인증 없음, 권한 없음, 존재하지 않는 자원 요청을 각각 저장한다.
- 상태 코드, 본문 구조, 응답 헤더, 쿠키 변화, 응답 시간과 후속 상태를 기록한다.
400,401,403,404,409,422처럼 의도된 실패와 처리하지 못한500을 구분한다.
Step 2. 입력별 최소 오류 유도
- 한 요청에서 한 값만
null, 빈 문자열, 잘못된 자료형, 누락 값으로 바꾼다. - 숫자는
0,-1, 정상 범위를 조금 넘는 값부터 확인한다. - JSON은 문법 오류, 중복 키, 배열·객체 바꾸기를 필요한 입력에만 적용한다.
- 대용량 본문, 장시간 지연, 동시 요청은 기본 오류 확인에 사용하지 않는다.
Step 3. 어느 계층의 오류인지 구분
- CDN·WAF·리버스 프록시가 만든 HTML 오류인지 애플리케이션 JSON 오류인지 확인한다.
Server,Via,X-Request-ID,traceparent와 본문 오류 식별자를 함께 본다.- 같은 요청을 다시 보내 오류가 반복되는지 확인한다. 일회성 게이트웨이 오류는 앱 결함과 분리한다.
Step 4. 보호 동작과 자원 정리 확인
200과500만 보지 말고 보호 데이터, 세션, 쿠키와 권한이 바뀌었는지 확인한다.- 업로드·편집 잠금·일회용 토큰은 오류 뒤 같은 테스트 객체를 정상적으로 다시 사용할 수 있는지 확인한다.
- 외부 인증 서비스의 실패를 mock할 수 있다면 접근이 거부되는지만 확인한다. 주문·결제 상태 정합성은 비즈니스 로직 문서로 분리한다.
상황별 빠른 선택
| 현재 상황 | 첫 확인 |
|---|---|
| 숫자 ID를 받는 조회 API | 문자열, 0, -1, 존재하지 않는 정상 형식 ID |
| JSON 생성·수정 API | 필수 필드 누락, null, 문자열·객체 자료형 교체 |
| 인증된 API | 토큰 없음, 잘못된 토큰, 권한 없는 테스트 계정 |
| 업로드·편집·일회용 토큰 | 오류 한 번 뒤 정상 요청이 가능한지 확인 |
| 외부 인증 연동 | mock 실패 응답에서 접근이 거부되는지 확인 |
500 또는 HTML 오류 | 원시 응답 헤더와 생성 계층 확인 |
| 로그인·비밀번호 재설정 | 존재하는 테스트 계정과 없는 계정의 응답 비교 |
페이로드 노트
1. 필수 값과 자료형을 한 개씩 변경
이럴 때 사용: JSON API가 기대하지 않은 값을 어떻게 처리하는지 가장 먼저 확인할 때 사용한다.
{"quantity":1,"product_id":"TEST-100"}
아래 값은 한 번에 하나씩 바꾼다.
{"quantity":null,"product_id":"TEST-100"}
{"quantity":"1","product_id":"TEST-100"}
{"quantity":{},"product_id":"TEST-100"}
검증 오류가 일반화된 400·422 응답으로 끝나는지, 내부 클래스명이나 쿼리가 노출되는지, 예외 뒤 보호 기능이 기본 허용값으로 처리되는지 확인한다.
2. 경로·쿼리 숫자의 경계 확인
이럴 때 사용: 숫자형 자원 ID, 페이지 번호, 수량을 받는 요청에서 사용한다.
GET /api/orders/not-a-number HTTP/1.1
GET /api/orders/0 HTTP/1.1
GET /api/orders/-1 HTTP/1.1
문자열에서 변환 스택 트레이스가 나오는지, 음수가 다른 자원으로 정규화되는지, 존재하지 않는 ID가 권한 검사를 건너뛰는지 확인한다. 정상적인 400이나 404만 반환되면 취약점이 아니다.
3. JSON 문법과 Content-Type 오류 확인
이럴 때 사용: API 파서, 프레임워크 전역 오류 처리, 게이트웨이와 앱의 응답 차이를 확인할 때 사용한다.
POST /api/profile HTTP/1.1
Content-Type: application/json
{"display_name":"test"
POST /api/profile HTTP/1.1
Content-Type: text/plain
{"display_name":"test"}
깨진 JSON은 보통 400, 지원하지 않는 형식은 415가 자연스럽다. 500이 나오더라도 내부 정보, 상태 변화, 반복 재현이 없으면 오류 처리 개선 후보일 뿐 보안 취약점으로 바로 확정하지 않는다.
4. 인증·권한 오류가 안전하게 닫히는지 확인
이럴 때 사용: 인증 또는 권한 검사 과정에서 파싱·검증 예외가 발생할 수 있는 보호 API에 사용한다.
GET /api/account/summary HTTP/1.1
Authorization: Bearer invalid.test.token
GET /api/admin/summary HTTP/1.1
Authorization: Bearer <LOW_PRIVILEGE_TEST_TOKEN>
잘못된 인증 정보는 거절되어야 한다. 오류 본문이 반환되면서 보호 데이터도 함께 포함되거나, 권한 검사 예외 뒤 기본 관리자·익명 권한으로 실행되면 fail-open이다. 401과 403의 차이는 정상적인 인증·인가 구분일 수 있으므로 그 자체를 문제로 보지 않는다.
5. 외부 인증 실패 시 접근 거부 확인
이럴 때 사용: 테스트 환경에서 SSO·토큰 검증 서비스의 실패 응답을 mock 또는 프록시로 바꿀 수 있을 때 사용한다.
| 모의 응답 | 확인할 것 |
|---|---|
| timeout | 로컬 세션이나 기본 권한이 발급되지 않음 |
401·서명 오류 | 외부 검증 실패로 접근이 종료됨 |
| 잘못된 JSON | 파싱 예외 뒤 인증 성공값을 사용하지 않음 |
외부 서비스를 직접 느리게 하거나 중단하지 않는다. 결제·주문 상태, 재시도, callback 정합성은 비즈니스 로직에서 확인한다.
6. 오류 응답의 노출 정보 확인
이럴 때 사용: 앞선 최소 변조에서 앱 또는 프레임워크 오류가 반환됐을 때 사용한다.
| 노출 값 | 실무 판단 |
|---|---|
| 오류 식별자·요청 ID | 운영자 추적용이면 일반적으로 정상 |
| 프레임워크 이름 | 단독 영향은 낮고 정확한 버전·취약 상태를 추가 확인 |
| 소스 경로·함수·줄 번호 | 내부 구조 파악에 직접 도움이 되는지 확인 |
| 테이블·컬럼·원본 쿼리 | SQLi 등 다음 진단에 사용할 수 있는지 확인 |
| 내부 호스트·포트·URL | 내부 접근 경로와 결합 가능한지 확인 |
| 비밀번호·토큰·연결 문자열 | 원문을 재노출하지 말고 마스킹해 사용 가능성만 확인 |
안전한 외부 응답은 원인을 상세히 설명하지 않아도 된다.
{
"error":"request_failed",
"request_id":"req-7f3a"
}
7. 계정·자원 존재 여부는 차이만 확인
이럴 때 사용: 로그인, 비밀번호 재설정, 초대, 자원 조회에서 같은 실패가 서로 다르게 보일 때 사용한다.
존재하는 테스트 계정 + 잘못된 값
존재하지 않는 계정 + 같은 잘못된 값
본문, 상태 코드, 길이와 시간을 비교한다. 여기서는 오류 응답이 일관적인지만 보고, 계정 목록 확인이나 후속 이메일 검증은 인증의 사용자 열거 절차로 이어간다.
8. 오류 뒤 자원 정리 여부 확인
이럴 때 사용: 업로드, 임시 예약, 편집 잠금, 일회용 토큰 처리 중 한 번의 오류가 발생한 경우 사용한다.
- 오류 후 같은 테스트 파일을 정상 업로드할 수 있는지 확인한다.
- 테스트 초안의 편집 잠금이 해제됐는지 확인한다.
- 실패한 일회용 토큰이 잘못 소모되거나 다시 유효해지지 않았는지 확인한다.
- 임시 객체가 사용자에게 보이거나 다음 요청에 재사용되지 않는지 확인한다.
반복 오류로 자원을 고갈시키지 않고, 통제된 실패 한 번과 정상 요청 한 번으로 확인한다. 동시성 자체가 핵심이면 Race Condition 절차로 분리한다.
9. Burp에서 응답 차이 정리
이럴 때 사용: 상태 코드는 같지만 본문이나 헤더가 미묘하게 다를 때 사용한다.
- Repeater에서 정상, 예상 실패, 예외 유도 요청을 각각 저장한다.
- Comparer로 본문과 헤더 차이를 비교한다.
- Logger 또는 HTTP history에서 redirect, refresh 요청, 후속 API 호출을 확인한다.
- 자동 스캔 결과는 동일한 최소 요청으로 다시 재현한다.
우회 매트릭스
| 관찰 결과 | 다음 확인 | 판단 |
|---|---|---|
| 잘못된 JSON이 CDN HTML로 거절됨 | 정상 JSON의 자료형 오류로 앱 계층 확인 | 앱 오류 처리까지 도달하지 않음 |
| 모든 오류가 같은 JSON임 | 헤더, 쿠키, 후속 상태를 비교 | 일관된 본문은 긍정적 단서 |
응답은 200이고 본문에 error가 있음 | 실제 상태·데이터·부수 효과 확인 | 상태 코드만으로 성공 판정 금지 |
한 번만 500이 발생함 | 같은 최소 요청을 재전송 | 일회성 오류는 근거 부족 |
| 스택 트레이스는 없고 요청 ID만 있음 | ID에 내부 정보가 포함되는지 확인 | 무작위 추적 ID는 정상 |
404가 권한 없음과 자원 없음에 동일함 | 본문·시간·부수 효과 비교 | 자원 존재를 숨기는 설계일 수 있음 |
| 응답 시간만 다름 | 동일 조건을 여러 번 교차 측정 | 반복되는 차이만 후보 |
| 개발 환경에서만 상세 오류가 보임 | 외부 접근성과 실제 데이터 연결 확인 | 공개된 개발 환경이면 별도 영향 판단 |
| 프록시 오류와 앱 오류 모양이 다름 | Via, 요청 ID, 서버 로그 연결 확인 | 생성 계층을 나눠 기록 |
취약 판정
확정
- 인증·권한·서명 검증 중 예외가 발생했는데 보호 데이터나 기능이 허용된다.
- 외부 인증 서비스의 실패가 성공으로 처리되어 로컬 세션이나 접근 권한이 발급된다.
- 오류 응답에 사용 가능한 자격증명, 토큰, 연결 문자열 또는 민감 데이터가 노출된다.
- 한 번의 통제된 실패 뒤 잠금·임시 객체·일회용 상태가 남아 다른 정상 흐름에 영향을 준다.
후보 또는 보류
- 처리하지 못한 입력에서
500만 발생한다. - 무작위 요청 ID나 일반적인 오류 코드만 반환된다.
- 프레임워크 이름이나 내부 경로가 보이지만 추가 활용 가능성이 확인되지 않는다.
401,403,404가 상황에 맞게 서로 다르게 반환된다.- 시간 차이가 작거나 반복되지 않는다.
- mock 없는 운영 환경이라 외부 인증 실패를 안전하게 확인할 수 없다.
영향 상승
- 예외로 다른 사용자·관리자 권한 또는 조직 경계를 넘는다.
- 노출된 비밀이 실제 내부 서비스 인증이나 다른 취약점 재현에 사용된다.
- 오류 상태가 여러 요청이나 사용자에게 지속된다.
- 제한된 단일 요청만으로도 서비스 가용성 저하가 반복 재현된다.
참고자료
- OWASP Top 10:2025 A10 - Mishandling of Exceptional Conditions
- OWASP Error Handling Cheat Sheet
- OWASP WSTG - Testing for Error Handling
- OWASP - Improper Error Handling
- PortSwigger - Information disclosure
- CWE-209 - Generation of Error Message Containing Sensitive Information
- CWE-703 - Improper Check or Handling of Exceptional Conditions