【问题标题】:Protecting SQL Insert Of CSV File From SQL Injection保护 CSV 文件的 SQL 插入免受 SQL 注入
【发布时间】:2016-05-31 08:05:46
【问题描述】:

我正在转换我的代码以保护它免受 SQL 注入。

目前我已经转换了我的大部分代码并使其正常工作,但我有两个查询让我有点困惑。我正在使用 php 文档here

示例 4 是我认为需要使用的情况。但我不明白这将如何在我准备好的陈述中获得我需要的价值。

我需要更改的第一条语句是,

require_once('Dbconfig.php');

$limit  = (intval($_GET['limit']) != 0) ? $_GET['limit'] : 5;
$offset = (intval($_GET['offset']) != 0) ? $_GET['offset'] : 0;

$sql = "SELECT * FROM wuno_inventory WHERE 1 ORDER BY id ASC LIMIT $limit OFFSET $offset";
try {
    $stmt = $DB_con->prepare($sql);
    $stmt->execute();
    $results = $stmt->fetchAll();
}
catch (Exception $ex) {
    echo $ex->getMessage();
}
if (count($results) > 0) {
    foreach ($results as $res) {
        echo '<tr class="invent">';
        echo '<td>' . $res['wuno_product'] . '</td>';
        echo '<td>' . $res['wuno_alternates'] . '</td>';
        echo '<td>' . $res['wuno_description'] . '</td>';
        echo '<td>' . $res['wuno_onhand'] . '</td>';
        echo '<td>' . $res['wuno_condition'] . '</td>';
        echo '</tr>';
    }
}
?>

我需要转换的第二个语句是,

<?php
require_once ('Dbconfig.php');

$limit = (intval($_GET['limit']) != 0 ) ? $_GET['limit'] : 5;
$offset = (intval($_GET['offset']) != 0 ) ? $_GET['offset'] : 0;

if(!empty($_POST["itemID"])) {
 $sql=" SELECT * FROM wuno_inventory WHERE wuno_product like '%". $_POST["itemID"] ."%' OR wuno_alternates like '%". $_POST["itemID"] ."%' ORDER BY wuno_product ASC LIMIT $limit OFFSET $offset ";
try {
  $stmt = $DB_con->prepare($sql);
  $stmt->execute();
  $results = $stmt->fetchAll();
} catch (Exception $ex) {
  echo $ex->getMessage();
}
if (count($results) > 0) {
  foreach ($results as $res) {
    echo '<tr class="invent">';  
    echo '<td>' . $res['wuno_product'] . '</td>';  
    echo '<td>' . $res['wuno_alternates'] . '</td>';  
    echo '<td>' . $res['wuno_description'] . '</td>';  
    echo '<td>' . $res['wuno_onhand'] . '</td>';  
    echo '<td>' . $res['wuno_condition'] . '</td>';  
    echo '</tr>';   
  }
}
}
?>

这是我尝试使用的示例,

<?php
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
if ($stmt->execute(array($_GET['name']))) {
  while ($row = $stmt->fetch()) {
    print_r($row);
  }
}
?>

我不明白在语句中添加? 的方式和原因。它真的告诉我我需要做的就是在我的两个列名所在的位置添加一个? 吗?请告诉我如何将这两个语句转换为准备好的语句以防止 sql 注入。

【问题讨论】:

标签: php mysql sql-server csv pdo


【解决方案1】:

准备好的语句库负责确保输入到列中的数据是“安全的”,从而防止 SQL 注入。

以下是在您的一个代码示例中如何使用占位符 (?) 作为准备好的语句:

if(!empty($_POST["itemID"])) {
 $sql=" SELECT * FROM wuno_inventory WHERE wuno_product like ? OR wuno_alternates like ? ORDER BY wuno_product ASC LIMIT $limit OFFSET $offset ";
try {
      $stmt = $DB_con->prepare($sql);
      $stmt->execute(array('%'.$_POST['itemID'].'%','%'.$_POST['itemID'].'%')); // two placeholders in the query means two items in the array
      $results = $stmt->fetchAll();
    } catch (Exception $ex) {
       echo $ex->getMessage();
    }
}

阅读更多Demystifying PDO

您必须将要在数组中绑定的所有值传递给PDOStatement-&gt;execute(),或者您必须使用PDOStatement-&gt;bindValue() 绑定每个值,然后不带参数调用PDOStatement-&gt;execute()。将数组(空或非空)传递给 execute() 将替换任何以前的绑定,并可能导致错误,例如使用 MySQL 时,如果您传递了一个空数组,则会出现错误“SQLSTATE[HY000]: General error: 2031” (CR_PARAMS_NOT_BOUND)。

【讨论】:

  • 因此,为了安全起见,与在语句中将prepared设置成这样,$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
  • 准备好的语句的基础是带有占位符的查询。为占位符发送参数时,安全性就来了。
  • 谢谢先生。因此,将来请确保我在查询中使用占位符。不要担心语句中是否使用了prepared这个词。这一切都基于在查询中使用占位符?
  • 正确。然后将查询参数绑定在数组中或使用其中一种绑定方法。
  • 除非解决了$limit$offset 的分配问题,否则此答案中的更改只能部分解决SQL 注入漏洞。第二个参数应该是intval($_GET(foo) 而不仅仅是$_GET(foo)
猜你喜欢
  • 2020-05-06
  • 1970-01-01
  • 2010-12-24
  • 1970-01-01
  • 1970-01-01
  • 2021-10-23
  • 2016-06-16
  • 1970-01-01
  • 2012-10-24
相关资源
最近更新 更多