防止 PHP 代码中的 SQL 注入(包括代码)

第一次来这里,所以我会尽量做到彻底。


我是一个相当新的程序员,并开始在一家新公司工作,我一直试图防止在旧项目遗留的特定 PHP 代码中进行一些 SQL 注入,但在我重写它时需要。


这个项目在 Laravel 作为后端,AngularJS 作为前端。


我尝试了几种方法来防止 SQL 注入,但都得到了相同的错误。


错误:


SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'll.created_at BETWEEN '?' AND '?' UNION SELECT 1 as type, ll.id, ll.name, ll.ema' at line 1

这是有问题的原始代码:


   if (!empty($request['inst'])) {

        $institution = $request['inst'];

        $inst = ' ll.inst_id = ' . $request['inst'] . ' AND ';

        $instCount = ' customers.inst_id = :inst AND ';

        $instEvent = ' location_id = :inst AND ';

    } else {

        $inst = ' ';

        $instCount = ' ';

        $instEvent = ' ';

        $institution = "";

    }

    $startTime = $request['start'];

    $endTime = $request['end'];

以下是我在仔细阅读互联网和 SO 后使用的一些技术。

  1. 占位符(?而不是所有变量,并在最后创建一个包含所有变量 9 次的数组)

  2. 命名绑定示例:DB::select($sql, ["inst" => $institution, "start" => $startTime, "end" => $endTime,])

  3. 命名绑定 命名绑定,PDO::ATTR_EMULATE_PREPARES => true,因此我可以多次使用 :inst、:start、:end

  4. 使用 @ 符号的 SQL 变量绑定

技术结果:

  1. 没有保护 - 工作正常,我收到正确的结果

  2. 占位符 - 我收到上述错误,但 SQL 在占位符中有正确的数据。我可以获取生成的 SQL 并通过 phpmyadmin 服务器 SQL 查询运行它,并按预期接收数据。

  3. 命名绑定 - 根本不起作用。我收到一条错误消息SQLSTATE[HY093]: Invalid parameter number: parameter was not defined

  4. 使用 - 命名的绑定可以PDO::ATTR_EMULATE_PREPARES => true,工作,但是它会影响我从服务器中提取的所有数据,将诸如数字之类的东西转换为字符串或更糟。这会对到处打字造成严重破坏

  5. SQL 变量绑定 - 也不起作用,收到上述错误

我不确定是否可以将这个巨大的 SQL 查询转换为 Laravel Eloquent 或 Query Builder,尽管我已经尝试过了。

有人有想法么?任何帮助将不胜感激,我已经为此苦苦挣扎了几个星期。


慕哥6287543
浏览 163回答 1
1回答

冉冉说

$institution = $request['inst']??'';$start = $request['start'];$end = $request['end'];$joins = [    1 => ['date_field' => 'meeting_set_first', 'is_active' => false],    2 => ['date_field' => 'occurred_date', 'is_active' => true],    3 => ['date_field' => 'not_show_date', 'is_active' => true],    4 => ['date_field' => 'cancel_meeting_date', 'is_active' => true],    5 => ['date_field' => 'sale_date', 'is_active' => true],    6 => ['date_field' => 'cancel_sale_date', 'is_active' => true],    7 => ['date_field' => 'extended_date', 'is_active' => false],    8 => ['date_field' => 'meeting_set_date', 'is_active' => true],];$sql = 'SELECT 0 as type ,ll.id as lead_name, ll.name, ll.email, ll.updated_at, u.employee_name, ls.meeting_set_date, ls.meeting_set_first FROM customers ll LEFT JOIN leads_statistics ls  ON ll.id = ls.lead_id LEFT JOIN users u ON ll.userUpdate = u.employee_id  WHERE '.($institution?" ll.inst_id = :inst0 AND ":'').' ll.created_at BETWEEN :start0 AND :end0 UNION ';if ($institution) {    $placeHolders[':inst0'] = $institution;}$placeHolders[':start0'] = $start;$placeHolders[':end0'] = $end;$queryJoin = [];foreach($joins as $key => $join) {    $queryJoin[] = 'SELECT '.$key.' as type, ll.id, ll.name, ll.email, ll.updated_at, u.employee_name, ls.meeting_set_date, ls.meeting_set_first FROM leads_statistics ls LEFT JOIN customers ll ON ls.lead_id = ll.id LEFT JOIN users u ON ll.userUpdate = u.employee_id  WHERE '.($institution?" ll.inst_id = :inst$key AND ":'').($join['is_active']?' ls.is_active = 1 AND ':'').' ls.'.$join['date_field'] ." BETWEEN :start$key AND :end$key";    if ($institution) {        $placeHolders[':inst'.$key] = $institution;    }    $placeHolders[':start'.$key] = $start;    $placeHolders[':end'.$key] = $end;}$sql .= implode(' UNION ', $queryJoin);$leads = DB::select($sql, $placeHolders);
打开App,查看更多内容
随时随地看视频慕课网APP