
graphi-qlIntrospectionSchema DumpingInsomnia의 Schema Documentation스키마 관계도스키마 정보 노출이 주는 의미백엔드는 블랙박스 영역스키마 정보를 열어둔다면?원데이 취약점을 찾는 원리Graphql InjectionFuzzing대응방안What’s Next?
graphi-ql
graphql
을 사용한 개발 시, 아래 그림과 같이 GraphiQL
과 같은 사이트를 활용하곤 한다.활용 이유는 쿼리, 뮤테이션 API 종류를 살펴보는 것 뿐만 아니라, 호출 시 필요한 인자와 리턴으로 받을 수 있는 값들에 대한 정보를 제공하기 위함이다.
프론트엔드 개발자는 해당 정보들을 토대로 필요한 값들만 선택하여 API를 구성하게 된다.

GraphiQL
과 같은 사이트는 개발 시점에 개발편의성을 위해 필요한 것으로, P
roduction
으로 배포 시에는 보안 목적으로 사이트를 제공하지 않도록 닫아야 한다.
GraphiQL을 Production에서 닫아야 하는 이유는 뭘까?
- 공개 API가 아니고서야, 외부 개발자에게 관련 정보들을 제공할 이유가 없다.
- 악의를 가진 사용자에겐 최대한 아무 정보도 제공하지 않아야 한다.
Introspection
graphiQL
접근을 차단하는 것으로 대응은 끝난 것일까?결론부터 말하면 Production으로 나갈 경우
Introspection
도 disable
해야한다.Introspection
설정이 켜져있다면, 그래서 __Schema
, __Type
, __Field
등을 포함해서 요청을 보낼 수 있다면 graphiQL을 닫지 않은 것과 동일하다.
Schema Dumping
실제로 schema dumping 이라는 단어를 사용하는 지는 모르겠다.
다만 사용 가능한 모든 스키마들을 수집하는 작업을 말하고 싶어서
Schema Dumping
이라고 부르겠다.Introspection
이 활성화 되어 있는 상태라면 아래와 같은 쿼리를 통해 Schema Dumping
이 가능하다.query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ...FullType } directives { name description locations args { ...InputValue } } } } 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 ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } } }

실제 Schema Dumping을 돌린 결과 10498줄의 방대한 양의 스키마 정보들이 수집되었다.
어떤 쿼리,뮤테이션이 있는지, 파라미터는 어떤 것들이 있고 타입은 어떻게 되는지, 리턴으로 받을 수 있는 값들의 종류와 각각의 타입은 어떻게 되는지에 대해 열려있는 모든 스키마 정보를 수집할 수 있었다.
Insomnia
의 Schema Documentation

Insomnia
의 graphql 탭에선 아예 graphiQL
과 동일한 뷰와 정보를 조회할 수 있도록 Schema Documentation
기능을 제공한다.스키마 관계도
위 사이트에 Introspection 결과를 붙여넣기 하면 관계도를 확인할 수 있다.


