들어가며

최근 여러 서버 및 API 등에서 보안 사고가 발생하고 있다. 이중 공공 기관등의 서버 직접 침해는 제외하고 API 관련 내용에 대해서 어떤 문제가 있고 왜 발생하고 해결책에 대해 고민해본다.

API 보안은 현대 웹 애플리케이션에서 가장 중요한 고려사항 중 하나이다. 특히 NestJS와 같은 엔터프라이즈급 프레임워크를 사용할 때는 보안에 대한 체계적인 접근이 필요하다.

주요 API 보안 문제점

1. 인증 및 인가 취약점

가장 흔한 문제 중 하나는 인증(Authentication)과 인가(Authorization)의 부적절한 구현이다.

문제점:

  • JWT 토큰의 만료 시간이 너무 길거나 검증이 제대로 이루어지지 않음
  • 역할 기반 접근 제어(RBAC)가 제대로 구현되지 않음
  • 세션 관리가 취약함

발생 원인:

  • 개발 초기 단계에서 보안을 간과하고 기능 구현에만 집중
  • 보안 모범 사례에 대한 이해 부족
  • 테스트 환경과 프로덕션 환경의 보안 설정 차이

2. 입력 검증 부재

사용자 입력에 대한 검증이 제대로 이루어지지 않으면 다양한 공격에 취약해진다.

문제점:

  • SQL Injection
  • NoSQL Injection
  • Command Injection
  • XSS (Cross-Site Scripting)
  • XXE (XML External Entity) 공격

발생 원인:

  • DTO(Data Transfer Object) 검증 로직 누락
  • 화이트리스트 기반 검증 대신 블랙리스트 사용
  • 파일 업로드 시 확장자 및 크기 검증 부재

3. 과도한 정보 노출

에러 메시지나 응답에서 민감한 정보가 노출되는 경우가 많다.

문제점:

  • 스택 트레이스가 그대로 노출됨
  • 데이터베이스 스키마 정보 노출
  • 내부 시스템 구조 정보 노출
  • API 버전 정보 등 메타데이터 과다 노출

발생 원인:

  • 개발 편의성을 위해 상세한 에러 메시지 사용
  • 프로덕션 환경에서도 디버그 모드 활성화
  • 에러 처리 미흡

4. Rate Limiting 부재

API 호출에 대한 제한이 없으면 DDoS 공격이나 무차별 대입 공격에 취약하다.

문제점:

  • 무제한 API 호출 가능
  • 로그인 시도 횟수 제한 없음
  • 특정 IP나 사용자에 대한 제한 없음

발생 원인:

  • Rate limiting의 중요성 인식 부족
  • 구현 복잡도에 대한 우려
  • 성능 영향에 대한 과도한 걱정

5. CORS 설정 오류

Cross-Origin Resource Sharing 설정이 잘못되면 CSRF 공격에 취약해진다.

문제점:

  • 모든 Origin 허용 (*)
  • Credentials 허용과 함께 와일드카드 사용
  • 필요한 헤더나 메서드만 허용하지 않음

발생 원인:

  • CORS 정책에 대한 이해 부족
  • 개발 편의성을 위해 느슨한 설정 사용
  • 프로덕션 환경에서도 개발 환경 설정 유지

6. 민감한 데이터 평문 저장

비밀번호나 개인정보를 암호화하지 않고 저장하는 경우가 있다.

문제점:

  • 비밀번호 평문 저장
  • 개인정보 암호화 미흡
  • API 키나 토큰을 코드에 하드코딩

발생 원인:

  • 암호화의 필요성 인식 부족
  • 구현 복잡도 회피
  • 환경 변수 관리 미흡

보안 문제점에 대한 대응의 현실판

핵심 요약

  • 기술적으로 “무엇이 문제인지”는 대부분 알고 있다. 문제는 “언제, 어떻게 고칠지”에 대한 조직적 의사결정과 리스크 수용이다.
  • 취약점 식별은 쉽다. 개선(마이그레이션, 다운타임 설득, 회귀 테스트)과 책임소재가 어려운 지점이다.

확인은 쉽다, 개선이 어렵다

  • npm audit, IDE 취약점 스캐너(mend.io 등)로 이슈 추적은 즉시 가능
    # npm audit를 통한 취약점 점검
    npm audit
    npm audit fix
    
  • 어려운 점
    • 연쇄적 버전 업그레이드(의존 모듈 동반 상향, 브레이킹 체인지)
    • 테스트 커버리지 부족으로 인한 회귀 리스크
    • 다운타임/릴리스 윈도우 허용을 얻기 위한 내부 설득

현장에서 자주 보이는 안티패턴

  • 인증/인가를 “임시로” 느슨하게 풀고 그대로 굳어짐
  • 목적이 다른 API를 권한 범위만 비틀어 재사용
  • 내부 백오피스용 우회키를 제품 경로에 유입
  • 공개/비공개 도메인을 분리하지 않고 한 API에 혼합
  • 응답 필터링/프로젝션 정책(PROFILE_SELECT_OPTION 등)이 누적 변경으로 무너짐

실패가 생기는 전형적 흐름(예)

1) 원래 분리했어야 할 /users/profiles/public/users/profiles/private를 개발속도/복잡도 이유로 합침
2) 이후 기능 추가(예: 팔로워 수) 시 응답 필터 누락
3) 쿼리 프로젝션 옵션에 민감정보가 섞여 들어오고, 일부 엔드포인트에서 필터링 누락
4) “안전한 내부 호출만”이라는 가정이 깨지는 순간 사고로 이어짐

실무적 대안 체크리스트

  • API 스코프를 공개/비공개로 물리적으로 분리하고, 합칠 때는 응답 빌더에서 화이트리스트 필터를 기본값으로 사용
  • 역할·권한은 느슨화 대신 “명시적 추가 엔드포인트”로 대응(임시 완화 금지)
  • 프로덕션에 들어가는 우회키/백도어성 파라미터는 금지, 필요 시 별도 네트워크 경계 내 내부 전용 서비스로 격리
  • 주기적 의존성 업그레이드 데이 운영(브레이킹 체인지 적립 방지)
  • 변경 전후 API 스냅샷/계약 테스트로 회귀 리스크 통제

마무리

한 줄 핵심

  • 보안은 “지속 업그레이드 + 명시적 분리 + 테스트로 통제”가 전부다.

바로 적용 가능한 액션 아이템

  • 의존성 정기 업그레이드 스프린트 운영(브레이킹 체인지 적립 금지)
  • OS/런타임은 메이저 릴리스 라인 추종(보안 패치 라인 유지)
  • 공개/비공개/민감 데이터 접근 경로를 물리적으로 분리
  • 화이트리스트 기반 응답 필터를 기본 정책으로 채택
  • 계약/스냅샷/보안 회귀 테스트를 CI에 상시화
  • 완화(waiver)는 만료일·보상통제와 함께 티켓으로 관리

마지막으로

  • 모든 노력을 다해도 사고는 완전히 0이 되지 않는다. 중요한 건 “빨리 감지하고, 영향 범위를 작게, 복구를 빠르게” 하는 체계다.
  • AI 도구로 문서·테스트 생산성은 좋아지고 있지만, 공격자도 똑같이 빨라진다. 기본기에 충실하되, 자동화로 빈도를 높이자.
  • 오늘도 우리의 서버가 안전하길.

참고 자료