此类可以阻止或检测可能的SQL攻击吗?

时间:2013-11-20 17:24:57

标签: php mysql get filtering sql-injection

我刚写了一个简单的PHP类,我认为它可以帮助我防止或检测可能的SQL攻击。我不确定这是否真的有效,这就是为什么我在这里发布它来阅读你的想法和建议。

因此,让我们从经典的config.php文件开始,该文件创建与DB的连接并选择特定的数据库。我把它变成了一个类,它返回主页面中的连接链接。让我们看看:

<?php

class mysql_init
{

    public function initDb(){

        $con = mysqli_connect("localhost","user","password");
        mysqli_select_db($con,"geneticDb");

        return $con;
    }
}

?>

所以在这之后让我们看一下主页safe.php的代码。它有一个简单的例子,通过用户通过GET请求提供的Id从数据库中获取数据。

<?php

require_once('filter.php');
require_once('config.php');

$connection = new mysql_init();
$con = $connection->initDb();

$safe = new filter($con,'GET');

$n_id = $_GET['noteId'];


$data = mysqli_query($con,"SELECT noteType FROM notes WHERE noteId = $n_id ");

if($data){
    $row = mysqli_fetch_array($data, MYSQLI_BOTH);
    echo $row["noteType"];
}

?>

正如您所看到的,我也包括了filter.php,它是一个扫描用户发送的GET或POST请求的类。如果它会发现一些奇怪的东西,它会占用与数据库的会话的线程ID并将其关闭。事实是,这还没有完成,我的意思是我会用一些期货来保存一些(攻击者的)日志到数据库,并将他/她重定向到另一页通知他/她的记录。

<?php

class filter
{
    private $_activity = 0;

    public function __construct($sql_connection,$method){

        switch ($method) {
            case 'GET':
                $this->check_GET($sql_connection);
                break;

            case 'POST':
                $this->check_POST($sql_connection);
                break;

            case 'ALL':
                $this->check_POST($sql_connection);
                $this->check_GET($sql_connection);
                break;


            default:
                # code...
                break;
        }           
    }

    private function check_GET($con){

        if($_SERVER['REQUEST_METHOD'] == 'GET')
        {
            echo $_SERVER['REQUEST_URI']."<br>".$_SERVER['SCRIPT_NAME']."<br><br>";

            foreach($_GET as $index => $value)
            {                   
                if(preg_match('/\s/', $value))                              # no whitespaces
                    $this->_activity = 1;

                if(preg_match('/[\'"]/', $value))                           # no quotes
                    $this->_activity = 1;

                if(preg_match('/[\/\\\\]/', $value))                        # no slashes
                    $this->_activity = 1;

                if(preg_match('/(and|or|null|not|if)/i', $value))           # no sqli boolean keywords
                    $this->_activity = 1;

                if(preg_match('/(union|select|from|where)/i', $value))      # no sqli select keywords
                    $this->_activity = 1;

                if(preg_match('/(group|order|having|limit)/i', $value))     # no sqli select keywords
                    $this->_activity = 1;

                if(preg_match('/(into|file|case)/i', $value))               # no sqli operators
                    $this->_activity = 1;

                if(preg_match('/(;|--|#|\/\*)/', $value))                   # no sqli comments
                    $this->_activity = 1;

                if(preg_match('/(=|&|\|)/', $value))                        # no boolean operators
                    $this->_activity = 1;

                if(isset($this->_activity) && $this->_activity == 1){
                    echo "Something detected => ".$index." : ".$value."<br>";
                    $thread_id = mysqli_thread_id($con);
                    mysqli_kill($con, $thread_id);
                    $this->_activity = 0;
                }
            }
        } 
    }


    private function check_POST($con){

        if($_SERVER['REQUEST_METHOD'] == 'POST')
        {
            echo $_SERVER['REQUEST_URI']."<br>".$_SERVER['SCRIPT_NAME']."<br><br>";

            foreach($_POST as $index => $value)
            {                   
                if(preg_match('/\s/', $value))                              # no whitespaces
                    $this->_activity = 1;

                if(preg_match('/[\'"]/', $value))                           # no quotes
                    $this->_activity = 1;

                if(preg_match('/[\/\\\\]/', $value))                        # no slashes
                    $this->_activity = 1;

                if(preg_match('/(and|or|null|not|if)/i', $value))           # no sqli boolean keywords
                    $this->_activity = 1;

                if(preg_match('/(union|select|from|where)/i', $value))      # no sqli select keywords
                    $this->_activity = 1;

                if(preg_match('/(group|order|having|limit)/i', $value))     # no sqli select keywords
                    $this->_activity = 1;

                if(preg_match('/(into|file|case)/i', $value))               # no sqli operators
                    $this->_activity = 1;

                if(preg_match('/(;|--|#|\/\*)/', $value))                   # no sqli comments
                    $this->_activity = 1;

                if(preg_match('/(=|&|\|)/', $value))                        # no boolean operators
                    $this->_activity = 1;

                if(isset($this->_activity) && $this->_activity == 1){
                    echo "Something detected => ".$index." : ".$value."<br>";
                    $thread_id = mysqli_thread_id($con);
                    mysqli_kill($con, $thread_id);
                    $this->_activity = 0;
                }
            }
        } 
    }
}

?>

所以现在一切都好。你认为这段代码是有效的,还是以某种方式可以绕过它?

谢谢。

1 个答案:

答案 0 :(得分:1)

  

此类可以阻止或检测可能的SQL攻击吗?

没有。
它也适用于现实生活。

想象一下,在Stack Overflow这个站点上使用了类似的方法。您是否能够发布充满“危险”角色的问题?