PHP MySQL的漏洞

问题描述:

我使用此功能,以防止SQL注入PHP MySQL的漏洞

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); 
} 

我用它像

​​

查询应该是安全的调用page.php文件?ID等于1时 然而,当添加'像URL.php?id = 1的URL的末尾它会给出错误

警告:mysql_fetch_object():提供的参数不是有效的MySQL结果资源

这意味着页面仍然存在漏洞,我认为任何机构都有解决方案?

+2

没有这意味着SQL查询语句是无效的,说注意到对注入漏洞 – 2011-02-23 00:07:46

+0

该查询100%容易受到SQL注入,并通过这个代码来看,你没有一个线索是什么意思。 – rook 2011-02-23 22:44:56

+1

[Warning:mysql_fetch_array():提供的参数不是有效的MySQL结果](http:// stackoverflow。com/questions/795746/warning-mysql-fetch-array-supplied-argument-is-not-a-valid-mysql-result) – Fluffeh 2012-08-21 11:40:09

如果你的ID是数字,最简单的解决方案就是

$sql = "select * from news where id = '".intval($_GET['id'])."'"; 
+0

这样可以解决这个问题,但是现在它从mysql注入安全吗? – user629300 2011-02-23 00:12:08

+0

@ user629300,在这个特定的情况下 - 是的。用户/攻击者不能在查询中除了整数之外的任何东西,这就是你所期望的。 – Czechnology 2011-02-23 00:30:00

如果它是一个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)."'"; 
+1

更好的办法是使用[ctype_digit](http://php.net/manual/en/function.ctype-digit.php),这会阻止像10e3这样的有效数字。 – Dunhamzzz 2011-02-23 00:11:57

+0

好点。编辑。 – Emmanuel 2011-02-23 00:17:02

查询将因为您的条件未包含在引号中而中断。因此,只有数值可以工作。

为了使它不破,经过查询前验证号码,或者使用

$sql = "select * from news where id = '".cleanQuery($id)."' "; 

顺便说一句,htmlentities()是不必要的,可能有害于你的环卫功能。

对于整数使用(INT)

$sql = 'select * from news where id = '.(int) $_GET[id];

使用PDO的准备语句。准备好的语句具有在参数化查询中的每个外部变量时防止所有形式的参数注入的好处。也就是说,要小心数据类型转换。

+0

+1很棒的建议,特别是如果你不知道什么是sql注入。 – rook 2011-02-23 22:46:05

准备语句始终是有关sql查询的方式。 PHP有一个名为mysqli的库。事实上,“我”在mysqli代表“改进”说很多:)

这里是一个例子!首先,我这样做是为了我的数据库:

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