views:

159

answers:

4

Hi! I have been tearing my hair with this one for a while.

index.php:

$(document).ready(function(){ 
    $(".index_login_subm").click(function(){
        uid = $("input:username").val();
        pwd = $("input:password").val();
        $.post("backend/login.php",{
            uid:uid,
            pwd:pwd
        },function(data){
            alert("Returned data: " + data);
         });
        return false;
    });
});

login.php:

include("../../settings.php");
echo $uid;
echo $_POST['uid'];

none of the echoes returns anything.

settings.php:

foreach ($_POST as $key => $value) { 
   $$key = mysql_real_escape_string($value);
}
foreach ($_GET as $key => $value) { 
   $$key = mysql_real_escape_string($value); 
}

The code works well if i comment the settings.php-include out (well, of course the echo $uid won't work), so it must be something the mysql_real_escape_string does. Anyone have any idea what I am doing wrong?

index.php also includes settings.php if that makes any difference.

EDIT: Posts below made me want to clarify; the paths are all correct. settings.php (and some other scripts) are all put outside of the root folder to make them inaccessible to a web user. They are working well when accessed by the scripts.

A: 

index.php obviously is located in root directory of website, but the script that you are calling is in "backend" catalog.

Try using include_once instead of include and use absolute paths, not relative.

Example:

<?php
    include_once($_SERVER['DOCUMENT_ROOT']."/settings.php"); //absolute path to file
    echo $uid;
    echo $_POST['uid'];
?>

Using absolute paths will make life easier for you if you move files around.

Silver Light
Yep, I have intentionally put the db-connection script etc outside of the (web-user) accessible root, but the scripts still fetch them as they should. The paths are all correct.
Mattis
+4  A: 

As described in the PHP manual, mysql_real_escape_string requires a real database connection established with mysql_connect (in the second parameter). If none exists, it tries to create one by simply calling mysql_connect(). If this does not work either, it returns false.

So, you would have to create a database connection first. But before you start doing this: note it is a really really bad idea to simply take every POST and GET variable and spit it into the global namespace.

Steffen Müller
You are correct that I have my database connection AFTER the mysql_real_escape_string, I will fix it and see if it solves the issue.Could you please point me to a better way to avoid SQL injection?
Mattis
Confirmed it, I had my mysql_connect after the mysql_real_escape_string. Moving it made it work. I will fix my bad injection code in the way @Tchalvak suggested it below.
Mattis
A much better way to avoid SQL injection is to use a quoting mechanism that prevents SQL injection in the moment you assemble your SQL statement. It works like:$sql = yourquotefunc("SELECT * FROM users WHERE login=?", $_POST["login"]);Simply roll your own function for this.
Steffen Müller
+3  A: 

First, I would avoid the variable variables, they're really not necessary in this context and they make for a moving target if you're not sure what keys are actually reaching that script, and they're bad practice due to the security issues that they create. Instead, I would put the escaped values within settings.php into an array. Then you can simply var_dump() the array after including settings.php, and see what was available.

function extract_requests(){
    $res = array();
    foreach ($_REQUEST as $key => $value) { 
        if($key){
            $res[$key] = $value;
        }
    }
    return $res;
}

Second, manually call login.php with the correct url string, exactly what you would want the javascript to call for, so that you can be sure that any behavioral problems aren't coming from the login.php script itself.

http://localhost/somewhere/login.php?uid=50

include("../../settings.php");
$input = extract_requests();
var_dump($input);
echo $input['uid'];
echo $_POST['uid'];

Finally, I would check your data that you are sending in post(). I'm not a javascript guru, but

uid:uid,
 pwd:pwd

looks like it would cause issues to me, so it'd be good to make sure that your data is being sent in the way that you expect.

$(document).ready(function(){ 
    $(".index_login_subm").click(function(){
        uid = $("input:username").val();
        pwd = $("input:password").val();
        var inputData = {uid:uid, pwd:pwd};
        alert(uid+" "+pwd);
        // If you have a console.log() available, just use it on inputData here instead.
        $.post("backend/login.php",inputData
         ,function(data){
            alert("Returned data: " + data);
         });
        return false;
    });
});

Edit: Based on the mysql_real_escape_string-only-when-a-connection-has-been-initiated thing, I've removed the escaping from the code above, because really, you'll be better off escaping the stuff right before you put it into the sql.

In addition, keep in mind that using javascript for the login WILL come back to bite you, with functionality as basic and necessary as login, you don't want a javascript error to break any ability for a viewer to log in. Here it will do so.

Tchalvak
Thank you for your comments on the escaped values, I will make sure to code it your way :) I agree that uid:uid etc looks like it could mess up, but it does work, I tried it before using it.
Mattis
Huge thanks for the code, I'll implement it right away.
Mattis
+1  A: 

Is there a valid mysql link?

string mysql_real_escape_string  ( string $unescaped_string
                                [, resource $link_identifier  ] )

If the link identifier is not specified, the last link opened by mysql_connect() is assumed. If no such link is found, it will try to create one as if mysql_connect() was called with no arguments. If no connection is found or established, an E_WARNING level error is generated.

May be your error reporting setting ignores E_WARNING level errors.

Amarghosh
You are correct, this was the problem. Putting the mysql_connect before the mysql_real_escape_string fixed it. I will make sure to code a better way to escape the SQL injection.
Mattis