1

我一直在为一个视频网站做一个项目。它从数据库中提取信息并在需要的地方插入详细信息。

到目前为止一切都运行良好,但我刚刚进行了 SQL 注入测试,一切都完全开放。我一直在寻找答案以关闭它并使事情更加安全。

我试图实现 PDO 语句,但我无法理解它。这个月我只在研究 php/sql,所以我非常新。

任何帮助或其他解决方案都会很棒,下面的代码是我的页面的主要连接点,我认为这也是最脆弱的部分

<?php
$username="********"; 
$password="*******";
$database="*******";

$id = $_GET['id']; 
$badchars = array("\"", "\\", "/", "*", "'", "=", "-", "#", ";", "<", ">", "+", "%");
$myid = str_replace($badchars, "", $id); 
mysql_connect('localhost',$username,$password);
@mysql_select_db($database) or die( "Unable to select database");
$result = mysql_query("SELECT * FROM Videos WHERE id='$id'");
while($row = mysql_fetch_array($result)) {
    $title=mysql_result($result,0,"title");
    $url=mysql_result($result,0,"url");
    $id=mysql_result($result,0,"id");
    $description=mysql_result($result,0,"description");
    $source=mysql_result($result,0,"source");
    $type=mysql_result($result,0,'type');
}
?>
4

2 回答 2

2

这是您重写为使用 PDO 的示例,并附有解释。

<?php
$username="********"; 
$password="*******";
$database="*******";

try {
  $pdo = new PDO("mysql:host=localhost;dbname=$database", $username, $password);
} catch (PDOException $e) {
  error_log("PDO connection error: " . $e->getMessage());
  header("Location: http://www.example.com/error.php");
  exit;
}

您可以将 GET 参数强制转换为 int,它将只使用数字部分并去掉其他任何内容。

$id = (int) $_GET['id']; 

在要替换动态值的查询中保留一个占位符。您可以将位置参数与?符号一起使用,也可以将命名参数与冒号前缀语法一起使用。

$sql = "SELECT * FROM Videos WHERE id = :id";

每次调用prepare() 或execute() 后测试错误很重要。

最好不要简单地出现错误die(),让浏览器出现白屏,但如果可能的话它们应该恢复,或者至少显示一个友好的“哎呀!” 页面,以便用户可以继续使用您的网站。

$stmt = $pdo->prepare($sql);
if ($stmt === false) {
  $err = $pdo->errorInfo();
  error_log("PDO prepare error: " . $err[2]);
  header("Location: http://www.example.com/error.php");
  exit;
}

传递参数值数组以替换为 execute() 的参数。在命名参数的情况下,它是一个关联数组。在位置参数的情况下,使用简单的序数数组。

if ($stmt->execute(array(":id"=>$id)) === false) {
  $err = $stmt->errorInfo();
  error_log("PDO execute error: " . $err[2]);
  header("Location: http://www.example.com/error.php");
  exit;
}

然后,您可以从语句的结果集中每行获取一个关联数组:

while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
  extract($row);
}

注意我展示了extract()的使用,这是一个 PHP 内置函数,它根据关联数组 $row 的键创建变量 $title、$url 等。但我这样做只是为了匹配您的代码;通常我只会引用这些字段$row["title"],依此类推。

于 2013-03-11T20:31:43.740 回答
-1
$result = mysql_query("SELECT * FROM Videos WHERE id='" . mysql_real_escape_string($_GET['id']) . "'");

...您可能还想考虑使用mysql_fetch_assoc () 而不是 mysql_fetch_array() ,这将大大简化结果值。根本不需要那些对 mysql_result() 的调用。

于 2013-03-11T19:45:58.307 回答