🪤 부적절한 예외 처리 시뮬레이터 KISA A-4 · 부적절한 예외 처리
두 가지 안티패턴: (1) 광범위한 빈 catch가 예외를 통째로 삼켜 보안 검사가 조용히 건너뛰어집니다; (2) 핸들러가 전체 스택 트레이스·SQL 오류·내부 경로를 사용자에게 노출합니다. 둘 다 오류를 취약점으로 바꿉니다.
① 취약한 예외 핸들러 VULNERABLE
안티패턴을 선택하세요. 삼킴: 빈 catch가 권한/검증 실패를 숨겨 동작이 그대로 진행됩니다. 노출: 핸들러가 원본 예외(스택 트레이스·SQL·파일 경로)를 응답에 그대로 echo — 스택·DB 스키마를 알려주는 정보 노출.
공격자에게 보이는 HTTP 응답:
(실행 전)
② 안전한 핸들러: 구체적 catch · 안전 메시지 · 서버 로그 SECURE
수정본은 보안 관련 실패를 절대 삼키지 않고(중단), 구체적 예외를 잡으며, 상세 내용은 상관관계 id와 함께 서버에만 기록하고, 사용자에게는 일반 메시지만 반환합니다.
사용자에게 보이는 HTTP 응답:
(실행 전)
내부 서버 로그 (사용자에게 미노출):
(실행 전)
③ 취약 vs 안전 코드
VULNERABLE
// (1) 삼킴 — 보안 검사 실패가 사라진다
try {
checkLicense(user); // 실패하면 예외
enablePremiumFeature(); // 그래도 실행됨?!
} catch (Exception e) {
// 아무것도 안 함 — 예외 통째로 삼킴
}
// (2) 노출 — 내부 정보를 사용자에게
try {
runQuery("SELECT ... WHERE name='" + name + "'");
} catch (Exception e) {
e.printStackTrace(response.getWriter()); // 스택/SQL 노출
response.send(e.toString()); // 경로/버전 노출
}
SECURE
// (1) 보안 실패는 절대 삼키지 않는다
try {
checkLicense(user);
} catch (LicenseException e) {
log.warn("license check failed", e); // 서버 로그
return deny(); // 동작 중단
}
enablePremiumFeature(); // 통과한 경우만
// (2) 구체적 catch + 일반 메시지 + 서버 로그
try {
runParameterizedQuery(name); // SQLi 자체도 차단
} catch (SQLException e) {
String id = UUID.randomUUID().toString();
log.error("query failed id=" + id, e); // 상세는 서버만
return error(500, "처리 중 오류 (ref " + id + ")"); // 일반 메시지
}
삼킴은 보안 통제가 실패했다는 유일한 신호를 없애 — 공격자가 인가된 것처럼 진행합니다. 노출은 스택 트레이스·SQL 오류·경로로 프레임워크 버전·쿼리 구조·파일시스템 지도를 공격자에게 넘겨 다음 공격을 가속합니다. 방어: 구체적 예외만 잡기 · 보안 경로에 빈 catch 금지 · 상세는 상관관계 id와 함께 서버에만 로깅 · 클라이언트에는 일반 메시지(+id)만 · 운영에서 프레임워크 디버그 페이지 비활성화.
⚠️ 교육용 시뮬레이션입니다. 스택 트레이스·SQL 오류·서버 로그는 페이지 내부에서 만든 mock이며, 실제 예외·데이터베이스·파일시스템과 무관합니다.