GraphQL 실습(5) - Performing CSRF exploits over GraphQL (PortSwigger Academy)
GraphQL endpoint의 CSRF 취약점을 이용해 피해자의 이메일을 변경하는 과정
Lab: Performing CSRF exploits over GraphQL
Lab Link: Performing CSRF exploits over GraphQL
핵심 포인트와 취약점 개념
이번 Lab은 GraphQL endpoint에서 발생하는 CSRF 취약점을 다루는 문제다.
핵심 포인트는 다음과 같다.
- GraphQL mutation 기반 사용자 이메일 변경 기능
application/x-www-form-urlencoded요청 허용- CSRF 토큰 미사용
최종 목표는 피해자의 이메일을 우리가 원하는 값으로 변경하는 것이다.
공격 흐름
1. 이메일 변경 요청 분석
주어진 계정 wiener:peter로 로그인한 뒤 이메일을 변경해보면,
Burp HTTP History에서 관련 endpoint가 노출되는 것을 확인할 수 있다.
이메일 변경 요청 (GraphQL mutation)
해당 mutation은 input으로 이메일 값을 받아 사용자의 이메일 주소를 변경하는 기능이다.
따라서 CSRF를 활용하면, 세션이 유효한 피해자의 브라우저를 통해 자동으로 요청을 전송하여
피해자의 이메일 주소를 우리가 원하는 값으로 변경할 수 있다.
2. CSRF 공격 가능 여부 확인
POST /graphql/v1 요청을 Repeater로 가져와 분석 해보자.
일반적인 CSRF 공격은 브라우저가 자동으로 생성할 수 있는 요청 형식에 의존한다.
따라서 application/json만 엄격하게 허용하는 경우에는 CSRF 공격이 훨씬 어려워진다.
반면 application/x-www-form-urlencoded는 HTML <form>으로 자연스럽게 전송할 수 있기 때문에
세션 쿠키 기반 인증을 사용하는 환경에서는 CSRF로 이어지기 쉽다.
기존 요청은 POST + application/json Content-Type을 사용하고 있다.
이 형태는 일반적인 HTML <form>으로 직접 전송할 수 없기 때문에,
브라우저에서 자동 전송 가능한 형태인지 확인하기 위해
application/x-www-form-urlencoded 형태로 변환해본다.
application/x-www-form-urlencoded적용 및 query와 variables를 JSON 형태가 아닌 HTML 형식으로 변경
이 형태로 전송했을 때도 정상적으로 이메일이 변경된다면,
해당 endpoint는 브라우저에서 전송 가능한 요청을 그대로 받아들이고 있다는 뜻이다.
결과는 성공적으로 이메일이 바뀐것을 확인할 수 있다.
이제 Burp에서 제공하는 Generate CSRF PoC 기능을 이용해 실제로 브라우저에서 재현 가능한지 다시 한번 확인해본다.
Engagement Tools → Generate CSRF PoC
Test in browser를 클릭한 뒤 생성된 테스트 URL을 브라우저에서 열어본다.
에러가 발생하며 “Invalid syntax with offending token ‘
EOF란?
<EOF>는 “End of File”을 의미한다.
GraphQL parser가 아직 더 읽어야 할 문법이 남아 있다고 판단했는데, 실제 전달된 값은 중간에서 끊겨버렸다는 뜻이다.
여기서는 application/x-www-form-urlencoded 형태로 요청을 보냈기 때문에
본문이 key=value&key=value 형식으로 안전하게 인코딩되어야 한다.
하지만 URL Encoding을 하지 않은 상태로 query를 넣으면,
():{}- 줄바꿈(
\n) - 공백
과 같은 문자들이 그대로 전달되면서 파라미터 파싱이 깨질 수 있다.
그 결과 GraphQL 서버는 query 전체를 받지 못하고, 중간에서 끝난 잘린 문장으로 해석하여
<EOF> 문법 에러를 반환하게 된다.
따라서 query=(내용)&variables=(내용) 형태로 각 값을 URL Encoding한 뒤 다시 전송했다.
URL Encoding된 요청
CSRF PoC 브라우저 테스트 결과
성공적으로 이메일을 def@gmail.com으로 변경한 것을 확인할 수 있었다.
My Account화면 - 이메일 변경된 내용 반영
즉, 이 <form> 기반 CSRF payload를 공격자의 서버에 업로드한 뒤 피해자가 해당 페이지를 방문하게 만들면,
유효한 세션 쿠키가 함께 전송되면서 이메일 변경 mutation이 피해자 권한으로 실행된다.
그 결과 피해자의 이메일 주소는 공격자가 지정한 값으로 변경된다.
3. Exploit 서버 업로드
Burp Suite의 CSRF PoC Generator를 통해 생성한 HTML 코드를 Exploit Server의 Body에 업로드한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<body>
<form action="https://0a9d001b03d61a68813a5c25006f0017.web-security-academy.net/graphql/v1" method="POST">
<input type="hidden" name="query" value="mutation changeEmail($input: ChangeEmailInput!) {         changeEmail(input: $input) {             email         }     }" />
<input type="hidden" name="variables" value="{"input":{"email":"ghi@gmail.com"}}" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>
이후 Deliver exploit to victim을 클릭하면,
피해자가 해당 페이지를 방문했다는 가정하에 CSRF가 실행되며 lab이 마무리된다.
정리
이번 Lab에서는 GraphQL endpoint에서 발생하는 CSRF 취약점에 대해 실습해볼 수 있었다.
해당 endpoint는 application/x-www-form-urlencoded 요청을 허용하고 있었고,
별도의 CSRF 토큰 검증도 존재하지 않았다. 또한 세션 기반 인증을 사용하고 있었기 때문에,
피해자의 브라우저가 자동으로 요청을 전송하면 정상 사용자 요청처럼 처리되었다.
결국 피해자의 의도와 무관하게 이메일 변경 mutation을 실행시킬 수 있었고,
이를 통해 피해자 계정의 이메일 까지 임의로 변경할 수 있었다.











