【问题标题】:Convert normal SQL statements to prepared statements将普通 SQL 语句转换为预处理语句
【发布时间】:2016-02-03 12:55:31
【问题描述】:

我正在使用 PHP 7,MySQL。我已经为我的项目编码很长时间了,现在它有数千个 MySQL 查询。那时我不知道准备好的陈述。

现在,为了避免 SQL 注入,我想使用准备好的语句,但是我很难将它们一一转换为准备好的语句。

有什么方法可以解析普通语句并使用 PHP 自动将其转换为准备好的语句?对于每个 MySQL 查询,我将其传递给 PHP 函数,然后再传递给 MySQL 命令。

public function dbquery($query,$dbname,$dbclose="-1")
{   
        $this->mysqli->select_db($dbname);
        $GLOBALS["dbr_total"]++;$GLOBALS["dbr_query"]++;
        $colarr=Array();$tares=Array();
    if ($result = $this->mysqli->query($query))
    {
        $GLOBALS["dbretry"]=0;
        $finfo = $result->fetch_fields();
        $c=0;
        foreach ($finfo as $val)
        {
            $colarr[$c]=$val->name;//get all colum names in this array
            $c++;
        }
        $co=0;
        while($obj = $result->fetch_object())
        {
            for($k=0;$k<count($colarr);$k++)
            {
                $elem=$colarr[$k];
                $tares[$co][$elem]=$obj->{$colarr[$k]};
            }
            $co++;
        }
        if($co==0)
        {
            $GLOBALS["dbretry"]=0;
            if($dbclose!="-1"){$this->dbclose();}
            return EMPTY_RESULT;
        }
    }
    else
    {
        if($GLOBALS["dbretry"]>3)
        {
            $GLOBALS["dbretry"]=0;
            $errmsg=$this->mysqli->error;
            $errno=$this->mysqli->errno;
            if($dbclose!="-1"){$this->dbclose();}
            $errobj=new ta_errorhandle();
            $errobj->senderror("OOPS! Could Not process your query!".$errmsg,$errno,"1");
        }
        else
        {
            $GLOBALS["dbretry"]++;
            $this->dbquery($query,$dbname);
        }
    }
        //QUERY DONE
        if($dbclose!="-1"){$this->dbclose();$result->close();}
        unset($obj);unset($finfo);unset($query);unset($result);unset($colarr);unset($c);unset($co);
        return $tares;
}




public function dbinsert($query,$dbname,$dbclose="-1")
{   
    $this->mysqli->select_db($dbname);
    $GLOBALS["dbr_total"]++;;$GLOBALS["dbr_insert"]++;
    if (!$this->mysqli->query($query))
    {
        $errmsg=$this->mysqli->error;
        $errno=$this->mysqli->errno;

        die("<br><br>".$errmsg."<br><br>".$errno);

        if($GLOBALS["dbretry"]>3)
        {
            $GLOBALS["dbretry"]=0;
            $logobj=new ta_logs();
            $logobj->store_templogs("PROBLEM EXECUTING QUERY:".$query." ON ".$dbname);
            return $this->mysqli;
        }
        else
        {
            $GLOBALS["dbretry"]++;
            $this->dbinsert($query,$dbname);
        }
    }
    else
    {
        $GLOBALS["dbretry"]=0;
    }
    if($dbclose!="-1"){$this->dbclose();}
    return SUCCESS;
}

现在我要做的是调用 $dbobj-&gt;dbquery("my query","database name"); 其中 $dbobj 是这些函数类的对象。

如何转换这些函数,以便使用我收到的作为参数的任何查询并将其转换为准备好的语句?我无法重写代码中的每个查询。我已经编写了超过 10,000 个查询。

【问题讨论】:

  • 您期望通过这种方法获得什么“净收益”?是的,您的脚本可以解析 sql 语句 ....就像 MySQL 服务器一样。有什么优势?
  • 我想防止 SQL 注入,但我无法将所有查询重写为准备好的。所以,我想将此函数转换为解析传入的查询并转换为准备好的。而我在开始编码时制作这个函数的原因是因为我认为如果mysql改变了语法或者我必须迁移到其他数据库,我可以通过改变这个函数来轻松地做到这一点。
  • 如果您可以解析查询“sql-injection-safe”,那么是什么阻碍了 MySQL 服务器这样做呢? IE。您打算实施什么样的额外 SmartLayer™?
  • 事实上,我什至不知道攻击者尝试SQL注入时是否可以解析查询。或者除了使用准备好的语句之外还有其他方法可以做到这一点吗?我希望将用户输入的相同值存储在数据库中并检索相同的值,但所有这些都没有 SQL 注入。
  • 当参数在语句中时,损坏可能已经造成。如果您的代码应该解析任意 sql 语句,我看不出(至少在这个通用公式中)它给表带来了什么新东西。

标签: php mysql


【解决方案1】:

问题是您似乎将整个查询作为字符串传递给您的 dbquery() 方法。

Prepared statements 仅在将值作为参数传递给查询的情况下防止 sql 注入,而不是在该值已在查询中时。

由于您的整个查询是单个字符串,没有占位符并且没有单独传递任何值,因此您不能在不更改将查询和参数传递给dbquery() 方法的方式的情况下使用准备好的语句来防止 sql 注入。因此,如果您想利用准备好的语句的 sql 预防功能,则需要重写查询。

【讨论】:

  • 谢谢。我明白你的意思..我会尝试其他方式..我将获取所有传入的 get、post 和所有请求并对其进行清理..顺便说一句,是否有这样做而不是使用准备好的语句?
  • 是的,还有其他选择。请参阅此处的stackoverflow.com/questions/60174/… 主题。阅读超出接受的答案,因为它几乎重复了“使用准备好的陈述”的口头禅,我不是一个超级粉丝。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-18
  • 2016-03-29
  • 1970-01-01
  • 2021-01-08
  • 2013-02-15
  • 2019-07-03
  • 1970-01-01
相关资源
最近更新 更多