1

Authentication proceeds even if fields are blank or incorrect.

I'm using Kali Linux and everything is working, php is properly running.

<?php

$auth = 1;

$user1='14c4b06b824ec593239362517f538b29';       //username
$pass1='5f4dcc3b5aa765d61d8327deb882cf99';       //password

if($auth==1)
{
    if(!isset($_SERVER['PHP_AUTH_USER']))
    {
        if(md5($HTTP_SERVER_VARS['PHP_AUTH_USER'])!=$user1 || md5($HTTP_SERVER_VARS['PHP_AUTH_PW'])!=$pass1)
        {
            header("WWW-Authenticate: Basic");
            header("HTTP/1.0 401 Unauthorized");
            die("Unauthorized access!");
        }
    }
}

?>

If the input username=username & password=password then continue to load the page, else if not then retry

But what I am experiencing is that even when the input is blank or incorrect, it continues to load the page.

Desmon
  • 25
  • 5

2 Answers2

1

But what I am experiencing is that even when the input is blank or incorrect, it continues to load the page.

Because in this case $_SERVER['PHP_AUTH_USER'] is set!

That should fix your problem:

if($auth==1)
{
    if(md5($_SERVER['PHP_AUTH_USER'])!=$user1 ||
       md5($_SERVER['PHP_AUTH_PW'])!=$pass1)
    {
        header("WWW-Authenticate: Basic");
        header("HTTP/1.0 401 Unauthorized");
        die("Unauthorized access!");
    }
}

Old answer:

Something is fishy here.

On one line you are checking if $_SERVER['PHP_AUTH_USER'] is set, on another you are calculating md5 from $HTTP_SERVER_VARS['PHP_AUTH_USER'].

Note the difference.

Probably should be:

if(md5($_SERVER['PHP_AUTH_USER'])!=$user1 || md5($_SERVER['PHP_AUTH_PW'])!=$pass1)
Andrejs Cainikovs
  • 27,428
  • 2
  • 75
  • 95
  • Also, this might be of your interest: https://stackoverflow.com/a/14809899/147407 – Andrejs Cainikovs Aug 15 '19 at 09:17
  • $user1 is already an md5 hash also $pass1 what I want is that the authentication will prompt the user to input the username and password if the username inputed and then converted to md5 and it is equal to the $user1 and the password inputed when converted to md5 is also equal to $pass1 only then will the page continue loading, else if the converted username and password inputed by the user is not equal or is blank, then it will ask the user to retry or if the user hits the cancel or pressed the escape button, it will load the 401 unauthorized access. – Desmon Aug 15 '19 at 09:41
  • I clearly understand what are you trying to achieve. What I do not understand - why it's not working. My gut feeling tells me there are some details missing, and perhaps where exactly you are using this code excerpt. If you could provide *full, minimal, reproducible* scenario, that would help. – Andrejs Cainikovs Aug 15 '19 at 09:54
  • I haven't wrote any code for what I am going to use this. I have only written this authentication part but it's not working the way I want it to work. That's literally the only content of the php file I'm working. – Desmon Aug 15 '19 at 09:56
  • Perhaps you have a different code which could provide the process I am trying to achieve? I only copied that from the official documentation page of php and just adjusted it that way since I want it to convert the input username and password into md5 and if the converted hash is equal to $user1 & $pass1, it will continue to load the page, else it will ask to retry. – Desmon Aug 15 '19 at 09:59
  • @suspectus was right. That's the `isset` issue, which is set even if the password is wrong, and then all checks are bypassed. – Andrejs Cainikovs Aug 15 '19 at 10:16
  • Please note, debugging this kind of authentication might be a bit tricky if you are dealing with it for the first time. You might need to unset username/password on the server side in one way or another. One option would be to create a dedicated `logoff.php` script, for example. Otherwise, if username/password are set, they are persistent, and you will not be able to test entire authentication flow. – Andrejs Cainikovs Aug 15 '19 at 10:18
0

I would like to add to the existing answer that you should not compare secrets (such as passwords) using the equality operator due to timing attacks. PHP has a function specifically designed to avoid this: hash_equals()

if ($auth == 1) {
    if (!hash_equals(md5($_SERVER['PHP_AUTH_USER']), $user1) || !hash_equals(md5($_SERVER['PHP_AUTH_PW']), $pass1)) {
        header("WWW-Authenticate: Basic");
        header("HTTP/1.0 401 Unauthorized");
        die("Unauthorized access!");
    }
}

I would also advise against MD5 as it's quite a weak algorithm that is not sufficient for passwords. Using a free online tool it is ridiculusly easy to "reverse" those hashes using lookup (rainbow) tables that contain a large number of hashes and their plain text equivalents, which can be queried within seconds.

Free Password Hash Cracker Enter up to 20 non-salted hashes, one per line: 14c4b06b824ec593239362517f538b29 5f4dcc3b5aa765d61d8327deb882cf99 Supports: LM, NTLM, md2, md4, md5, md5(md5_hex), md5-half, sha1, sha224, sha256, sha384, sha512, ripeMD160, whirlpool, MySQL 4.1+ (sha1(sha1_bin)), QubesV3.1BackupDefaults Hash   Type    Result 14c4b06b824ec593239362517f538b29 md5 username 5f4dcc3b5aa765d61d8327deb882cf99   md5 password Color Codes: Green: Exact match, Yellow: Partial match, Red: Not found.

Should you chose to improve the security of your script I would suggest taking a look at password_hash and it's pair password_verify() which is timing attack safe.

You could make a standalone script that generates the hashes for you:

<form method="POST">
  <input name="data[Username]" placeholder="Username">
  <input name="data[Password]" placeholder="Password">
  <input type="submit">
</form>
<?php
if (!empty($_POST['data']) && is_array($_POST['data'])){
  $hashes = array_map(function ($value) {
    return password_hash($value, PASSWORD_DEFAULT);
  }, $_POST['data']);
  echo '<p>Your hashes:</p><pre>';
  print_r($hashes);
  echo '</pre>';
}

This will give you two inputs that you can enter your desired values into and it will output hashes when you submit the form. These hashes are non-reversible, similar to MD5, but they are much less prone to the lookup attack demonstrated above.

Input username Input password Submit button Your hashes: Array ( [Username] => $2y$10$5dt0CX73JcgLfAbrMAuFdeboEl5SQzkFDf9Uqwr/5I7OQaJdNiUl2 [Password] => $2y$10$E/fhcug/XuA0bQ5SVJXFS.b9nxeLpPM5r.hgCHcyVXx/4P6/u4QSO )

You may notice that even when hitting refresh in your browser the values won't be the same each time. This is due to salting which further increases the resilience of any hashing algorithm by making sure you can't just take the hash and compare it against a table of known hashes with their plain text equivalents. Use the values you get in place of the MD5 hashes of your script, and replace the verification code with the following:

if ($auth == 1) {
    if (!password_verify($_SERVER['PHP_AUTH_USER'], $user1) || !password_verify($_SERVER['PHP_AUTH_PW'], $pass1)) {
        header("WWW-Authenticate: Basic");
        header("HTTP/1.0 401 Unauthorized");
        die("Unauthorized access!");
    }
}
SeinopSys
  • 8,787
  • 10
  • 62
  • 110
  • Thanks for the advice man! I learned a lot, I'll look that up and study the algorithm. Thanks! – Desmon Aug 23 '19 at 02:34