我了解到使用预准备语句(参数化查询)可用于防止SQL注入攻击,但本文中提到的一些例外情况:PDO准备语句是否足以防止SQL注入?
我的问题是预准备语句如何防止SQL注入?到目前为止,我学到了什么:
- 使用参数化查询时,客户端将查询发送到服务器
进行准备(优化),没有任何数据,稍后,参数(用户输入或任何)将发送到服务器,以便用户数据驻留在原始查询之外。
使用预处理查询时,如果未转义用户数据,则不会阻止任何 SQL 注入。
出于这个原因,我未能测试该示例,因为使用 execute()
、bind_param()
、binVlaue()
、binParam()
在使用时都会转义数据,因此我们无法随它们发送未转义的数据来测试具有未转义参数的预准备语句的安全性。
基本问题是这样的:
$value = "Foo' OR 1 = 1 --";
$query = "SELECT id FROM users WHERE name = '$value'";
如上所述,这是实际查询:
SELECT id FROM users WHERE name = 'Foo' OR 1 = 1 --'
这里的问题是字符'
,它在字符串文本上下文中具有终止字符串文本的特殊含义。
解决此问题的一种方法是转义在字符串文本中具有特殊含义的字符:
SELECT id FROM users WHERE name = 'Foo'' OR 1 = 1 --'
另一种方法是将字符串文字完全分离出来,这样就不会混淆它的开始和结束位置:
query: SELECT id FROM users WHERE name = $1
$1: Foo' OR 1 = 1 --
前一种技术是转义,后者是参数化查询。您只需要使用其中之一。如果您转义了也参数化的值,则只会用不必要的反斜杠弄乱您的值。
注入意味着用户输入用作 SQL 语句的一部分。
如果使用预准备语句,则用户输入将被视为内容,而不是 SQL 命令的一部分。
但是,如果您通过将用户输入字符串连接在一起来构建 SQL 命令,则会再次引入 SQL 注入漏洞。
简而言之,使用准备好的查询是安全的,但用户输入应仅用作参数,而不是查询文本的一部分。
是的,你可以通过 pdo 和 mysqli 来防止 sql 注入
<<查看演示>>
使用 PDO:
步骤 - 1:连接数据库
在这里,我创建数据库"inphplab"。您可以根据需要进行更改。
$dbConnection = new PDO('mysql:dbname=inphplab;host=127.0.0.1;charset=utf8', 'root', '');
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
步骤 - 2:将数据插入表"员工"
在这里,我采用两个变量并声明名称和地址,如下所示。
$name = "bapuRocks";
$address = "India";
$stmt = $dbConnection->prepare("INSERT INTO employee ( name, address) VALUES ( :name, :address )");
$stmt->bindValue(':name', $name);
$stmt->bindValue(':address', $address);
printf("%s Row inserted.'n", $stmt->execute());
使用 MySQLi:
步骤 - 1:连接数据库
在这里,我创建数据库"inphplab"。您可以根据需要进行更改。
$mysqli = new mysqli('localhost', 'root', '', 'inphplab');
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s'n", mysqli_connect_error());
exit();
}
步骤 - 2:将数据插入/删除到表"员工"中
在这里,我采用两个变量并声明名称和地址,如下所示。
$stmt = $mysqli->prepare("INSERT INTO employee SET `name`=?,`address`=?");
$stmt->bind_param('ss', $name, $address);
$name = 'Yuvraj Sinh';
$address = 'India';
/* execute prepared statement */
$stmt->execute();
printf("%s Row inserted.'n", $stmt->affected_rows);
/* close statement and connection */
$stmt->close();
/* Clean up table CountryLanguage */
$mysqli->query("DELETE FROM employee WHERE name='Bharat Sinh'");
printf("%s Row deleted.'n", $mysqli->affected_rows);
/* close connection */
$mysqli->close();
防止SQL注入的最简单方法是使用简单的hex2str()
函数将所有用户输入转换为HEX,然后使用str2hex()
将其转换回来 - 这确保了所有数据都是安全的。
function strToHex($string){
$hex = '';
for ($i=0; $i<strlen($string); $i++){
$ord = ord($string[$i]);
$hexCode = dechex($ord);
$hex .= substr('0'.$hexCode, -2);
}
return strToUpper($hex);
}
function hexToStr($hex){
$string='';
for ($i=0; $i < strlen($hex)-1; $i+=2){
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
return $string;
}
编辑
$ID = strToHex($_GET["ID"]);
$COL1 = strToHex($_GET["COL1"]);
$COL2 = strToHex($_GET["COL2"]);
$query = "insert into my_db.my_table(ID, COL1, COL2) VALUES('$ID','$COL1','$COL2')";
就这么简单