GraphQL Injection이란?
GraphQL Injection이란 GraphQL 쿼리가 담긴 요청을 조작하여 악의적인 요청을 보내는 기법입니다.
API와 GraphQL에 관한 설명은 다른 포스팅을 참고해 주세요 (API란? / GraphQL이란?)
아래의 사진과 같이 상품의 정보들을 불러오는 요청에 대한 응답으로 id값이 1, 2, 4인 상품만 반환될 경우 id값이 3인 상품이 숨겨져 있을 수 있다는 추측을 할 수 있습니다.
이러한 경우 인자 값으로 id값에 3을 포함시켜 요청해 주면 아래와 같이 비공개 정보를 불러올 수 있습니다.
또한 GraphQL에서 스키마에 대한 정보를 서버에서 쿼리할 수 있는 내장 GraphQL 함수를 통해 아래와 같이 GraphQL의 스키마 정보도 불러올 수 있습니다.
공격을 위해서는 GraphQL이 작동하는 엔드포인트에 접근해야 합니다. GraphQL는 단일 엔드포인트로 단 하나의 엔드포인트에서 API가 데이터에 접근하게 됩니다.
burp suite PortSwigger에서 제공되는 랩을 통해 GraphQL Injection 과정을 좀 더 자세히 설명하도록 하겠습니다.
GraphQL Injection 실습
Lab: Accessing private GraphQL posts
Lab: Accessing private GraphQL posts | Web Security Academy
The blog page for this lab contains a hidden blog post that has a secret password. To solve the lab, find the hidden blog post and enter the password. Learn ...
portswigger.net
위와 같이 블로그에 여러 글들이 표시되는 페이지입니다.
글을 불러오는 요청을 살펴보니 위와 같이 /graphql/v1 이라는 엔드포인트로 쿼리가 요청되고 있는 것을 확인할 수 있었습니다.
위에 대한 요청으로는 아래와 같은 응답이 가고 있었으며
해당 요청에서는 앞서 예시를 든 것처럼 id값이 3인 게시글이 나오지 않는다는 것을 알게 되었습니다.
처음에는 아래와 같이 인자값을 추가하여 요청을 보냈는데
응답으로 해당 인자값이 getAllBlogPosts에 정의되지 않았다는 에러가 반환되었습니다.
따라서 일단 쿼리에 대한 정보를 알기 위해 스키마 구조를 불러오는 내장 함수를 사용하여 스키마 구조를 반환받았습니다.
해당 요청이 긴 만큼 응답은 더욱 길게 반환되기 때문에 사진에 다 담지 못하였고 쿼리 구조가 심각히 길 경우 분석하기 어려운 경우가 많습니다. 따라서 저는 GRAPHQL VOYAGER를 통해 응답을 붙여 넣고, 해당 응답을 구성도로 만들어 확인해 보았습니다.
따라서 위와 같은 구성도를 통해 getBlogPost라는 쿼리로 요청할 수 있는 내용들을 알 수 있었습니다. 그중 flag 값이 담겨있을 것 같은 postPassword라는 내용이 있어 이를 쿼리에 담아 id 인자값을 3으로 설정 후 요청하였더니
숨겨진 비밀번호를 찾을 수 있었습니다.
해당 비밀번호를 통해 랩을 클리어할 수 있었습니다.
GraphQL Injection - CSRF
GraphQL Injection을 이용해 CSRF와 같은 공격도 진행할 수 있다는 것을 알게 되어 해당 실습도 진행해 보았습니다.
https://portswigger.net/web-security/graphql/lab-graphql-csrf-via-graphql-api
Lab: Performing CSRF exploits over GraphQL | Web Security Academy
The user management functions for this lab are powered by a GraphQL endpoint. The endpoint accepts requests with a content-type of x-www-form-urlencoded and ...
portswigger.net
문제에서 제공받은 계정으로 로그인을 하였더니
해당 계정의 이메일을 변경할 수 있는 페이지가 나왔고
이메일이 변경되는 것도 확인하였습니다.
이번에도 /graphql/v1 이라는 엔드포인트로 이메일 변경 요청이 가고 있었고 이는 mutation을 통해 기능하고 있었습니다.
뮤테이션(mutation)이란?
데이터를 추가, 삭제 또는 편집하는 등의 기능
위의 뮤테이션에 대한 응답은 아래와 같이 반환되고 있었고,
해당 요청을 조작하여 GraphQL Injection과 CSRF를 연계하여 공격해 볼 수 있겠다는 생각을 하였습니다.
일단, 요청을 CSRF PoC를 이용해 사용하기 위해 요청 콘텐츠 타입을 application/json에서
application/x-www-form-urlencoded로 바꾸어주고 body값도 변경해 주었습니다.
요청을 붙여 넣어 CSRF PoC FORM 코드를 반환받았고
해당 코드의 value에 특수문자가 포함되어 있기에 HTML 엔티티로 변환해 준 후 hacking@hacking.com로 변경하는 요청 폼을 localhost에 띄우고
Submit 버튼을 눌러주었더니
이메일이 변경된 것을 확인할 수 있었습니다.
대응방안
이러한 GraphQL Injection에 대한 대응 방안으로는 쿼리에 대한 입력값 검증, 프로덕션 환경에서는 introspection기능을 비활성화, 권한이 없는 데이터에 접근 제한, JSON 형식의 POST 요청만 허용(CSRF에 대한 대응) 등이 존재합니다.
이 외에도 중첩된 쿼리를 통해 DoS 공격을 할 수 있는데, 해당 대응 방안으로 쿼리의 깊이를 제한해 주는 방법이 나왔지만 이를 별칭으로 우회할 수 있습니다. 다양한 GraphQL Injection 방법은 추후 포스팅에서 다루도록 하겠습니다.
'Web > Web Hacking' 카테고리의 다른 글
SSTI (Server Side Template Injection) (4) | 2024.10.25 |
---|---|
CSTI (Client Side Template Injection) (0) | 2024.10.24 |
NoSQL Injection (0) | 2024.09.07 |
XXE External Entities (0) | 2024.09.06 |
File Download Vulnerability (0) | 2024.09.06 |