Translated ['src/network-services-pentesting/pentesting-web/graphql.md']

This commit is contained in:
Translator 2025-02-05 10:25:23 +00:00
parent 9612722432
commit 174aa44751

View File

@ -4,11 +4,11 @@
## Introduction
GraphQL은 **효율적인 대안**으로 **REST API**에 강조되며, 백엔드에서 데이터를 쿼리하는 간소화된 접근 방식을 제공합니다. REST는 데이터를 수집하기 위해 다양한 엔드포인트에 여러 요청을 필요로 하는 반면, GraphQL은 **단일 요청**을 통해 필요한 모든 정보를 가져올 수 있게 합니다. 이러한 간소화는 데이터 가져오기 프로세스의 복잡성을 줄여 **개발자에게 큰 이점**을 제공합니다.
GraphQL은 **효율적인 대안**으로 **REST API**에 주목받고 있으며, 백엔드에서 데이터를 쿼리하는 간소화된 접근 방식을 제공합니다. REST는 데이터를 수집하기 위해 다양한 엔드포인트에 여러 요청을 필요로 하는 반면, GraphQL은 **단일 요청**을 통해 필요한 모든 정보를 가져올 수 있니다. 이러한 간소화는 데이터 가져오기 프로세스의 복잡성을 줄여 **개발자에게 큰 이점**을 제공합니다.
## GraphQL과 보안
GraphQL을 포함한 새로운 기술의 출현과 함께 새로운 보안 취약점도 발생합니다. 주목할 점은 **GraphQL은 기본적으로 인증 메커니즘을 포함하지 않습니다**. 개발자가 이러한 보안 조치를 구현하는 것이 책임입니다. 적절한 인증이 없으면 GraphQL 엔드포인트가 인증되지 않은 사용자에게 민감한 정보를 노출할 수 있어 상당한 보안 위험을 초래합니다.
GraphQL을 포함한 새로운 기술의 출현과 함께 새로운 보안 취약점도 발생합니다. 주목할 점은 **GraphQL은 기본적으로 인증 메커니즘을 포함하지 않는다**는 것입니다. 개발자가 이러한 보안 조치를 구현하는 것이 책임입니다. 적절한 인증이 없으면 GraphQL 엔드포인트가 인증되지 않은 사용자에게 민감한 정보를 노출할 수 있어 상당한 보안 위험을 초래합니다.
### 디렉토리 브루트 포스 공격과 GraphQL
@ -31,7 +31,7 @@ GraphQL을 포함한 새로운 기술의 출현과 함께 새로운 보안 취
#### 유니버설 쿼리 <a href="#universal-queries" id="universal-queries"></a>
URL이 GraphQL 서비스인지 확인하기 위해 **유니버설 쿼리**인 `query{__typename}`을 보낼 수 있습니다. 응답에 `{"data": {"__typename": "Query"}}`가 포함되면 해당 URL이 GraphQL 엔드포인트를 호스팅하고 있음을 확인니다. 이 방법은 쿼리된 객체의 유형을 나타내는 GraphQL의 `__typename` 필드에 의존합니다.
URL이 GraphQL 서비스인지 확인하기 위해 **유니버설 쿼리**인 `query{__typename}`을 보낼 수 있습니다. 응답에 `{"data": {"__typename": "Query"}}`가 포함되면 해당 URL이 GraphQL 엔드포인트를 호스팅하고 있음을 확인할 수 있습니다. 이 방법은 쿼리된 객체의 유형을 나타내는 GraphQL의 `__typename` 필드에 의존합니다.
```javascript
query{__typename}
```
@ -57,7 +57,7 @@ query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofTy
**오류**
**오류**가 **표시**될지 아는 것은 흥미롭습니다. 이는 유용한 **정보**에 기여할 것입니다.
**오류**가 **표시**될 것인지 아는 것은 흥미롭습니다. 이는 유용한 **정보**에 기여할 것입니다.
```
?query={__schema}
?query={}
@ -162,7 +162,7 @@ name
```
/?query=fragment%20FullType%20on%20Type%20{+%20%20kind+%20%20name+%20%20description+%20%20fields%20{+%20%20%20%20name+%20%20%20%20description+%20%20%20%20args%20{+%20%20%20%20%20%20...InputValue+%20%20%20%20}+%20%20%20%20type%20{+%20%20%20%20%20%20...TypeRef+%20%20%20%20}+%20%20}+%20%20inputFields%20{+%20%20%20%20...InputValue+%20%20}+%20%20interfaces%20{+%20%20%20%20...TypeRef+%20%20}+%20%20enumValues%20{+%20%20%20%20name+%20%20%20%20description+%20%20}+%20%20possibleTypes%20{+%20%20%20%20...TypeRef+%20%20}+}++fragment%20InputValue%20on%20InputValue%20{+%20%20name+%20%20description+%20%20type%20{+%20%20%20%20...TypeRef+%20%20}+%20%20defaultValue+}++fragment%20TypeRef%20on%20Type%20{+%20%20kind+%20%20name+%20%20ofType%20{+%20%20%20%20kind+%20%20%20%20name+%20%20%20%20ofType%20{+%20%20%20%20%20%20kind+%20%20%20%20%20%20name+%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}++query%20IntrospectionQuery%20{+%20%20schema%20{+%20%20%20%20queryType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20mutationType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20types%20{+%20%20%20%20%20%20...FullType+%20%20%20%20}+%20%20%20%20directives%20{+%20%20%20%20%20%20name+%20%20%20%20%20%20description+%20%20%20%20%20%20locations+%20%20%20%20%20%20args%20{+%20%20%20%20%20%20%20%20...InputValue+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}
```
마지막 코드 줄은 graphql 쿼리로, graphql의 모든 메타 정보를 덤프합니다 (객체 이름, 매개변수, 유형...)
마지막 코드 줄은 graphql 쿼리로, graphql의 모든 메타 정보를 덤프합니다 (객체 이름, 매개변수, 유형...)
![](<../../images/image (363).png>)
@ -176,7 +176,7 @@ name
![](<../../images/Screenshot from 2021-03-13 18-17-48.png>)
쿼리 "_flags_"의 유형이 "_Flags_"라는 점에 유의하세요. 이 객체는 아래와 같이 정의됩니다:
쿼리 "_flags_"의 유형이 "_Flags_"에 유의하세요. 이 객체는 아래와 같이 정의됩니다:
![](<../../images/Screenshot from 2021-03-13 18-22-57 (1).png>)
@ -193,7 +193,7 @@ query={flags{name, value}}
query = { hiddenFlags }
```
다른 예에서 "_Query_" 타입 객체 안에 두 개의 객체가 있었습니다: "_user_"와 "_users_".\
이 객체들이 검색을 위해 어떤 인수도 필요하지 않다면, 원하는 데이터를 **요청**하는 것만으로도 **모든 정보를 가져올 수 있습니다**. 이 인터넷 예제에서는 저장된 사용자 이름과 비밀번호를 추출할 수 있습니다:
이 객체들이 검색을 위해 어떤 인수도 필요하지 않다면, 원하는 데이터를 요청하기만 하면 **모든 정보를 가져올 수 있습니다**. 이 인터넷 예제에서는 저장된 사용자 이름과 비밀번호를 추출할 수 있습니다:
![](<../../images/image (880).png>)
@ -201,12 +201,12 @@ query = { hiddenFlags }
![](<../../images/image (1042).png>)
떤 식으로든 "_**uid**_" 타입 _**Int**_의 인수를 사용하여 검색하는 것 같습니다.\
떻게든 "_**uid**_" 타입 _**Int**_의 인수를 사용하여 검색할 것 같습니다.\
어쨌든, 우리는 이미 [Basic Enumeration](graphql.md#basic-enumeration) 섹션에서 필요한 모든 정보를 보여주는 쿼리가 제안되었다는 것을 알고 있었습니다: `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
제가 제공한 이미지를 읽어보면, 그 쿼리를 실행했을 때 "_**user**_"가 타입 _Int_의 **arg** "_**uid**_"를 가지고 있음을 알 수 있습니다.
제가 그 쿼리를 실행했을 때 제공된 이미지를 읽어보면 "_**user**_"가 타입 _Int_의 **arg** "_**uid**_"를 가지고 있음을 알 수 있습니다.
그래서 가벼운 _**uid**_ 브루트포스를 수행한 결과, _**uid**=**1**_에서 사용자 이름과 비밀번호를 검색할 수 있었습니다:\
그래서 가벼운 _**uid**_ 브루트포스를 수행한 결과, _**uid**=**1**_에서 사용자 이름과 비밀번호가 검색되었습니다:\
`query={user(uid:1){user,password}}`
![](<../../images/image (90).png>)
@ -215,17 +215,17 @@ query = { hiddenFlags }
![](<../../images/image (707).png>)
그리고 **열거 단계**에서 "_**dbuser**_" 객체가 "_**user**_"와 "_**password**_" 필드를 가지고 있다는 것을 발견했습니다.
그리고 **열거 단계**에서 "_**dbuser**_" 객체가 "_**user**_"와 "_**password**_"라는 필드를 가지고 있음을 발견했습니다.
**쿼리 문자열 덤프 트릭 (thanks to @BinaryShadow\_)**
문자열 타입으로 검색할 수 있다면, 예를 들어: `query={theusers(description: ""){username,password}}`와 같이 **빈 문자열**을 **검색**하면 **모든 데이터****덤프**합니다. (_이 예제는 튜토리얼의 예제와 관련이 없으므로, 이 예제에서는 "**description**"이라는 문자열 필드를 사용하여 "**theusers**"를 검색할 수 있다고 가정합니다_).
문자열 타입으로 검색할 수 있다면, 예를 들어: `query={theusers(description: ""){username,password}}`와 같이 **빈 문자열**을 검색하면 **모든 데이터를 덤프**합니다. (_이 예제는 튜토리얼의 예제와 관련이 없으므로, 이 예제에서는 "**description**"이라는 문자열 필드를 사용하여 "**theusers**"를 검색할 수 있다고 가정합니다_).
### 검색
이 설정에서, **데이터베이스**는 **사람들**과 **영화**를 포함합니다. **사람들**은 그들의 **이메일**과 **이름**으로 식별되며; **영화**는 그들의 **이름**과 **평점**으로 식별됩니다. **사람들**은 서로 친구가 될 수 있으며, 또한 영화가 있어 데이터베이스 내의 관계를 나타냅니다.
이름으로 사람들을 **검색**하고 그들의 이메일을 가져올 수 있습니다:
당신은 **이름**으로 사람들을 **검색**하고 그들의 이메일을 얻을 수 있습니다:
```javascript
{
searchPerson(name: "John Doe") {
@ -248,7 +248,7 @@ name
}
}
```
`name`을 가져오는 방법은 `subscribedMovies`의 사람을 나타냅니다.
`subscribedMovies`의 `name`을 가져오는 방법이 표시되어 있습니다.
여러 개의 객체를 **동시에 검색할 수 있습니다**. 이 경우, 2개의 영화를 검색합니다:
```javascript
@ -281,17 +281,17 @@ name
}
}
```
### 변형
### Mutations
**변은 서버 측에서 변경을 수행하는 데 사용됩니다.**
**변은 서버 측에서 변경을 수행하는 데 사용됩니다.**
**인트로스펙션**에서 **선언된** **변**을 찾을 수 있습니다. 다음 이미지에서 "_MutationType_"은 "_Mutation_"이라고 하며, "_Mutation_" 객체는 변의 이름(이 경우 "_addPerson_")을 포함합니다:
**인트로스펙션**에서 **선언된** **변**을 찾을 수 있습니다. 다음 이미지에서 "_MutationType_"은 "_Mutation_"이라고 하며, "_Mutation_" 객체는 변의 이름(이 경우 "_addPerson_")을 포함합니다:
![](<../../images/Screenshot from 2021-03-13 18-26-27 (1).png>)
이 설정에서 **데이터베이스**는 **사람**과 **영화**를 포함합니다. **사람**은 **이메일**과 **이름**으로 식별되며, **영화**는 **이름**과 **평점**으로 식별됩니다. **사람**은 서로 친구가 될 수 있으며, 데이터베이스 내의 관계를 나타내는 영화를 가질 수 있습니다.
이 설정에서 **데이터베이스**는 **사람**과 **영화**를 포함합니다. **사람**은 **이메일**과 **이름**으로 식별되며, **영화**는 **이름**과 **평점**으로 식별됩니다. **사람**은 서로 친구가 될 수 있으며, 데이터베이스 내의 관계를 나타내는 영화를 가질 수 있습니다.
데이터베이스 내에서 **새로운** 영화를 **생성하는**형은 다음과 같을 수 있습니다(이 예에서 변형은 `addMovie`라고 합니다):
데이터베이스 내에서 **새로운** 영화를 **생성하는**경은 다음과 같을 수 있습니다(이 예제에서 변경은 `addMovie`라고 불립니다):
```javascript
mutation {
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
@ -304,7 +304,7 @@ rating
```
**쿼리에서 데이터의 값과 유형이 어떻게 표시되는지 주목하세요.**
또한, 데이터베이스는 `addPerson`이라는 **변경** 작업을 지원하며, 이를 통해 **사람**을 생성하고 기존 **친구** 및 **영화**와의 연관성을 설정할 수 있습니다. 친구와 영화는 새로 생성된 사람과 연결하기 전에 데이터베이스에 미리 존재해야 한다는 점이 중요합니다.
또한, 데이터베이스는 `addPerson`이라는 **변경** 작업을 지원하며, 이를 통해 기존 **친구** 및 **영화**와의 연관성을 가진 **사람**을 생성할 수 있습니다. 친구와 영화는 새로 생성된 사람과 연결하기 전에 데이터베이스에 미리 존재해야 한다는 점이 중요합니다.
```javascript
mutation {
addPerson(name: "James Yoe", email: "jy@example.com", friends: [{name: "John Doe"}, {email: "jd@example.com"}], subscribedMovies: [{name: "Rocky"}, {name: "Interstellar"}, {name: "Harry Potter and the Sorcerer's Stone"}]) {
@ -339,7 +339,7 @@ releaseYear
### Batching brute-force in 1 API request
이 정보는 [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/)에서 가져왔습니다.\
GraphQL API를 통해 **다양한 자격 증명을 가진 많은 쿼리를 동시에 전송하여 인증**을 확인합니다. 이는 고전적인 brute force 공격이지만, 이제 GraphQL batching 기능 덕분에 HTTP 요청당 하나 이상의 로그인/비밀번호 쌍을 보낼 수 있습니다. 이 접근 방식은 외부 속도 모니터링 애플리케이션을 속여 모든 것이 잘되고 있으며 비밀번호를 추측하려는 brute-forcing 봇이 없다고 생각하게 만듭니다.
GraphQL API를 통해 **다양한 자격 증명을 가진 많은 쿼리를 동시에 전송하여 인증**을 확인합니다. 이는 고전적인 brute force 공격이지만, 이제 GraphQL batching 기능 덕분에 HTTP 요청당 하나 이상의 로그인/비밀번호 쌍을 보낼 수 있습니다. 이 접근 방식은 외부 속도 모니터링 애플리케이션을 속여 모든 것이 잘 되고 있으며 비밀번호를 추측하려는 brute-forcing 봇이 없다고 생각하게 만듭니다.
아래는 **한 번에 3개의 서로 다른 이메일/비밀번호 쌍**을 가진 애플리케이션 인증 요청의 가장 간단한 시연입니다. 분명히 같은 방식으로 단일 요청에서 수천 개를 보낼 수 있습니다:
@ -351,11 +351,11 @@ GraphQL API를 통해 **다양한 자격 증명을 가진 많은 쿼리를 동
## GraphQL Without Introspection
점점 더 많은 **graphql 엔드포인트가 introspection을 비활성화**하고 있습니다. 그러나 예상치 못한 요청이 수신될 때 graphql이 발생시키는 오류는 [**clairvoyance**](https://github.com/nikitastupin/clairvoyance)와 같은 도구가 스키마의 대부분을 재구성하는 데 충분합니다.
점점 더 많은 **graphql 엔드포인트가 introspection을 비활성화하고 있습니다**. 그러나 예상치 못한 요청이 수신될 때 graphql이 발생시키는 오류는 [**clairvoyance**](https://github.com/nikitastupin/clairvoyance)와 같은 도구가 스키마의 대부분을 재구성하는 데 충분합니다.
게다가, Burp Suite 확장 프로그램 [**GraphQuail**](https://github.com/forcesunseen/graphquail)은 **Burp를 통해 GraphQL API 요청을 관찰하고** **각 새로운 쿼리와 함께** 내부 GraphQL **스키마를 구축**합니다. 또한 GraphiQL 및 Voyager를 위한 스키마를 노출할 수 있습니다. 이 확장은 introspection 쿼리를 수신할 때 가짜 응답을 반환합니다. 결과적으로 GraphQuail은 API 내에서 사용할 수 있는 모든 쿼리, 인수 및 필드를 보여줍니다. 더 많은 정보는 [**여기서 확인하세요**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
멋진 **단어 목록**을 통해 [**GraphQL 엔티티를 발견할 수 있습니다**](https://github.com/Escape-Technologies/graphql-wordlist?).
멋진 **단어 목록**은 [**GraphQL 엔티티를 발견하는 데 사용할 수 있습니다**](https://github.com/Escape-Technologies/graphql-wordlist?).
### Bypassing GraphQL introspection defences <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a>
@ -397,7 +397,7 @@ ws.send(JSON.stringify(graphqlMsg))
```
### **노출된 GraphQL 구조 발견하기**
introspection이 비활성화된 경우, JavaScript 라이브러리에서 미리 로드된 쿼리를 찾기 위해 웹사이트의 소스 코드를 검사하는 것 유용한 전략입니다. 이러한 쿼리는 개발자 도구의 `Sources` 탭을 사용하여 찾을 수 있으며, API의 스키마에 대한 통찰력을 제공하고 잠재적으로 **노출된 민감한 쿼리**를 드러냅니다. 개발자 도구 내에서 검색하는 명령은 다음과 같습니다:
introspection이 비활성화된 경우, JavaScript 라이브러리에서 미리 로드된 쿼리를 찾기 위해 웹사이트의 소스 코드를 검사하는 것 유용한 전략입니다. 이러한 쿼리는 개발자 도구의 `Sources` 탭을 사용하여 찾을 수 있으며, API의 스키마에 대한 통찰력을 제공하고 잠재적으로 **노출된 민감한 쿼리**를 드러냅니다. 개발자 도구 내에서 검색하는 명령은 다음과 같습니다:
```javascript
Inspect/Sources/"Search all files"
file:* mutation
@ -429,7 +429,7 @@ query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
또한, [**XS-Search**](../../pentesting-web/xs-search/index.html) **공격**을 악용하여 사용자의 자격 증명을 이용해 GraphQL 엔드포인트에서 콘텐츠를 유출할 수 있습니다.
자세한 내용은 [**여기 원본 게시물 확인**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html)하십시오.
자세한 내용은 [**원본 게시물 확인**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html)하십시오.
## GraphQL에서의 교차 사이트 WebSocket 하이재킹
@ -443,7 +443,7 @@ GraphQL의 CRSF 취약점을 악용하는 것과 유사하게, **보호되지
## GraphQL에서의 권한 부여
엔드포인트에 정의된 많은 GraphQL 함수는 요청자의 인증만 확인하고 권한 부여는 확인하지 않을 수 있습니다.
엔드포인트에 정의된 많은 GraphQL 기능은 요청자의 인증만 확인하고 권한 부여는 확인하지 않을 수 있습니다.
쿼리 입력 변수를 수정하면 민감한 계정 세부 정보가 [유출](https://hackerone.com/reports/792927)될 수 있습니다.
@ -465,11 +465,11 @@ GraphQL의 CRSF 취약점을 악용하는 것과 유사하게, **보호되지
## GraphQL에서 별칭을 사용한 속도 제한 우회
GraphQL에서 별칭은 API 요청 시 **속성을 명시적으로 이름 지정**할 수 있는 강력한 기능입니다. 이 기능은 **단일 요청 내에서 동일한 유형**의 객체 여러 인스턴스를 검색하는 데 특히 유용합니다. 별칭은 GraphQL 객체가 동일한 이름을 가진 여러 속성을 가질 수 없도록 하는 제한을 극복하는 데 사용될 수 있습니다.
GraphQL에서 별칭은 API 요청 시 **속성을 명시적으로 이름 지정**할 수 있는 강력한 기능입니다. 이 기능은 **단일 요청 내에서 동일한 유형**의 객체 여러 인스턴스를 검색하는 데 특히 유용합니다. 별칭을 사용하면 GraphQL 객체가 동일한 이름의 여러 속성을 가질 수 없다는 제한을 극복할 수 있습니다.
GraphQL 별칭에 대한 자세한 이해를 위해 다음 리소스를 추천합니다: [Aliases](https://portswigger.net/web-security/graphql/what-is-graphql#aliases).
별칭의 주요 목적은 많은 API 호출의 필요성을 줄이는 것이지만, 별칭을 사용하여 GraphQL 엔드포인트에 대한 무차별 대입 공격을 실행할 수 있는 의도치 않은 사용 사례가 확인되었습니다. 이는 일부 엔드포인트가 **HTTP 요청 수**를 제한하여 무차별 대입 공격을 저지하기 위해 설계된 속도 제한기로 보호되기 때문입니다. 그러나 이러한 속도 제한기는 각 요청 내의 작업 수를 고려하지 않을 수 있습니다. 별칭을 사용하면 단일 HTTP 요청에 여러 쿼리를 포함할 수 있으므로 이러한 속도 제한 조치를 우회할 수 있습니다.
별칭의 주요 목적은 많은 API 호출의 필요성을 줄이는 것이지만, 별칭을 사용하여 GraphQL 엔드포인트에 대한 무차별 대입 공격을 실행할 수 있는 의도치 않은 사용 사례가 확인되었습니다. 이는 일부 엔드포인트가 **HTTP 요청 수**를 제한하여 무차별 대입 공격을 저지하기 위해 설계된 속도 제한기로 보호되기 때문입니다. 그러나 이러한 속도 제한기는 각 요청 내의 작업 수를 고려하지 않을 수 있습니다. 별칭을 사용하면 단일 HTTP 요청에 여러 쿼리를 포함할 수 있으므로 이러한 속도 제한 조치를 우회할 수 있습니다.
아래 제공된 예제를 고려해 보십시오. 이 예제는 별칭 쿼리를 사용하여 상점 할인 코드의 유효성을 확인하는 방법을 보여줍니다. 이 방법은 여러 쿼리를 하나의 HTTP 요청으로 컴파일하므로 속도 제한을 우회할 수 있으며, 동시에 여러 할인 코드를 확인할 수 있습니다.
```bash
@ -513,7 +513,7 @@ curl -X POST -H "User-Agent: graphql-cop/1.13" \
### **지시문 과부하 취약점**
**지시문 과부하**는 GraphQL 서버가 과도하게 중복된 지시문을 포함한 쿼리를 허용할 때 발생합니다. 이는 서버의 파서와 실행기를 압도할 수 있으며, 특히 서버가 동일한 지시문 로직을 반복적으로 처리할 경우 더욱 그렇습니다. 적절한 검증이나 제한이 없으면, 공격자는 수많은 중복 지시문을 포함한 쿼리를 작성하여 높은 계산 또는 메모리 사용을 유발하여 **서비스 거부(DoS)**를 초래할 수 있습니다.
**지시문 과부하**는 GraphQL 서버가 과도하고 중복된 지시문을 허용할 때 발생합니다. 이는 서버의 파서와 실행기를 압도할 수 있으며, 특히 서버가 동일한 지시문 로직을 반복적으로 처리할 경우 더욱 그렇습니다. 적절한 검증이나 제한이 없으면, 공격자는 수많은 중복 지시문으로 쿼리를 작성하여 높은 계산 또는 메모리 사용을 유발하여 **서비스 거부(DoS)**를 초래할 수 있습니다.
```bash
# Test provided by https://github.com/dolevf/graphql-cop
curl -X POST -H "User-Agent: graphql-cop/1.13" \
@ -535,7 +535,7 @@ curl -X POST \
-d '{"query": "{ __schema { directives { name locations args { name type { name kind ofType { name } } } } } }"}' \
'https://example.com/graphql'
```
그리고 **사용자 정의 항목 중 일부를 사용합니다.**
그리고 **사용자 정의** 항목 중 일부를 사용하십시오.
### **필드 중복 취약점**
@ -554,12 +554,16 @@ curl -X POST -H "User-Agent: graphql-cop/1.13" -H "Content-Type: application/jso
- [https://github.com/assetnote/batchql](https://github.com/assetnote/batchql): 배치 GraphQL 쿼리 및 변형 수행에 중점을 둔 GraphQL 보안 감사 스크립트.
- [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): 사용 중인 graphql 지문 인식
- [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): 스키마를 가져오고 민감한 데이터 검색, 권한 테스트, 스키마 무차별 대입 및 특정 유형에 대한 경로 찾기에 사용할 수 있는 도구 키트.
- [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): 독립형으로 사용하거나 [Burp 확장](https://github.com/doyensec/inql)으로 사용할 수 있습니다.
- [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): 독립형으로 사용하거나 [Burp extension](https://github.com/doyensec/inql)으로 사용할 수 있습니다.
- [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): CLI 클라이언트로도 사용 가능하며 공격 자동화: `python3 graphqlmap.py -u http://example.com/graphql --inject`
- [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): **GraphQL 스키마에서 특정 유형에 도달하는 다양한 방법을 나열하는 도구**.
- [https://github.com/doyensec/GQLSpection](https://github.com/doyensec/GQLSpection): InQL의 독립형 및 CLI 모드의 후계자
- [https://github.com/doyensec/inql](https://github.com/doyensec/inql): 고급 GraphQL 테스트를 위한 Burp 확장 또는 파이썬 스크립트. _**스캐너**_는 InQL v5.0의 핵심으로, GraphQL 엔드포인트 또는 로컬 introspection 스키마 파일을 분석할 수 있습니다. 모든 가능한 쿼리와 변형을 자동 생성하여 분석을 위한 구조화된 보기로 정리합니다. _**공격자**_ 구성 요소는 배치 GraphQL 공격을 실행할 수 있게 해주며, 이는 잘못 구현된 속도 제한을 우회하는 데 유용할 수 있습니다: `python3 inql.py -t http://example.com/graphql -o output.json`
- [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance): 일부 Graphql 데이터베이스의 도움을 받아 introspection이 비활성화된 상태에서도 스키마를 얻으려고 시도합니다. 이 데이터베이스는 변형 및 매개변수의 이름을 제안합니다.
- [https://github.com/doyensec/inql](https://github.com/doyensec/inql): 고급 GraphQL 테스트를 위한 Burp 확장 또는 파이썬 스크립트. _**Scanner**_는 InQL v5.0의 핵심으로, GraphQL 엔드포인트 또는 로컬 introspection 스키마 파일을 분석할 수 있습니다. 모든 가능한 쿼리와 변형을 자동 생성하여 분석을 위한 구조화된 보기로 정리합니다. _**Attacker**_ 구성 요소는 배치 GraphQL 공격을 실행할 수 있게 해주며, 이는 잘못 구현된 속도 제한을 우회하는 데 유용할 수 있습니다: `python3 inql.py -t http://example.com/graphql -o output.json`
- [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance): 일부 Graphql 데이터베이스의 도움을 받아 introspection이 비활성화된 경우에도 스키마를 얻으려고 시도합니다. 이 데이터베이스는 변형 및 매개변수의 이름을 제안합니다.
### 일반적인 취약점을 악용하기 위한 스크립트
- [https://github.com/reycotallo98/pentestScripts/tree/main/GraphQLDoS](https://github.com/reycotallo98/pentestScripts/tree/main/GraphQLDoS): 취약한 graphql 환경에서 서비스 거부 취약점을 악용하기 위한 스크립트 모음.
### 클라이언트
@ -574,7 +578,7 @@ https://graphql-dashboard.herokuapp.com/
- AutoGraphQL을 설명하는 비디오: [https://www.youtube.com/watch?v=JJmufWfVvyU](https://www.youtube.com/watch?v=JJmufWfVvyU)
## 참고자료
## 참고 문헌
- [**https://jondow.eu/practical-graphql-attack-vectors/**](https://jondow.eu/practical-graphql-attack-vectors/)
- [**https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696**](https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696)