PHP检测SQL注入尝试

时间:2018-04-28 13:31:26

标签: php mysql sql sql-injection

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

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

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

2 个答案:

答案 0 :(得分:2)

我创建了一个非常基本且简单的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上对其进行检查

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

答案 1 :(得分:1)

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

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

概念思想:

     

如果使用正确实施的预处理语句系统,则不可能从用户变量中以 data 字符串的形式进行SQL注入。因此,就像人们向水箱扔水气球一样;试图“发现”这些违规行为也毫无价值。他们本身不会向您显示更多信息,而只是有人阅读了提供此类方法的网站。

     

因此,只要您正确构建了PHP / SQL,那么任何数量或任何质量的SQL注入尝试都只是water off a ducks back,并且您会累计浪费更多的处理能力以及尝试检测和记录的时间和精力他们比您根本不会理会它们。