zoukankan      html  css  js  c++  java
  • SQL注入实例( PHP + mysql )

    SQL注入的产生一般是由:开发人员在编写过程中未对用户输入参数做处理,直接拼接SQL,导致数据库被篡改。

    下面的Demo演示的是“恶意用户利用漏洞删除mysql数据”

    <?php
    //原有的sql模块,不安全的,抛弃
    function sql($sql){
      /*
      * 这是一个为了使用方便而编写的sql方法。
      * 所有select开头的sql返回查询结果,
      * 所有非select开头的sql返回受影响的行数。
      */    
    
        $ip="***";
        $port=3306;
        $username="***";
        $password="***";
        $database="***";
        $return = 0;
        //创建PDO对象
        $dsn = "mysql:host=$ip;dbname=$database;port=$port;charset=utf8";
        if(preg_match("/^[iIuUdDsS][nNpPeE][sSdDlL][eEaA][rRtTcC][tTeE]/is",$sql)){
            try{
                            $options = array(
                              PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, //默认是PDO::ERRMODE_SILENT, 0, (忽略错误模式)
                              PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 默认是PDO::FETCH_BOTH, 4
                            );
                            $pdo = new PDO($dsn, $username, $password, $options);
                            if (preg_match("/^[sS]/is",$sql)) {
                              //使用query
                              $stmt = $pdo->query($sql); //返回一个PDOStatement对象
                              $return = $stmt->fetchAll(); //获取所有
                              //$return = $stmt->rowCount(); //记录数
                            }else{
                              $return = $pdo->exec($sql); //返回受影响的行数
                              //$return = $pdo->lastInsertId();//返回修改的ID
                            }
                            $pdo = null;
                    }catch(Exception $e){
                        $return = $e->getMessage();
                    }
        }
        return $return;
    }
    
    
    
    /*
    * Sql注入Demo,这是存在风险的实力:
    */
    $k  = $_GET['k'];
    $v  = $_GET['v'];
    $i  = file_get_contents('php://input');
    if( strlen($k)>0 && ((strlen($v)>0 && count($_GET)==2)||( strlen($i)>0 && count($_GET)==1) )){ 
        $v = strlen($v) > 0 ? $v : $i;
        echo sql("insert into kv(k,v)values('$k','$v');"); //没有使用预编译
        exit();
    }
    
    ?>

     恶意用户访问:

    1 curl "***.com/1.php?k=sql注入" -d "test');delete from kv;"

    结果:kv表数据被全部删除!

    MySQL [***_db]> select * from kv;
    Empty set (0.04 sec)
    
    MySQL [***_db]> 

    解决方法:通过PHP prepare预编译sql

    代码如下:

    <?php
    
    //进行预编译的sql方法
    function ssql($sql,$arr=[],$json=false){
            $ip="***";
            $port=3306;
            $username="***";
            $password="***";
            $database="***";
            $dsn = "mysql:host=$ip;dbname=$database;port=$port;charset=utf8";
            $return = 0;
    
            if(preg_match("/^[iIuUdDsS][nNpPeE][sSdDlL][eEaA][rRtTcC][tTeE]/is",$sql)){
                    try{
                            $options = array(
                                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, //默认是PDO::ERRMODE_SILENT, 0, (忽略错误模式)
                                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 默认是PDO::FETCH_BOTH, 4
                            );
                            $pdo = new PDO($dsn, $username, $password, $options);//创建PDO对象
                            $stmt = $pdo->prepare($sql);//2)使用prepare预处理
                            $precute = $stmt->execute($arr);  //执行一条预处理语句 .成功时返回 TRUE, 失败时返回 FALSE 
                            if($precute){
                                    if( preg_match("/^[sS]/is",$sql) ) {
                                            $sqlData = $stmt->fetchAll();
                                    }else{
                                            $sqlData = $stmt->rowCount(); //成功数
                                    }
                                    if($json){
                                            $return = json_encode($sqlData,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);//JSON_PRETTY_PRINT|
                                    }
                            }
                            $pdo = null;
                    }catch(Exception $e){
                    }
            }
        return $return;
    }
    
    
    
    /*
    * 这是被测代码,使用预编译的sql方法
    */
    $k  = $_GET['k'];
    $v  = $_GET['v'];
    $i  = file_get_contents('php://input');
    if( strlen($k)>0 && ((strlen($v)>0 && count($_GET)==2)||( strlen($i)>0 && count($_GET)==1) )){ 
        $v = strlen($v) > 0 ? $v : $i;
        echo ssql("insert into kv(k,v)values(?,?);",[$k,$v]);
        exit();
    }
    ?>

     恶意用户访问:

    1 curl "***.com/1.php?k=sql注入" -d "test');delete from kv;"

    结果:直接存入data,没有数据被删除。

    MySQL [***_db]> select * from kv;
    +----+------+-----------+------------------------+------+
    | i | s | k | v | n |
    +----+------+-----------+------------------------+------+
    | 89 | NULL | sql注入 | test');delete from kv; | NULL |
    +----+------+-----------+------------------------+------+
    1 row in set (0.04 sec)

    MySQL [***_db]>

    TryEverything
  • 相关阅读:
    python基础——反射
    python基础——模块
    python基础——异常处理、递归
    python基础——生成器与迭代器
    python基础——装饰器
    Python常见面试题
    Socket网络编程
    爬虫解析相关
    爬虫请求相关
    初识爬虫
  • 原文地址:https://www.cnblogs.com/LiTry/p/13741253.html
Copyright © 2011-2022 走看看