【问题标题】:PHP detect SQL injection attemptPHP 检测 SQL 注入尝试
【发布时间】:2018-04-28 13:31:26
【问题描述】:

我的代码已经是安全的,在 SQL 查询中使用参数,但是,我想检测是否有人尝试在提交表单中注入一些东西。

我找到了 Snort,但我需要的是 PHP 脚本级别的东西,而不是整个网络。

这是一个包含学生个人信息的网站,因此,我们将警告(甚至采取行动)任何尝试攻击的人。

【问题讨论】:

  • github.com/PHPIDS/PHPIDS尝试phpids
  • "little" 使用 phpids 有点矫枉过正。所有 SQL 注入都以单/双 qoute 和一些 SQL 关键字开头,以测试 POST 或 GET 请求是否存在注入。
  • 我尝试了 phpids 并最终安装了 enygma/expose。我想知道,有没有类似的东西和nginx的级别?我可以重复使用 ee 使用的过滤器。
  • @RaymondNijland “所有 SQL 注入都以单/双 qoute 开头” - 不,它们不是。请不要说这样的话,如果有人读到这里后真的相信了,那就很危险了。
  • 我的意思是说所有 SQL 注入攻击 开始测试 使用单/双 qoutes @misorude 如果他们工作他们添加其他关键字.. 我认为你理解错了,或者我应该写得更清楚

标签: php mysql sql sql-injection


【解决方案1】:

我创建了一个非常基本且简单的 PHP 类,用于检查/检测 SQL 注入尝试。

<?php
/**
 * simpleSQLinjectionDetect Class
 * @link      https://github.com/bs4creations/simpleSQLinjectionDetect 
 * @version   1.1
 */

class simpleSQLinjectionDetect
{   
    protected $_method  = array();
    protected $_suspect = null; 

    public $_options = array(
                            'log'    => true,
                            'unset'  => true,
                            'exit'   => true,
                            'errMsg' => 'Not allowed',
                        );

    public function detect()
    {
        self::setMethod();

        if(!empty($this->_method))
        {
            $result = self::parseQuery();

            if ($result)
            {
                if ($this->_options['log']) {
                    self::logQuery();
                }

                if ($this->_options['unset']){
                    unset($_GET, $_POST);
                }

                if ($this->_options['exit']){
                    exit($this->_options['errMsg']);
                }
            }
        }
    }

    private function setMethod()
    {
        if ($_SERVER['REQUEST_METHOD'] === 'GET') {
            $this->_method = $_GET;
        }

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $this->_method = $_POST;
        }
    }

    private function parseQuery()
    {
        $operators = array(
            'select * ',
            'select ',
            'union all ',
            'union ',
            ' all ',
            ' where ',
            ' and 1 ',
            ' and ',
            ' or ',
            ' 1=1 ',
            ' 2=2 ',
            ' -- ',
        );

        foreach($this->_method as $key => $val)
        {
            $k = urldecode(strtolower($key));
            $v = urldecode(strtolower($val));

            foreach($operators as $operator)
            {
                if (preg_match("/".$operator."/i", $k)) {
                    $this->_suspect = "operator: '".$operator."', key: '".$k."'";
                    return true;
                }
                if (preg_match("/".$operator."/i", $v)) {
                    $this->_suspect = "operator: '".$operator."', val: '".$v."'";
                    return true;
                }
            }
        }
    }

    private function logQuery()
    {
        $data  = date('d-m-Y H:i:s') . ' - ';
        $data .= $_SERVER['REMOTE_ADDR'] . ' - ';
        $data .= 'Suspect: ['.$this->_suspect.'] ';
        $data .= json_encode($_SERVER);
        @file_put_contents('./logs/sql.injection.txt', $data . PHP_EOL, FILE_APPEND);
    }
}

/* then call it in your app...
*********************************************/
$inj = new simpleSQLinjectionDetect();
$inj->detect();

你也可以在github上查看

这是一个非常简单和基础的类。欢迎任何改进/更新的建议:)

【讨论】:

  • SELECT * FROM account WHERE username = whatever AND password = '' OR 2=2 -- '
【解决方案2】:

这实际上是一个相当困难的话题。 BillyK 可能有一个半可行的方法,但最好让 MySQL 为您完成艰苦的工作;因此:

  • 1) 在MySQL Transaction 中运行用户构造的(即不安全)查询。
  • 2) 它给出了多少个结果? (检查返回的两行和受影响的行
  • 3) 记录任何 MySQL 错误警告日志。
  • 4) 取消/回滚事务。因此,您的数据库没有任何变化。
  • 5) 使用参数化变量(即安全)重新运行查询
  • 6) 它给出了多少个结果? (检查返回的两行和受影响的行
  • 7) 检查 (6) 给出的结果数量是否与 (2) 不同,或者 (5) 是否给出任何 SQL 错误警告。您还可以使用PHP array comparison 功能检查结果集是否相等。
  • 8) 出现任何阳性结果,例如结果计数的差异、结果集相等性或 SQL 警告,然后将该查询字符串记录到保存文件中以供人工审核。

概念思考:

使用正确实施的准备语句系统,SQL 注入不可能从用户变量作为 data 字符串发生。因此,就像人们向水箱扔水气球一样;尝试“检测”这些违规行为也毫无价值;它们本身并没有向您展示任何东西,只是有人阅读了一些提供此类方法的网站。

因此,只要您正确构建了 PHP/SQL,那么任何数量或任何质量的 SQL 注入尝试都只是water off a ducks back,并且您在尝试检测和记录它们时累积地浪费了更多的处理能力、时间和精力。你会简单地忽略它们。

【讨论】:

  • 请注意,COMMIT 不仅可以作为 php 方法调用,还可以作为 SQL 语句来完成,因此攻击者可以使用这种方法轻松提交更改。如果在数据库中定义了用户权限,攻击者可以很容易地获得管理员权限。尽管这个概念是正确的,但这种方法应该只在真正的沙盒 VM 上采用,并且要小心谨慎。
猜你喜欢
  • 2010-11-06
  • 1970-01-01
  • 2023-03-31
  • 2011-09-04
  • 2020-08-19
  • 2023-03-26
  • 2015-07-08
  • 2010-09-07
  • 1970-01-01
相关资源
最近更新 更多