【问题标题】:PDO implementation, MySQL, SQL InjectionPDO 实现、MySQL、SQL 注入
【发布时间】:2013-02-27 03:15:03
【问题描述】:

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

到目前为止,一切都运行良好,但我刚刚进行了 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');
}
?>

【问题讨论】:

  • 不要尝试让你自己的 SQL 更干净,使用提供给你的那个。 mysql_real_escape_string.
  • 你试过的 PDO 代码是什么?
  • mysql_fetch_array 为您提供所有字段,您无需使用mysql_result
  • 感谢 Rocket 的提示,等我回到笔记本电脑上,我会尝试挖掘我以前的代码

标签: php sql pdo sql-injection


【解决方案1】:

这是您使用 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"] 等等。

【讨论】:

  • 给 OP 的说明:这里所有的 try..catch$stmt-&gt;errorInfo() 块都是无用的,使得代码无缘无故变得臃肿且没用。在实际项目中使用此代码时,将它们全部删除。
  • @YourCommonSense,发布您自己的答案,因为切线的设计问题而投票否决别人的答案是小气和粗鲁的。
  • 感谢您抽出宝贵的时间回答并对每个部分进行非常详细的解释,正是我需要的,当我带着笔记本电脑回来时我会尝试一下,希望我能理解它.抱歉,很遗憾,我无法对此投票,因为我需要 +15 声望才能这样做
【解决方案2】:
$result = mysql_query("SELECT * FROM Videos WHERE id='" . mysql_real_escape_string($_GET['id']) . "'");

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

【讨论】:

    猜你喜欢
    • 2017-08-24
    • 2015-08-20
    • 1970-01-01
    • 2018-01-19
    • 1970-01-01
    • 2013-04-18
    • 2012-08-04
    • 2011-06-26
    • 2013-12-02
    相关资源
    最近更新 更多