GraphQL Introspection 노출은 운영 환경에서 누구나 __schema 쿼리 한 번으로 전체 타입·필드·인자 목록을 받아갈 수 있는 결함이다.
REST 의 OPTIONS 응답이 "엔드포인트 몇 개"를 알려 준다면, GraphQL introspection 은 API 전체 지도, 숨겨진 admin 필드, 인자 형식까지 자동으로 알려 준다.
AI 도구가 짜 준 Apollo Server·Yoga·Hasura 코드는 기본값이 introspection ON 이라, 검토 없이 배포되면 그대로 새는 상태가 된다(출처: PortSwigger Web Security Academy "GraphQL", OWASP GraphQL Cheat Sheet).
한눈에 보는 GraphQL Introspection 노출
Q. Introspection 이 무엇인가요? A. GraphQL 의 표준 메타 쿼리(__schema, __type)로 서버의 전체 타입·필드·인자·deprecate 표시까지 받아 오는 기능입니다. GraphiQL/Apollo Studio 같은 개발 툴이 자동완성을 만드는 데 사용합니다.
Q. 노출돼도 인증으로 막으면 안전하지 않나요?
A. 스키마는 곧 공격 표면 지도입니다. 숨긴 줄 알았던 adminPanel·internalUser 같은 필드, deprecate 안 된 옛 인자, mutation 들이 그대로 노출되어 BFLA·Mass Assignment·IDOR 공격 시작점이 됩니다.
Q. AI 가 만든 GraphQL 서버에서 왜 자주 새나요?
A. Apollo Server·Yoga·Hasura·Postgraphile 모두 기본값이 introspection 활성화이며, AI 도구는 짧은 코드를 선호해 운영 분기 차단 로직을 빠뜨리는 일이 흔합니다.
Q. introspection 만 끄면 안전한가요?
A. 진입 단서는 줄지만 근본 차단은 아닙니다. depth limit · alias 폭주 · batch 쿼리 · 비용 제한도 같이 둬야 OWASP API Top 10 의 Unrestricted Resource Consumption 까지 막을 수 있습니다.
실제 공격 흐름 — 4단계
- 스키마 덤프:
POST /graphql에{ __schema { types { name fields { name args { name type { name } } } } } }전송 - 숨은 필드 식별:
adminUser·internalSettings·secretToken같은 필드 발견 - 권한 우회 시도: 일반 사용자 토큰으로 mutation 호출 → BFLA 결함 있으면 통과
- 2차 자원 고갈: alias 100개·depth 20 깊이 쿼리 1발로 DB 다운 유도
핵심: introspection 노출은 단독 결함이라기보다 "다른 결함 찾는 시간을 1시간에서 1분으로 줄여 주는 가속기" 다.
AI 가 만든 GraphQL 코드의 위험 패턴
| 서버 | AI 가 자주 짜는 코드 | 위험 |
|---|---|---|
| Apollo Server v4 | new ApolloServer({ schema }) 만으로 시작 | introspection·landingPage 운영에도 ON |
| GraphQL Yoga | createYoga({ schema }) | GraphiQL UI 가 운영에서 그대로 열림 |
| Hasura | HASURA_GRAPHQL_ADMIN_SECRET 만 설정 | 익명 역할에 introspection 허용 기본 |
| Postgraphile | 옵션 미설정 | 스키마 전체 + 워치 모드까지 노출 가능 |
| NestJS GraphQL | GraphQLModule.forRoot({ autoSchemaFile: true }) | playground·introspection 운영에 살아 있음 |
30초 자가 점검
# 1. introspection 살아 있는지 (3초)
curl -s -X POST https://your.app/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{ __schema { types { name } } }"}' | head -c 400
# 2. GraphiQL/Playground UI 노출
curl -I https://your.app/graphql
curl -I https://your.app/playground
# 3. 인증 없이 mutation 가능한지
curl -s -X POST https://your.app/graphql \
-H "Content-Type: application/json" \
-d '{"query":"mutation { __typename }"}'
위 1번에 타입 목록이 보이면 노출. 외부 노출 자산(.env·관리자 페이지·민감 파일·헤더 17종)은 CodeScan 30초 무료 스캔으로 동시에 점검.
서버 별 차단 코드 — 복사용
Apollo Server v4
import { ApolloServer } from "@apollo/server";
const server = new ApolloServer({
schema,
introspection: process.env.NODE_ENV !== "production",
// 운영에서는 landingPage 도 끔
plugins: process.env.NODE_ENV === "production"
? [require("@apollo/server/plugin/disabled").ApolloServerPluginLandingPageDisabled()]
: [],
});
GraphQL Yoga
import { createYoga } from "graphql-yoga";
const yoga = createYoga({
schema,
graphiql: process.env.NODE_ENV !== "production", // UI 차단
// 운영 환경에서 introspection 차단
plugins: [
{
onValidate({ params, setValidationFn, validateFn }) {
if (process.env.NODE_ENV === "production") {
// NoSchemaIntrospectionCustomRule 같은 룰 추가
}
},
},
],
});
Hasura
# config.yaml 또는 환경변수
HASURA_GRAPHQL_ENABLE_CONSOLE: "false" # 운영
HASURA_GRAPHQL_DEV_MODE: "false"
HASURA_GRAPHQL_ENABLED_APIS: "graphql" # metadata 등 차단
# 역할별 introspection 차단은 permissions 에서 명시
공통 — NoSchemaIntrospectionCustomRule
import { NoSchemaIntrospectionCustomRule } from "graphql";
// validationRules 옵션에 추가하면 운영에서 __schema 쿼리 거부
validationRules: process.env.NODE_ENV === "production"
? [NoSchemaIntrospectionCustomRule]
: [],
같이 막아야 할 GraphQL 자원 고갈 3종
| 공격 | 예시 | 차단 |
|---|---|---|
| Depth attack | user{posts{user{posts{user{...}}}}} 20단 | graphql-depth-limit 또는 query-complexity 도입(depth 7~10) |
| Alias overload | 같은 필드를 100개 alias 로 호출 | alias 카운트 제한 룰(graphql-no-alias) |
| Batch attack | 한 요청에 mutation 1000개 배치 | 요청당 operation 수 제한 + rate limit |
실제 사고·참고
- PortSwigger Web Security Academy "GraphQL" — introspection 노출에서 시작해 BOLA/BFLA 로 이어지는 표준 실험 코스(출처: portswigger.net/web-security/graphql).
- OWASP GraphQL Cheat Sheet — 운영 introspection 차단·depth/alias/batch 제한·인증 결합 권고.
- 2026 다수 HackerOne 디스클로저 — Apollo/Yoga 기본 설정 그대로 배포한 SaaS 에서 스키마 덤프 → BOLA·BFLA 로 이어진 보고가 매월 누적.
오늘 시작할 5가지 액션
- 위 자가 점검 1번 명령 1회 실행 → 타입 목록 보이면 즉시 차단 코드 적용
- 본인 스택 차단 코드 복사·배포 (운영 분기에서 introspection·UI·landingPage off)
- NoSchemaIntrospectionCustomRule + graphql-depth-limit + alias 제한 도입
- 관련 글: Mass Assignment 차단, CORS 사례, API 키 유출 점검
- 외부 노출은 CodeScan 30초 무료 스캔
CodeScan 이 잡아 주는 것
CodeScan 은 해킹대회 수상·레드팀 운영 경력의 보안 전문 기업 SENTRIX 가 운영하는 보안 점검 SaaS 다. GraphQL 엔드포인트의 introspection·UI 노출과 함께 .env·관리자 페이지·민감 파일·헤더 17종을 URL 한 줄로 자동 점검한다.
다음에 해야 할 한 가지
GraphQL 노출은 다른 결함을 빠르게 찾게 해 주는 가속기다. 운영에서 introspection 을 끄는 한 줄이 가장 빠른 1수다.
👉 실무자라면 본인 스택 차단 코드 1줄을 오늘 배포하고 CodeScan 30초 무료 스캔으로 외부 노출을 함께 끊어라.
👉 임원/CISO 라면 SENTRIX 30분 1:1 GraphQL 보안 진단으로 introspection·BOLA·BFLA·자원 고갈 4축 1회 점검을 권장한다.
{ "@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [ {"@type":"Question","name":"GraphQL Introspection 노출이 무엇인가요?","acceptedAnswer":{"@type":"Answer","text":"__schema·__type 메타 쿼리로 운영 서버의 전체 타입·필드·인자 지도를 누구나 받아갈 수 있는 결함입니다. REST 의 OPTIONS 보다 훨씬 자세한 공격 표면 정보를 줍니다."}}, {"@type":"Question","name":"인증으로 막으면 안전한가요?","acceptedAnswer":{"@type":"Answer","text":"안전하지 않습니다. 스키마 자체가 숨겨야 할 adminPanel·internalUser 같은 필드 존재를 공개하기 때문에 BFLA·Mass Assignment·IDOR 의 시작점이 됩니다."}}, {"@type":"Question","name":"AI 가 만든 GraphQL 서버가 왜 자주 새나요?","acceptedAnswer":{"@type":"Answer","text":"Apollo Server·Yoga·Hasura·Postgraphile 모두 기본값이 introspection 활성화이고, AI 도구는 짧은 코드를 선호해 운영 분기 차단 로직을 자주 빠뜨립니다."}}, {"@type":"Question","name":"introspection 만 끄면 충분한가요?","acceptedAnswer":{"@type":"Answer","text":"진입 단서는 줄지만 충분하지 않습니다. depth limit·alias 폭주·batch 쿼리·query complexity 도 같이 둬야 OWASP API Top 10 의 Unrestricted Resource Consumption 까지 막을 수 있습니다."}}, {"@type":"Question","name":"가장 빠른 1수는 무엇인가요?","acceptedAnswer":{"@type":"Answer","text":"운영 분기에서 introspection·GraphiQL UI·landingPage 를 비활성화하는 한 줄을 추가하는 것입니다. NoSchemaIntrospectionCustomRule 추가도 권장합니다."}} ] }