VaultSpace
Summary
We’ll use the app’s own public “function dispatcher” to call a state-changing helper that writes directly into $_SESSION. One request sets $_SESSION['admin']=true for our cookie, and then /dashboard.php shows the flag. No shell, no SQL, just an authorization check that trusts what the client can modify.
Start
The challenge ships a classic PHP stack with these relevant files:
api_handler.php— generic POST API gatewayfunctions.php— the functions that the gateway can calldashboard.php— admin-only page that renders the flag
Two observations frame the whole exploit:
A public dispatcher invokes server functions by name.
One exported function writes session auth based on caller input.
Dispatcher (Entry point)
No authentication sits in front of this entrypoint. Any POST is forwarded to
safe_call_function.Whatever we put in
$actiondetermines which server function runs. That’s huge power.
The “safety” check that isn’t authorization
The only gate is a regex on the name. That’s not a permission model.
If a sensitive routine starts with
set_, it passes and becomes remotely callable.call_user_func_array($fn, $params)uses ourparamsto build the function’s arguments, so we control both which function runs and what it receives.
Where the privilege flip actually happens
Whatever we put in
user_data['admin']becomes the session’s admin bit.No DB lookup, no signature, no role verification, just trust.
The admin check elsewhere simply reads that bit:
And the dashboard gates by it and renders the flag:
So if we can call set_user_session through the dispatcher and keep the same cookie, we’re in.
Steps for Exploitation
1- Get a session cookie
Open any page to establish a PHP session (keep the same cookie for the next requests).
2-Flip your session to admin via the dispatcher
Send a form-encoded POST that calls set_user_session with a single array argument. This shape makes PHP build params[0] as the $user_data array for call_user_func_array.
Under the hood:
The regex allows
set_user_session.call_user_func_array('set_user_session', [ {id, username, admin:1} ])runs.(bool)1becomestrue⇒$_SESSION['admin']=truefor your current cookie.
Then visit /dashboard and you should see the flag

Last updated