위 도식도는 어떤 정보들을 조회할 수 있는지, 또 내가 원하는 정보를 조회하기 위해 어떻게 쿼리를 구성시켜 나가야 하는 지에 대해 파악하기 좋은 자료가 된다.
스키마 정보 노출이 주는 의미
백엔드는 블랙박스 영역
백엔드는 클라이언트 사이드에서 뜯어볼 수 없다.
따라서 백엔드는
블랙박스
영역에 있으며, 정보 수집을 위해 반복 행위를 수행할 수밖에 없다.사소한 테이블명, 칼럼명 하나를 파악하기 위해서도 수많은 쿼리 요청과 반복 작업이 동반되어야 한다.
스키마 정보를 열어둔다면?
- 공격자에게 이러한 수고와 노력을 덜어주는 것과 같다.
- 이상행위의 반복을 모니터링하며 정보수집 시도에 대응할 수도 있는데, 이런 기회도 놓칠 수 있다.
원데이 취약점을 찾는 원리
스키마 정보는 한번 누출되고 나면 이후에 막는다고 하더라도, 공격자는 이미 이전에 누출된 데이터를 갖고 있을 것이며 여기서 크게 달라지지 않으므로 한번 누출된 것 자체로 불쾌하다.
원데이 취약점을 찾는 원리를 이해하면 이 불쾌감을 이해하는 데 도움이 된다.
제로데이 취약점
: 아무도 발견하지 못한 곳에서 새로운 취약점을 찾은 것
원데이 취약점
: 제로데이 취약점에 대한 패치가 나온 부분을 분석해서, 또 다른 취약점을 도출해 내는 것.- 패치가 적용되기 전의 정보와, 패치가 적용된 후의 바이너리를 디핑 뜬다.
- 이후 패치된 로직 내에서 취약점이 발생할 수 있는 부분들을 찾아서 분석하고,
- 기존 취약점에서 약간 공격방식이 변화된 또 다른 취약점을 찾아낸다.
물론 백엔드는 블랙박스이므로 로직을 디핑 떠볼 순 없지만, 스키마가 변경되었다면 변경 전, 변경 후의 스키마 형태를 보면서 어떤 식으로 공격할지 시나리오를 써볼 수 있는 정도로는 활용할 수 있다.
Graphql Injection
Graphql
환경에서 Injection
을 시도하는 것을 뜻한다.수집된 스키마 정보를 바탕으로
민감정보 탈취
, SQL Injection
, XXE
등의 취약점을 유발시키기 위한 쿼리, 뮤테이션을 쏘는 등의 공격을 시도한다.Fuzzing
위와 같은 공격 시도를 자동화 하여 취약점을 찾아나가는 방식을 뜻한다.
오펜시브 리서치 트렌드임.
Fuzzer
에 대한 연구가 활발히 이루어지고 있다.- 공개 퍼저 툴 예시 : WinAFL, AFL, Bff, Driller, manul + dharma 등등
- 퍼징 방식
- Dumb Fuzzing : 무작위, 무논리로 이상 데이터 만들어서 반복 테스트
- Smart Fuzzing : 정보를 기반으로 유효한 형식에서 조금씩 틀어가며 공격하는 방식
- Coverage Guided Fuzzing : 모든 커버리지를 채우도록 조건문을 뚫어가며 공격하는 방식. (비교적 기능이 잘 쓰이지 않아서 버그가 많이 제보되지 않은 부분에서 버그를 잘 터트린다. / 따라서 가성비가 좋다)

pentesting : 모의해킹
Graphql Injection
검색하면 GraphQLmap
이 검색되는데, 가장 위에 Dump a GraphQl schema가 있는 것을 볼 수 있다. 공격 시도 전에 선행되어야 하는 작업이기 때문이다.대응방안
핵심 대응방안은 간단한다.
- Production에선 Introspection을 disable 시킨다. (또는
role-based
로 관리한다) - 공격 시도 자체를 방어할 순 없지만, 최대한 필요한 정보들을 불편하게 얻도록 유도해야한다.
- 정보 수집을 위해 반복적인 이상 행위 쿼리 요청을 모니터링 하고 블락 시키는 등 방어체계를 구축하여 공격에 대응할 수 있다.
field fuzzing
을 어렵게 만들기- 에러 메세지를 통해 내부 정보를 획득할 수 없도록 해야한다.
- 겉으로 드러나는게 없다면 직접 정보를 찾아 나서야 하는데, 에러 메세지에서 주요정보를 제공할 경우 공격자의 비용을 훨씬 절감시킨다.
- 아래 그림 예시는 공격자의 field fuzzing 도중 서버 에러메세지가 field 명을 알려주는 예시다.
- 이건
suggestion
을disable
처리하여 해결할 수 있다.

What’s Next?
Production
외의 다른 개발 서버(Staging
,Development
등)의 서버 정보가 노출되지 않도록 프로덕트 코드를 철저하게 분리한다.- 기껏 Production에서 막아뒀는데, Staging이나 Development의 graphql url을 통해 schema dumping을 시도할 수 있기 때문이다.
특히 프론트엔드에서 dev, stg, prd 관련 정보를 한 프로덕트에 포함시켜서 빌드 배포하면 안된다.
- 클라이언트 사이드 프로덕트이기 때문에 모든 것을 뜯어볼 수 있다.
Staging
,Development
는 내부망에서만 접근할 수 있도록 망분리를 하는 것도 도움이 된다.
- 이상 트래픽 관련
모니터링/관제 시스템
을 구축한다. - 공격자가 획득 가능한 정보가 한정적이라면 정보획득/공격 목적의 fuzzing을 택할 수밖에 없고, 이는 이상 트래픽을 만들 수밖에 없다.
- 이상 트래픽 요청 @회 이상 요청 시 ip 차단 등의 정책으로 풀어낼 수 있다.