即使使用mysql_real_escape_string()函数,是否存在SQL注入的可能性?
考虑这个示例情况.SQL是用PHP构造的,如下所示:
$login = mysql_real_escape_string(GetFromPost('login'));
$password = mysql_real_escape_string(GetFromPost('password'));
$sql = "SELECT * FROM table WHERE login='$login' AND password='$password'";
Run Code Online (Sandbox Code Playgroud)
我听过很多人对我说,这样的代码仍然很危险,即使使用了mysql_real_escape_string()函数也可以破解.但我想不出任何可能的漏洞?
像这样的经典注射:
aaa' OR 1=1 --
Run Code Online (Sandbox Code Playgroud)
不工作.
你知道任何可能通过上面的PHP代码注入的注入吗?
我已经在Stack Overflow上重复了几次这个问题,但是没有一个能够充分探索这个问题(或者至少以一种对我有帮助的方式)
问题是数据库查询应该在PHP中为整数列返回整数数据类型.相反,查询将每列作为字符串类型返回.
我确保"PDO :: ATTR_STRINGIFY_FETCHES"为false,以确保结果不会被转换为字符串.
我见过的答案:
根据我的研究,我了解这是一个驱动程序实现问题.
许多消息来源声称MySQL本机驱动程序不支持返回数字类型.这似乎不正确,因为它适用于Mac OS X.除非他们的意思是" Linux上的MySQL本机驱动程序不支持该功能".
这意味着我在Mac OS X上安装的驱动程序/环境有一些特殊之处.我一直在尝试识别差异以便应用修复,但我受限于我对如何检查这些内容的了解.
php -i
PDO_MYSQL
用于MySQL的PDO驱动程序=>已启用客户端API版本=> 5.1.72
php -i
PDO_MYSQL
用于MySQL的PDO驱动程序=>启用客户端API版本=> mysqlnd 5.0.10 - 20111026 - $ Id:e707c415db32080b3752b232487a435ee0372157 $
PDO::ATTR_CASE => PDO::CASE_NATURAL,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS …Run Code Online (Sandbox Code Playgroud) 突然得到
SQLSTATE[HY000]:一般错误:1835 格式错误的通信数据包(SQL:select * from
tb_userswhere (username= 121211) limit 1)
在 Laravel 上。
我已经检查过这个:MySQL: ERROR 2027 (HY000): Malformed packet,但似乎是另一种情况。
但是我的 Laravel 出现了我之前提到的错误。有这方面的经验吗?
不久前开始使用PDO准备好的语句,据我所知,它可以为您完成所有的转义/安全性.
例如,假设$ _POST ['title']是一个表单字段.
$title = $_POST['title'];
$query = "insert into blog(userID, title) values (?, ?)"
$st = $sql->prepare($query);
$st->bindParam(1, $_SESSION['user']['userID'], PDO::PARAM_INT);
$st->bindParam(2, $title);
$st->execute();
Run Code Online (Sandbox Code Playgroud)
这真的很安全吗?我还要做别的吗?还有什么需要考虑的?
谢谢.
我正在尝试为我的数据库实现一个非常基本的搜索引擎,其中用户可能包含不同类型的信息.搜索本身由几个联合选择组成,其中结果总是合并为3列.
然而,返回的数据是从不同的表中获取的.
每个查询使用$ term进行匹配,我将它作为准备参数绑定到":term".
现在,手册说:
调用PDOStatement :: execute()时,必须为要传递给语句的每个值包含唯一的参数标记.您不能在预准备语句中两次使用同名的命名参数标记.
我想,不是用termex替换每个:term参数:termX(x为term = n ++),必须有一个更好的解决方案吗?
或者我只需绑定X号:termX?
编辑发布我的解决方案:
$query = "SELECT ... FROM table WHERE name LIKE :term OR number LIKE :term";
$term = "hello world";
$termX = 0;
$query = preg_replace_callback("/\:term/", function ($matches) use (&$termX) { $termX++; return $matches[0] . ($termX - 1); }, $query);
$pdo->prepare($query);
for ($i = 0; $i < $termX; $i++)
$pdo->bindValue(":term$i", "%$term%", PDO::PARAM_STR);
Run Code Online (Sandbox Code Playgroud)
好的,这是一个样本.我没有时间使用sqlfiddle,但如果有必要,我会稍后添加一个.
(
SELECT
t1.`name` AS resultText
FROM table1 AS t1
WHERE
t1.parent = :userID
AND …Run Code Online (Sandbox Code Playgroud) $sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%')
LIMIT :limit1, :limit2";
Run Code Online (Sandbox Code Playgroud)
我想仍然像这样使用数组输入:
$stmt->execute($array);
Run Code Online (Sandbox Code Playgroud)
否则我不能重复使用相同的方法来执行我的查询.
同时,:limit1和:limit2不起作用,除非它像这样输入:
$stmt->bindParam(':limit1', $limit1, PDO::PARAM_INT);
Run Code Online (Sandbox Code Playgroud)
我试图做两个但它不使用bindParams执行:
$stmt->bindParam(':limit2', $limit2, PDO::PARAM_INT);
$stmt->execute($array);
Run Code Online (Sandbox Code Playgroud)
它的方法是什么?
我以为我可以扩展PDOStatement并添加一个新方法"bindLimit"或其他东西,但我无法弄清楚PDO使用什么内部方法将参数绑定到变量.
在从旧mysql_*()函数迁移到新PDO类的过程中,我又遇到了一个问题:我有一个下表:
CREATE TABLE `test` (
`Id` tinyint(4) unsigned zerofill NOT NULL,
`UserName` varchar(4) NOT NULL,
`TestDecimal` decimal(6,0) unsigned zerofill DEFAULT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Run Code Online (Sandbox Code Playgroud)
注意zerofill'ed Id和TestDecimal字段.
如果我运行以下代码,使用旧mysql_*()函数:
$SqlQuery = "SELECT * FROM test";
$Sql_Result = mysql_query($SqlQuery);
var_dump(mysql_fetch_array($Sql_Result));
Run Code Online (Sandbox Code Playgroud)
我得到以下输出,正确的zerofilled Id列:
array (size=6)
0 => string '0001' (length=4)
'Id' => string '0001' (length=4)
1 => string 'alex' (length=4)
'UserName' => string 'alex' (length=4)
2 => string '000002' (length=6) …Run Code Online (Sandbox Code Playgroud) 请仔细阅读问题.这通常不是愚蠢的"我的代码不起作用!!!" 题.
当我使用预期的错误运行此代码时
try {
$sth = $dbh->prepare("SELECT id FROM users WHERE name INN(?,?) ");
$sth->execute(array("I'm","d'Artagnan"));
} catch (PDOException $e) {
echo $e->getMessage();
}
Run Code Online (Sandbox Code Playgroud)
我收到此错误消息
您的SQL语法中有错误...在第1行'INN('我'','d \'Artagnan')'附近
但我多年来一直认为查询和数据是分开发送给服务器的,而且绝不干涉.因此我有一些问题(虽然我怀疑有人得到答案......)
更新
mysqli 是按预期做的:它会抛出一个错误说 near 'INN(?,?)'
只是一个关于PDO的ATTR_EMULATE_PREPARES属性的简单问题 - 简单地说,当保持默认值(true)时,一切正常,花花公子.然而,禁用它,好吧,我甚至没有得到PHP错误消息,只是浏览器警告告诉我"连接已重置".
这里参考的是我正在使用的代码示例
<?php
include_once("config.php");
try {
$dbh = new PDO
(
"mysql:host=". DB_SERVER .";dbname=" . DB_NAME,
DB_USER,
DB_PASS,
array
(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => true
)
);
} catch(PDOException $e) {
echo "<pre>";
print_r("Error: " . $e);
echo "</pre>";
die();
}
$idNum = "1";
$sth = $dbh->prepare("SELECT * FROM `table` WHERE `id` = ?;");
$sth->bindParam(1,$idNum);
$sth->execute();
$res = $sth->fetch();
?>
<pre>
<?=print_r($res); ?>
</pre>
Run Code Online (Sandbox Code Playgroud)
从我可爱的测试表中很好地返回查询...
Array
(
[id] => 1
[field1] => q12w3e4r5t6y7u8i9
[field2] …Run Code Online (Sandbox Code Playgroud) 给出类似的东西
DB()->prepare("SELECT * FROM mysql.general_log WHERE user_host LIKE ?");
$statement->execute( array('%console%') );
foreach($statement as $record){
var_dump($record);
}
Run Code Online (Sandbox Code Playgroud)
general_log的内容是
*************************** 1. row ***************************
event_time: 2011-04-20 14:27:59
user_host: REDACTED[REDACTED] @ REDACTED [192.168.56.101]
thread_id: 30
server_id: 0
command_type: Connect
argument: REDACTED@REDACTED on REDACTED
*************************** 2. row ***************************
event_time: 2011-04-20 14:27:59
user_host: REDACTED[REDACTED] @ REDACTED [192.168.56.101]
thread_id: 30
server_id: 0
command_type: Query
argument: SELECT * FROM mysql.general_log WHERE user_host LIKE '%console%'
Run Code Online (Sandbox Code Playgroud)
我在一个令人厌恶的框架内工作(没有单元测试,没有文档,没有ryhme或原因)所以有可能在某个地方有人明确地禁用了MySQL准备语句,迫使PDO使用模拟模式......或者这是预期的行为?
PHP是PHP Version 5.2.10-2ubuntu6
MySQL的PDO驱动程序,客户端库版本5.1.41
更新:PDO()使用以下属性构造
PDO::ATTR_PERSISTENT => false
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION …Run Code Online (Sandbox Code Playgroud)