PHP MySQL漏洞

时间:2011-02-23 00:05:21

标签: php mysql security

我使用此函数来阻止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结果资源

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

6 个答案:

答案 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