제한 없는 자원 소비

제한 없는 자원 소비 (API4: Unrestricted Resource Consumption)

API 요청 하나를 처리하려면 네트워크 대역폭, CPU, 메모리, 저장소 같은 자원이 필요해요. 그리고 이메일·SMS·전화 발송이나 생체 인증 같은 자원은 서드파티 API 연동을 통해 요청당 요금을 내고 쓰는 경우가 많아요. 이런 소비에 제한을 두지 않으면, 공격자가 간단한 요청만 반복해 서비스 거부(DoS) 를 일으키거나 운영 비용을 폭발적으로 늘릴 수 있어요. 단순하면 단순한 만큼 자주 발견되고, 공격 도구도 흔해서 광범위하게 피해가 나는 리스크예요.

출처: OWASP API Security Top 10 — API4:2023 Unrestricted Resource Consumption

어떤 API가 취약한가요?

아래 제한 중 하나라도 빠져 있거나 너무 낮거나 높게 잘못 설정돼 있으면 취약해요.

  • 실행 타임아웃(execution timeouts)
  • 최대 할당 가능한 메모리
  • 최대 파일 디스크립터 수
  • 최대 프로세스 수
  • 최대 업로드 파일 크기
  • 단일 API 클라이언트 요청에서 수행할 수 있는 연산 수(예: GraphQL 배칭)
  • 단일 요청-응답에서 한 페이지에 돌려줄 레코드 수

공격 시나리오

시나리오 #1

서드파티 제공자인 Willyo가 이 API 호출 한 건당 $0.05를 청구한다고 해볼게요. 공격자는 첫 번째 API 호출을 수만 번 반복하는 스크립트를 돌려요. 백엔드는 그에 맞춰 Willyo에 수만 번의 문자 발송을 요청하고, 회사는 몇 분 만에 수천 달러의 손실을 보게 돼요.

시나리오 #2

GraphQL API 엔드포인트가 사용자에게 프로필 사진 업로드를 허용한다고 해볼게요.

POST /graphql

{
  "query": "mutation {
    uploadPic(name: "pic1", base64_pic: "R0FOIEFOR0xJVA…") {
      url
    }
  }"
}

API가 uploadPic 연산을 시도할 수 있는 횟수를 제한하지 않으면, 공격자는 GraphQL 배칭으로 같은 요청을 수백 개 실어 보내 서버 메모리를 고갈시키고 서비스 거부를 일으킬 수 있어요.

POST /graphql

[
  {"query": "mutation {uploadPic(name: "pic1", base64_pic: "R0FOIEFOR0xJVA…") {url}}"},
  {"query": "mutation {uploadPic(name: "pic2", base64_pic: "R0FOIEFOR0xJVA…") {url}}"},
  ...
  {"query": "mutation {uploadPic(name: "pic999", base64_pic: "R0FOIEFOR0xJVA…") {url}}"},
]

시나리오 #3

서비스 제공자가 클라이언트가 임의로 큰 파일을 내려받게 허용하는데, 파일이 변경되지 않아 캐시 서비스를 쓰고 있다고 해볼게요. 캐시 서비스는 15GB까지의 파일만 캐시한다고 해요. 그런데 어떤 파일이 업데이트되면서 크기가 18GB로 커지면, 모든 클라이언트가 새 버전을 즉시 땡기기 시작해요. 클라우드 소비 비용 알림이나 최대 비용 허용액이 없으면, 월 청구액이 평균 $13에서 $8,000로 치솟을 수 있어요.

예방 방법

  • 앞서 나열한 제한값(타임아웃, 메모리, 업로드 크기, 페이지당 레코드 수 등)을 정의하고 적절히 설정해요.
  • rate limiting을 구현해 클라이언트가 요청을 보낼 수 있는 비율을 통제해요.
  • 상용 API에 사용되는 서드파티 제공자 비용도 호출량에 연동되므로, 과도한 호출을 막는 제한과 비용 알림을 함께 설계해요.
  • 컨테이너 환경이라면 컨테이너별 자원 한도(CPU·메모리) 를 명시해 단일 인스턴스가 전체를 삼키지 못하게 해요.

더 알아보기