我使用此函数来阻止SQL注入
function cleanQuery($string)
{
if(get_magic_quotes_gpc()) // prevents duplicate backslashes
{
$string = stripslashes($string);
}
if (phpversion() >= '4.3.0')
{
$string = mysql_real_escape_string($string);
}
else
{
$string = mysql_escape_string($string);
}
return htmlentities($string);
}
我就这样使用它
$sql = "select * from news where id = ".cleanQuery($id)." ";
调用page.php?id = 1时查询应该是安全的 然而,当添加'到URL的末尾,如page.php?id = 1'时,它会给出错误
警告:mysql_fetch_object():提供的参数不是有效的MySQL结果资源
这意味着我认为页面仍然存在漏洞,任何机构都有解决方案吗?
答案 0 :(得分:4)
使用PDO准备好的声明。在参数化查询中的每个外部变量时,预处理语句具有防止所有形式的参数注入的良好属性。也就是说,请注意数据类型转换。
答案 1 :(得分:2)
对于整数使用(int)
$sql = 'select * from news where id = '.(int) $_GET[id];
答案 2 :(得分:1)
如果您的ID是数字,最简单的解决方案就是
$sql = "select * from news where id = '".intval($_GET['id'])."'";
答案 3 :(得分:1)
如果是id,只需使用is_numeric来验证:
if(ctype_digit($_GET['id'])){
$id = $_GET['id'];
} else {
$id = 1; // or whatever your default id is
}
或内联:
$sql = "select * from news where id = '".(ctype_digit($_GET['id']) ? $_GET['id'] : 1)."'";
答案 4 :(得分:1)
查询将中断,因为您的条件未包含在引号中。因此,只有数值可以工作。
要使其不中断,请在传递查询之前验证数字,或使用
$sql = "select * from news where id = '".cleanQuery($id)."' ";
顺便说一下,htmlentities()
是不必要的,可能对您的卫生功能有害。
答案 5 :(得分:1)
预处理语句始终是sql查询的方法。 php有一个名为mysqli的库。事实上,mysqli中的“i”代表“改进”,这说明很多:)
这是一个例子!首先,我在我的数据库中这样做了:
create database mydatabase default character set = UTF8;
use mydatabase;
create table news(id int auto_increment, title varchar(50), body text, primary key (id));
insert into news(title, body) values('good news','are good');
insert into news(title, body) values('old news','are old');
然后我使用这个php脚本(名为news.php)来访问我的表:
<?php
//my root user doesn't have a password, so third argument is empty string
$db = new mysqli("localhost", "root", "", "mydatabase");
if(mysqli_connect_errno()) {
die("unable to connect to database: " . mysqli_connect_error());
}
//change character set to utf8
if(!$db->set_charset("utf8")) {
die("Error loading character set utf8:\n{$mysqli->error}");
}
//the question marks denote parameters to be bound
$sql = "SELECT * FROM news WHERE id BETWEEN ? AND ?;";
$statement = $db->stmt_init();
$statement->prepare($sql);
$sqlError = $db->error;
if($sqlError != "") {
die("there was a problem with your query<br />\n$sql<br />\nerror reports:<br />\n$sqlError");
}
//the "i":s denote both parameters to bind are int
$statement->bind_param("ii", $min, $max);
$min = $_GET['min'];
$max = $_GET['max'];
$statement->execute();
$statement->store_result();
$statement->bind_result($id, $title, $body);
//everytime fetch is called, a new line is attempted to be read.
//if a line was read, two things happen:
//1. true is returned
//2. the values of the columns in the fetched result row is stored in the
// variables bound as results on the line above
while($statement->fetch()) {
print "$id, $title, $body";
}
$statement->free_result();
$statement->close();
$db->close();
?>
我这样称呼脚本:
http://localhost/news.php?min=1&max=2