HAKKShop
logic bugs + verb tampering?
We are presented with a PHP web application that has a custom database implementation DB.
Looking at register, we spot a bug in the way code is being processed.
//Register.php
// Checks if the code is a string and is set
if (isset($_REQUEST['username']) && isset($_REQUEST['password']) && isset($_REQUEST['code']) && is_string($_REQUEST['code'])) {
if (is_valid_invite($_POST['code'])) {
$username = $_POST['username'];
if (get_user_by_name($username)) {
show_error('Username already taken.');
} else {
add_tmp_perms(perms: 'users_add');
$user = create_user($username, $_POST['password']);
rm_tmp_perms('users_add');
if ($user) {
show_success('Account created successfully.');
header('Location: login.php');
} else {
show_error('Failed to create user.');
}
}
} else {
show_error('Invalid invite code.');
}
}
// Invites.php
function is_valid_invite($code) {
global $db;
$res = $db->select([
'SELECT' => '*',
'FROM' => 'invites',
'WHERE' => ['code' => $code],
]);
return count($res) === 1;
}Reading PHP's documentation, it states the following

This means we can set two code values, one in Cookie to satisfy the is_string check and one in $_POST data which is seen in the debugger.

We can use a payload like the following to then create a valid user. Since there is only one invite code from install.php, this returns one row, satisfying the

Now, we know that a admin user is created at the start via install.php. Looking at what our user can do, we see a interesting delete function in settings.php
Flow of the function
Check perms (Only for admin it seems)
if present - delete any user via
uid
Else If session
uid=== deleteuid(strict comparison)add temporary perms
add_tmp_permsdelete user
show success message
remove temporary perms
rm_tmp_perms
Something interesting is that we can directly pass the msg parameter into show_success which expects a string type.
This can cause a crash, allowing us to retain our delete_user privileges, assuming we do not follow the redirect to logout.php
We can thus formulate the exploit
Create two sessions, A and B
Use session A to do the following
pass in a errorneous type into
message, giving usdelete_userprivilegesdelete
adminuser by specifyinguid=1
Create a new user that will take the
uid=2using the bug aboveRun
install.phpto create the newadminuser asuid=2Use session B which still retains the uid of 2 to view the flag
Last updated