Azure의 GraphQL: 11부 - DoS 쿼리 방지

9375 단어 azuregraphql
이 시리즈의 이전 게시물에서 Post , related 에 대한 새로운 "가상"필드를 GraphQL 스키마에 추가했습니다.

type Post {
  id: ID!
  title: String!
  url: Url!
  date: Date
  tags: [String!]!
  description: String
  content: String!
  related(tag: String): [Post!]
}



하지만 그렇게 하는 과정에서 문제가 추가되었습니다. 이 쿼리를 예로 들어 보겠습니다.

query {
  posts {
    related {
      related {
        related {
          related {
            related {
              related {
                related {
                  related {
                    title
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}



이런... 여기서 무슨 일이 일어날까요? 정확히 당신이 생각하는 것, 내 API에 대한 일련의 재귀 쿼리와 나는 방금 내 서버에 대한 서비스 거부, DoS, 공격 벡터를 생성했습니다(분산되지 않았기 때문에 DDoS 공격이 아닙니다).

그러나 이것은 GraphQL 관점에서 완벽하게 유효합니다. 노출하라고 지시한 그래프를 걷고 있을 뿐입니다. 하지만 저는 그것이 제 서버를 다운시키는 것을 원하지 않았습니다! 이것은 단일 유형의 GraphQL 스키마이지만 더 복잡한 스키마에서는 다른 유형을 통해 원본으로 다시 재귀할 수 있는 유형이 있다는 것이 현실적입니다.

Azure API 관리 GraphQL 정책



좋은 소식입니다. APIM 정책을 활용하여 이 문제를 직접 해결할 수 있습니다. 이번에는 <validate-graphql-request> policy 을 사용하겠습니다.

이 정책은 인바운드 정책입니다. 즉, 요청이 백엔드로 전달되기 전에 적용됩니다. 이 경우에는 GraphQL 리졸버 정책으로 미리 정의한 규칙에 대해 가로채고 유효성을 검사할 수 있습니다.

정책의 두 가지 최상위 속성인 max-sizemax-depth 에 초점을 맞출 것입니다.
max-size 정책은 인바운드 요청 크기 제한을 적용하는 데 사용됩니다. 즉, 100kb를 초과하는 모든 요청을 거부하므로 과도한 쿼리 크기로 인해 과도한 쿼리 크기가 발생할 수 있으므로 단일 요청에서 재시도할 수 있는 데이터의 양을 제한합니다. 데이터베이스 작업을 수행 중입니다.

이를 APIM 정책의 <inbound> 섹션에 추가합니다.

<policies>
    <inbound>
        <base />
        <validate-graphql-request error-variable-name="size" max-size="10240" />
    </inbound>
    <!-- snip -->
</policies>



이것은 유용한 정책입니다. 특히 다양한 유형과 필드를 많이 노출하는 큰 GraphQL 스키마가 있지만 실제로 문제를 해결하지는 못할 것입니다. 크기 모자. 대신 정책의 max-depth 부분을 사용하려고 합니다.
max-depth 를 사용하면 쿼리를 거부하기 전에 요청이 수행할 수 있는 중첩 수준을 지정할 수 있습니다. 정책을 업데이트해 보겠습니다.

<policies>
    <inbound>
        <base />
        <validate-graphql-request error-variable-name="size" max-size="10240" max-depth="3" />
    </inbound>
    <!-- snip -->
</policies>


max-depth에서 알아야 할 한 가지는 GraphQL 작업 유형( query 또는 mutation )으로 시작하는 1 기반 인덱스를 사용한다는 것입니다. 즉, 깊이가 3이면 다음을 허용합니다.

query {
  postsByTag(tag: "graphql") {
    title
    related {
      title
    }
  }
}



그러나이 쿼리는 유효하지 않습니다.

query {
  postsByTag(tag: "graphql") {
    title
    related {
      title
      related {
        title
      }
    }
  }
}



그리고 위의 쿼리를 실행하면 다음 본문과 함께 400 Bad Request 상태를 제공합니다.

{
  "statusCode": 400,
  "message": "The query is too nested to execute, its depth is more than 3 "
}



성공! 우리는 게이트웨이 수준에서 블록을 생성했습니다. 즉, 다운스트림 서버가 불량 쿼리에 의해 적중되는 것에 대해 걱정하지 않아도 됩니다.

결론



GraphQL의 간과하기 쉬운 측면 중 하나는 그래프로 작업하고 그래프에서 탐색 및 악용될 수 있는 재귀 참조를 만들어 백엔드에 대한 DoS 공격 벡터를 생성할 수 있다는 것입니다.

그러나 Azure API Management의 GraphQL 정책으로 쉽게 처리할 수 있는 것입니다.
max-depth 정책의 <validate-graphql-request> 부분을 사용하면 클라이언트가 수행하는 작업에서 과도한 중첩을 방지할 수 있으며 이를 max-size 속성과 결합하여 크고 평평한 요청을 방지할 수 있습니다.

특정 리졸버 필드 또는 경로에 대한 액세스를 제한하는 것과 같이 정책에 설정할 수 있는 다른 규칙이 있지만 독자에게 연습 문제로 남겨두겠습니다. 😉

좋은 웹페이지 즐겨찾기