tags:

views:

284

answers:

4

I was tasked with cleaning up some errors on a site my company built quite a few years ago. I want to preface the code I post here with the caveat that I didn't write it, and I know it is not a very secure login system, but I have only been assigned to fix the bug at hand.

PROBLEM: When users go to login, after they submit the form the page appears to be refreshed, requiring them to retype their credentials. No login error is being reported. I could only duplicate this problem in Firefox and Safari so far. After a successful login, if one were to log out and log back in, everything seems to work fine. It's just after you initially start the browser and attempt to login the first time. I have duplicated this on different Macs/Windows PCs as well.

Here is the basic login page HTML. I am trimming out anything unnecessary, but can provide more code if needed.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
...

<body>
            <form name="login" method="post" id="mainform" action="clogin.php">
                 <label for="username">Username:</label>
                 <input type="text" id="username" name="username"><br />
                 <label for="password">Password:</label>
                 <input type="password" id="password" name="password"><br />
                 <input type="submit" name="Submit" class="button" style="float:right;" value="Login">                
            </form>
</body>

Here is the PHP, also trimmed for fat:

<?php
$db = mysql_connect('***', '***', '***') or die("Couldn't connect to the database."); 
mysql_select_db('***') or die("Couldn't select the database"); 

$result = mysql_query("SELECT count(id) FROM merchants WHERE passw='$_POST[password]' AND usern='$_POST[username]'") or die("Couldn't query the user-database."); 
$num = mysql_result($result, 0); 

if (!$num) { 

// When the query didn't return anything, 
// display the login form. 

$message = "Login Failed: Incorrect username or password";

header('Location: login.php?message='.$message);


} else { 

// Start the login session 
session_start(); 


// All output text below this line will be displayed 
// to the users that are authenticated. Since no text 
// has been output yet, you could also use redirect 
// the user to the next page using the header() function. 
header('Location: merchants/index.php'); 
}

Does anyone have an idea at where I should start looking? My first thought is that maybe the form isn't actually fully submitting? How could I tell if that was happening? Any hints or pointers would be great. I personally can't find a "code" problem that could be causing this.

A: 

Get the Tamper Data add on for Firefox. It'll let you watch the form post and the response back from the server. There are other add ons that will do the same, or if you also need to see the same data in IE you can get Fiddler.

Chris Shaffer
These tools will definitely help I think. Of course, now that I have them, I am having trouble getting the error to show up again. It is still happening on a co-worker's computer, but not mine.
Mesidin
A: 

What if instead of selecting COUNT(id) you instead just selected * and replaced mysql_result for mysql_num_rows, do the errors still occur?

$result = mysql_query("SELECT * FROM merchants WHERE passw='$_POST[password]' AND usern='$_POST[username]'") or die("Couldn't query the user-database."); 
$num = mysql_num_rows($result); 

if ($num < 1) {
tj111
This seemed to have no effect.Honestly, it seems to me like the page is just refreshing, and it's not going to script at all. I am trying to duplicate the problem with the tamper firefox plugin to see if this is actually the case.
Mesidin
+1  A: 

Resisting the urge to shout 'SQL injection attack!!!!1111', as you say it does rather look like the form isn't submitted correctly. A couple of ideas:

Do you check in some way that the form has been submitted in the code before you query the database? If so, is this value definitely being posted?

I had this very issue in Firefox / Safari before, when I had a <button type="submit"> tag to submit the form without a value assigned to that button - IE (<8)was fine with this, but other browsers definitely weren't.

Put the following code in your submission page to see exactly what gets submitted:

die('<pre>'.print_r($_POST,true).'</pre>');
BrynJ
Heh. Now you know why I prefaced with my caveat. Unless it fixes the problem, I was specifically asked not to change any code, even with my protests of vulnerability. Gah! Drives me nuts as well just looking at it. It makes no sense.I will try that out and see what I can come up with!
Mesidin
A: 

Lets just go for a rewrite here and see how it works:

<?php
$db = mysql_connect('***', '***', '***') or die("Couldn't connect to the db."); 
mysql_select_db('***') or die("Couldn't select the db"); 

$result = mysql_query("SELECT id FROM merchants WHERE passw='%s' AND usern='%s'",
                      mysql_real_escape_string($_POST['username']),
                      mysql_real_escape_string($_POST['password'])) 
      or die("Couldn't query the user table."); 

if (mysql_num_rows($result) != 0) {
     $user = mysql_fetch_assoc($result);
     $userId = $user['id'];

     // Destroy any old session data from before for a fresh session
     session_destroy();
     session_start(); 

     header('Location: merchants/index.php'); 
     exit();
} else {
    $message = "Login Failed: Incorrect username or password";

    header('Location: login.php?message='.$message);
    exit();
}
?>

Give that a shot. Always good to throw an exit() in after you set the location in the header to make sure no more code executes.

While you're at it you might want to have the error message set in the session array and send it back that was as opposed to through the query string:

...
} else {
    $message = "Login Failed: Incorrect username or password";
    $_SESSION['login_error'] = $message;
    header('Location: login.php');
    exit();
}

Then just access $_SESSION['login_message'] on your login page to display any errors.

Id this doesn't get you working try some var_dump() on the $_POST array to see what is coming into your form.

Parrots