简体   繁体   中英

PHP detect SQL injection attempt

My code is already safe, using parameters in SQL queries, but, I would like to detect if anyone attempts to inject something into a submit form.

I found Snort, but I would need something that would be at PHP script level, not the whole network.

This is for a site that contains personal information for students and thus, we will warn (or even take action against) anyone that even tries an attack.

I have created a very basic and simple PHP class for checking / detecting SQL injection attempts.

<?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();

You can check it on github also

This is a very simple and basic class. Any suggestions for improvements / updates are welcome :)

This is actually quite a hard topic. BillyK may have a semi-viable approach but it's better to let MySQL do the hard work for you; therefore:

  • 1) Run the user-constructed (ie unsafe ) query in a MySQL Transaction .
  • 2) How many results does it give? (Check for both rows returned and rows affected )
  • 3) Record any MySQL error warning logs.
  • 4) Cancel / rollback the Transaction. So that nothing has changed on your database.
  • 5) Re-run the query with the paramaterised variable (ie safe )
  • 6) How many results does it give? (Check for both rows returned and rows affected )
  • 7) Check if (6) gives a different number of results to (2) or if (5) gives any SQL error warnings. You can also use PHP array comparison features to check if the result sets are equal.
  • 8) Any positives come up, such as differences in result counts, result set eqauality or SQL warnings, then record that query string into a save file for human review.

Concept Thoughts:

With a properly implemented system of Prepared Statements it is not possible for SQL injection to occur from user variables as data strings. Therefore, rather like people throwing water balloons at tanks; it's also pretty worthless to try and "detect" these infractions; they in themselves don't show you anything more than someone read some website that offers such methods.

Therefore, as long as you have built your PHP/SQL correctly then any number or any quality of SQL injecton attempts are just water off a ducks back , and you cumulatively waste more processing power and time and effort trying to detect and record them than you would simply to ignore them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM