通过PDO和mysql从潜在的不安全输入创建新数据库

时间:2012-06-16 23:08:48

标签: php mysql pdo prepared-statement

我正在努力自动部署我编写的软件,并且需要能够为新帐户生成新的mysql数据库。但是,在消毒输入方面我很担心。

我正在使用PDO;但是,显然你不能使用'CREATE DATABASE'的预准备语句。所以,我也尝试过使用PDO :: quote;然而,然后我新创建的数据库名称被单引号包围(不是世界末日,但我仍然希望避免这种情况)。

有没有办法让它与预处理语句一起使用?如果没有,我可以做些什么来尽可能地保护自己免受sql注入攻击?我唯一的另一个想法是允许使用小白名单。

谢谢!

1 个答案:

答案 0 :(得分:2)

您需要编写一个stored procedure,然后您可以传递已清理的输入 (要使用我的示例,您需要更改一些变量,如数据库名称和正确的用户以及传递等等,以使其在您的数据库上运行)

示例:

<?php
$dsn = 'mysql:dbname=scratch;host=127.0.0.1';
$user = 'root';
$password = '';

try {
    $dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

$dbname = 'brand_new_db';

$statement = $dbh->prepare("CALL dbcreator(:db)");
$statement->bindParam(':db',$dbname);

if(!$statement->execute()){
    print_r($statement->errorInfo());
}
else {
    foreach( $dbh->query('SHOW DATABASES')->fetchAll() as $row){
        print "$row[0]" . PHP_EOL;
    }
}

存储过程:

DELIMITER $$

DROP PROCEDURE IF EXISTS `scratch`.`dbcreator` $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `dbcreator`(IN dbname VARCHAR(64))
BEGIN

SET @db = dbname;
SET @statement = CONCAT('CREATE DATABASE ',@db);
PREPARE prepared_statement FROM @statement;
EXECUTE prepared_statement;

END $$

DELIMITER ;

您创建一个PREPARE的SQL语句,在我们的案例CREATE DATABASE <our database>;中,因为CREATE DATABASE语句不能用于变量,然后您只需EXECUTE它。最后,执行CALL dbcreator('<dbname>')来执行存储过程。这是CALL dbcreator(:dbname),您可以使用并将params绑定到。

正如您所看到的,通过这种方式,您仍然可以在创建数据库时通过pdo安全地绑定params。使用一些简短的固定字符串为您创建的所有数据库添加前缀,以便于查找和区分,这可能不是一个坏主意。在存储过程中,dbname是limited to 64 characters,因为那是mysql的当前限制