【问题标题】:Patching a time based sql injection [duplicate]修补基于时间的 sql 注入 [重复]
【发布时间】:2016-09-10 16:30:23
【问题描述】:

我最近对客户端进行了一次代码审计,发现这些代码行被盲注了

代码sn-p:

<?php
if ($_GET['id'] != ''){
$groepsindeling = $_GET['id'];
} else {
$groepsindeling = $_GET['group'];
}
breadcrumb($groepsindeling);
?>

<?php
$groep = "SELECT * FROM `menubalk` WHERE `webnr` LIKE '%$webnr-%' AND `hoofdgroep` = '$_GET[id]' ORDER BY `naamt1` ASC";
$groepres = mysql_query($groep);
while ($groeprij = mysql_fetch_array($groepres)){
?>

我立即使用 mysqli_real_escape_string() 函数对其进行了修补。

新代码:

<?php
if ($_GET['id'] != ''){

$groepsindeling = mysqli_real_escape_string($_GET['id']);

settype($groepsindeling, "integer");

} 
else {
$groepsindeling = mysqli_real_escape_string($_GET['group']);
}
breadcrumb($groepsindeling);
?>

<?php
$groep = "SELECT * FROM `menubalk` WHERE `webnr` LIKE '%$webnr-%' AND `hoofdgroep` = '$_GET[id]' ORDER BY `naamt1` ASC";
$groepres = mysql_query($groep);
while ($groeprij = mysql_fetch_array($groepres)){
?>

我做了进一步的测试,看看代码是否可以对抗基于布尔的盲 SQL 注入,但它似乎失败了,因为基于时间的盲 SQL 注入在这里仍然适用。

感谢所有建议。

【问题讨论】:

  • 您仍在查询中使用非转义的 $_GET['id']。
  • 1.您正在混合 mysql 和 mysli api。 2.你不应该再使用mysql api了。它在很久以前就被弃用了,并在 php v7 中被删除。 3. 对于所有类型的 sql 注入,简单的转义是不够的。要么使用参数化查询(在 mysql api 中不可用,仅在 mysqli 或 pdo 中可用),或者你必须加强转义代码。
  • @CapitalC 但是我还能在查询中使用这个函数吗?
  • @Shadow 一些客户不想更改他们的代码... ;(
  • @Shadow 是的,我知道 mysql api 已被弃用,但他们不想更改代码。所以这就是为什么我被困在这里..需要找到一种方法来修补这个而不需要大量更改代码。已经建议了 WAF(Web 应用程序防火墙),但他们当然拒绝了。

标签: php mysql sql security


【解决方案1】:

正如其他人指出的那样,您在查询中仍然有转义的$_GET['id'],但是严格来说,$groepsindeling 可能不等同于 get var。基本上你说的是这个

  $groepsindeling = $_GET['id']  or $_GET['group'];

在这里代表:

if ($_GET['id'] != ''){
    $groepsindeling = $_GET['id'];
} else {
    $groepsindeling = $_GET['group'];
}

这不是原始查询中表示的内容。

 "SELECT * FROM `menubalk` WHERE `webnr` LIKE '%$webnr-%' AND `hoofdgroep` = '$_GET[id]' ORDER BY `naamt1` ASC";

查询严格使用$_GET['id'],因为我在那里看不到$_GET['group']。那么这就剩下两个选择了,

  • 原代码有缺陷
  • 原代码是正确的(在这种情况下$Id应该是一个新变量)

就这样

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

 "SELECT * FROM `menubalk` WHERE `webnr` LIKE '%$webnr-%' AND `hoofdgroep` = '$id' ORDER BY `naamt1` ASC";

如果不查看此页面的完整代码,就无法判断 $groepsindeling 是否与查询相关或只是在其他地方使用。我提到的另一种可能性是它们是相同的,并且原始代码存在错误。

说了这么多,鉴于breadcrumb($groepsindeling);,我认为它与查询无关,并保持代码不变。更改它并在查询中包含 $_GET['group'] 值可能会导致不可预知的行为,特别是如果该查询依赖于 $_GET['id'] = '' 进行任何操作。

有道理。

附带说明一下,在当前的 PHP 版本中,来自原始查询的 $_GET[id] 可能会引发 undefined constant 警告,我已经在 5.3 之前的 PHP 代码中看到过它......它应该是 @987654335 @。它仍然有效,因为 PHP 会给一个未定义的常量其名称的字符串表示形式。 (只是一种告诉代码有多旧的方法:-p)

最后要注意的是,您将mysql_querymysqli_real_escape_string 一起使用,因此其中的i 有一些含义,或者在此mysql_query 中缺少它。 mysql_* 函数已被弃用,如果我记得自 PHP 7 起已删除,这意味着此代码在 PHP 5x 之后不再是未来的证明。我不确定mysql_real_escape_stringmysqli_real_escape_string 之间是否有任何显着差异

【讨论】:

    【解决方案2】:

    如上所述,您在查询中使用 $_GET['id'] 这意味着人们仍然可以 SQL 注入查询字符串:

    $groep = "SELECT * FROM `menubalk` WHERE `webnr` LIKE '%$webnr-%' AND `hoofdgroep` = '$_GET[id]' ORDER BY `naamt1` ASC";
    

    尝试做:

    $groep = "SELECT * FROM `menubalk` WHERE `webnr` LIKE '%$webnr-%' AND `hoofdgroep` = '{$groepsindeling}' ORDER BY `naamt1` ASC";
    

    然后你使用你使用 real_escape_string 的“$groepsindeling”变量。

    您还应该阅读http://php.net/manual/en/mysqli.real-escape-string.php - 正如它所说,当您使用“mysqli_real_escape_string”时,您还需要在方法中设置 MySQLi 对象:

    string mysqli_real_escape_string ( mysqli $link , string $escapestr )
    

    另外,你应该保留 MySQLi 或 MySQL(不推荐这个)。

    【讨论】:

    • 非常感谢,现在已经解决了!感谢您的帮助!
    • @epidrollic - 原始代码有缺陷,你意识到了吗?原始代码中的“$_GET['group'];”从未在查询中使用。通过更新您将其放入查询中,这可能是也可能不是最初的预期。换句话说,假设$groepsindeling = $_GET[id] 是不正确的。应该使用一个新变量。
    猜你喜欢
    • 2021-08-16
    • 1970-01-01
    • 1970-01-01
    • 2018-10-20
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    • 1970-01-01
    • 2020-08-25
    相关资源
    最近更新 更多