개발 slecs

결제 플랫폼 보안 취약점 9건 한꺼번에 잡은 후기

목차

코드 리뷰 한 방에 9건

결제 플랫폼 코드 리뷰 받은 거 한꺼번에 정리함. CRITICAL 2건, HIGH 4건, MEDIUM 3건. 충전/이체/파트너 관리/API 키 인증 구간이 골고루 걸렸음. 생각보다 한 군데 몰려 있어서 작업 자체는 반나절 컷.

등급 영역 핵심
CRITICAL 이체 금액 검증 누락 + 동시성
CRITICAL API 키 인증 평문 비교
HIGH 충전 중복 요청 처리
HIGH 파트너 조회 권한 우회
MEDIUM 공통 로깅에 민감정보 노출

CRITICAL 두 건이 제일 아팠음

이체 쪽은 음수 금액·0원이 그대로 통과되는 케이스가 있었음. 프론트에서 막고 있다고 안심했던 건데, 외부에서 직접 호출이 들어오면 그대로 트랜잭션이 깔리는 구조였음. 진입점에서 다시 막아야 한다는 걸 또 까먹은 거였음.

if (amount == null || amount.signum() <= 0) {
    throw new IllegalArgumentException("amount must be positive");
}

API 키 쪽은 더 부끄러움. 그냥 equals 로 비교하고 있었음. 길이 다르면 빨리 빠져나오는 패턴이라 타이밍 공격 여지가 있다고 지적받음. 상수시간 비교로 바꿔서 정리함.

  • 검증은 진입 레이어에서 한 번 + 도메인에서 한 번, 두 겹으로
  • 비밀값 비교는 무조건 상수시간 비교 함수
  • 동시성은 DB 레벨 락으로, 애플리케이션 락으로 잡으려고 하지 말 것

HIGH/MEDIUM 정리

충전 중복 요청은 멱등키를 받아두고 처리 결과를 캐싱하는 식으로 풀었음. 같은 요청을 두 번 누르는 사용자가 생각보다 많아서, 토스트 띄워도 그새 두 번 들어오는 케이스가 잡힘.

파트너 조회는 전형적인 IDOR 비슷한 거였음. 파라미터로 받은 파트너 식별자를 그대로 신뢰하면 안 되는데, 세션 컨텍스트에 들어 있는 파트너 식별자랑 일치하는지 한 번 더 확인하도록 고침.

  • MEDIUM 로깅 이슈는 카드 뒷자리·전화번호가 평문으로 찍히던 구간 마스킹
  • 마스킹 유틸을 따로 빼서 다른 진입 레이어도 같이 정리
  • 권한 체크 헬퍼 하나로 통일해서 누락 방지

회고

리뷰 받기 전엔 "이 정도는 이미 다 막아뒀지" 라고 생각했는데 막상 받아 보니 9건. 특히 검증 누락은 진입점이 늘어날수록 계속 새는 부분이라, 차라리 공통 검증기를 따로 하나 두는 게 낫겠다는 생각. 동시성도 트래픽이 더 늘기 전에 한 번 정리해 두는 게 안전해 보임. 다음 리뷰 들어가기 전까지 그 두 가지 먼저 손보는 걸로.

댓글 0

첫 댓글 달아줘.