这个PHP代码到底是什么问题?

时间:2012-03-13 18:22:52

标签: php mysql sql

我正在尝试PHP和MySQL,但现在我找到了一个我想要使用的PHP代码,但它很容易被SQL注入。有谁知道注射是什么以及什么代码可以修复它?

    <?
        // both the username and password must be specified
        if(!isset($_GET["username"]) || !isset($_GET["password"])) {
                print "NO username and/or password";
                die;
        }
        $username = $_GET["username"];
        $password = $_GET["password"];

        // prepare database connection
        mysql_connect("host", "user", "password");
        mysql_select_db("dbase");

        // validate the specified username
        $res = mysql_query("SELECT id FROM users WHERE username = '$username'");

        if(!$res || !($row = mysql_fetch_row($res))) {
                print "Unknown username";
                die;
        }
        // validate the password
        $res = mysql_query("SELECT password FROM users WHERE id = ".$row[0]);
        if(!$res || !($row = mysql_fetch_row($res))) {
                print "Illegal userid record";
                die;
        }
        if($password != $row[0]) {
                print "Invalid password";
                die;
        }
        // Access Granted
?>

代码是额外代码的一部分,但是没有必要,可以使用/somecode.php?username='OD'1'='1&amp; password = something'选择用户名但是'或者不使用密码,任何人都可以帮助我吗?

此致

3 个答案:

答案 0 :(得分:2)

不要动态构建SQL代码 - 将用户输入作为参数传递。

请参阅PHP文档中的this example

如果您像这样动态构建SQL:

$res = mysql_query("SELECT id FROM users WHERE username = '$username'");

其中$username可能包含由用户直接提供的内容,那么您就有风险。使用诸如预准备语句之类的解决方案,用户无法直接影响正在执行的SQL查询,这是一种更安全的替代方案。

答案 1 :(得分:1)

问题在于这一行:

    // validate the specified username
    $res = mysql_query("SELECT id FROM users WHERE username = '$username'");

由于$ username直接来自用户,因此有人可以传递test' OR id='1的用户名,这将产生以下sql:

SELECT id FROM users WHERE username ='test'或id ='1';

攻击者现在已经成为id为1的用户。糟糕!

您需要使用$_GET['username']或类似的内容转义addslashes()变量。

答案 2 :(得分:1)

该代码存在几个问题:

  • 您使用的是过时的API。您应该将PDO预备语句一起使用而不是古老的mysql_函数。
  • 等待发生SQL注入

相反,您的代码看起来应该是这样的:

$connection = new PDO('mysql:dbname=dbase;host=127.0.0.1', 'user' , 'password' );
$connection->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

$stmt = $connection->prepare('SELECT id FROM users WHERE username = :user');
$stmt->bindParam( ':user', $_POST['username'], PDO::PARAM_STR, 128);

if ( $stmt->execute() )
{
    var_dump( $stmt->fetchAll(PDO::FETCH_ASSOC ));
}

补充阅读: