• php代码审计3审计sql注入漏洞


    SQL注入攻击(sql injection)被广泛用于非法获取网站控制权,在设计程序时,忽略或过度任性用户的输入,从而使数据库受到攻击,可能导致数据被窃取,更改,删除以及导致服务器被嵌入后门程序等


    sql注入的条件
    用户输入数据可控,源程序要执行代码,拼接了用户输入的数据

    注入两大类型(不同数据库的比较方式不同)

    数字型注入:当输入的参数为整数时,可认为是数字型注入(如 id 年龄,页码等都可以认为是数字型注入,并且不需要单引号来闭合)
    $result = "select * freo admin where id=$id";


    字符型注入:当输入的参数为字符串时。称为字符型,需要单引号来闭合
    $result = "select * from admin where id='$id'";

    <?php
    $conn = mysql_connect('localhost', 'root', 'root') or die('bad!');
    mysql_query("SET NAMES binary'");
    mysql_select_db('test', $conn) OR emMsg("数据库连接失败");
    //这里id没有做整形转换
    $id = isset($_GET['id']) ? $_GET['id'] : 1;//sql语句没有做过滤,造成注入
    $sql = "SELECT * FROM news WHERE id={$id}";
    $result = mysql_query($sql, $conn) or die(mysql_error());
    ?>

    注入的利用方式
    查询数据
    读写文件
    执行命令

    注入过程
    攻击者访问页面
    将包含有攻击字符组成的sql语句转发给数据库执行
    数据库执行发回应用程序服务器
    应用程序将内容返回浏览器,即成功攻击


    盲注:在sql注入过程中,sql语句执行的选择后,选择的数据不在页面显示
    基于布尔sql盲注
    基于时间sql盲注
    基于报错sql盲注

    修复方案
    使用预编译语句
    使用存储过程
    检查数据类型
    使用安全函数过滤



    宽字节注入及二次注入

    宽字节注入:字符(charater)是组成字符集(character set)的基本单位,对字符赋予一个数值(encoding)来确定这个字符在该字符集中的位置,字符序(collation)指同一字符集内字符间的比较规则,由于ascll表示的字符只有128个,因此规范使用Unicode编码,但是使用ascll表示的字符使用Unicode并不高效,所以出现了中间格式字符集,被称为通用转换格式及UTF。GB2312 GBK GB118030 BIG5 Shift JIS等这些都是常说的宽字节,实际只有两字节,宽字节带来的安全问题主要是ascll字符(一字节)的现象

    <?php
    //连接数据库部分,注意使用了gbk编码,把数据库信息填写进去
    $conn = mysql_connect('localhost', 'root', 'toor!@#$') or die('bad!');
    mysql_query("SET NAMES 'gbk'");
    mysql_select_db('test', $conn) OR emMsg("连接数据库失败,未找到您填写的数据库");
    //执行sql语句
    $id = isset($_GET['id']) ? addslashes($_GET['id']) : 1;
    $sql = "SELECT * FROM news WHERE tid='{$id}'";
    $result = mysql_query($sql, $conn) or die(mysql_error()); //sql出错会报错,方便观察
    ?>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="gbk" />
    <title>新闻</title>
    </head>
    <body>
    <?php
    $row = mysql_fetch_array($result, MYSQL_ASSOC);
    echo "<h2>{$row['title']}</h2><p>{$row['content']}<p> ";
    mysql_free_result($result);
    ?>
    </body>
    2</html>

    SQL语句是SELECT * FROM news WHERE tid='{$id}',就是根据文章的id把文章从news表中取出来,在这个sql语句前面,使用了一个addslashes函数,将$id的值转义。这是通常cms中对sql注入进行的操作,只要我们的输入参数在单引号中,就逃逸不出单引号的限制,无法注入,addslashes函数产生的效果就是,让’变成’,让引号变得不再是“单引号”,只是一撇而已。一般绕过方式就是,想办法处理’前面的\,我们这里的宽字节注入是利用mysql的一个特性,mysql在使用GBK编码的时候,会认为两个字符是一个汉字(前一个ascii码要大于128,才到汉字的范围)。如果我们输入%df’会看到报错,说明sql语句出错,看到出错说明可以注入了,为什么在’也就是%27前面加了一个%df就报错了?而且可以看到,报错的原因就是多了一个单引号,而单引号前面的反斜杠不见了,这就是mysql的特性,因为gbk是多字节编码,他认为两个字节代表一个汉字,所以%df和后面的也就是%5c变成了一个汉字“運”,而’逃逸了出来。

    原理:%df%27---->(addslashes)--->%df%5c%27------>(GBK)====運'用户输入---->g过滤函数--->代码层的$sql--->mysql处理请求--->mysql中的sql
    默认编码character_set_client-->根据character_set_connection转换-->更新数据库是转换成字段对应的编码。

    修复方案
    使用mysql_set_charset(GBK)指定字符集
    使用mysql_real_escape_string进行转义



    二次注入
    注入点因为经过过滤处理无法触发sqlsql注入漏洞,比如addslashes函数,将单引号等字符转义变成’,但是存进数据库后数据又被还原,在这种情况下,如果发现一个新的注入同时引用了被插入的数据库数据时,就可以实现闭合新发现的注入漏洞引发二次注入,

    利用思路:
    现将注入语句插入到数据库,注册,留言等功能具有insert数据库的操作,然后在使用update的地方触发插入到数据库的注入语句。

    一阶sql注入:发生在一个http请求和响应中,对系统的攻击是立即执行的,攻击者在http请求中提交非法输入,应用程序处理非法输入,使用非法输入构造sql语句,在攻击过程中向攻击者返回结果

    二阶sql注入:攻击者在http请求中提交恶意输入,恶意输入保存在数据库中,攻击者提交第二次http请求,为处理第二次htt请求,程序在检索存储在数据库中的恶意输入,构造sql语句,如果攻击成功,在第二次请求响应中返回结果


    代码1
    <?php
        include('./connect.php'); //引入数据库配置文件
        $id=$_GET['id'];
        $select_sql="SELECT * FROM article WHERE title='$id'";
        echo $select_sql;
        mysql_query('set names utf8');
        $select_sql_result=mysql_query($select_sql);
        $date=mysql_fetch_assoc($select_sql_result);
     ?>
     <!DOCTYPE html>
     <html>
       <head>
         <meta charset="utf-8">
         <title><?php echo $date['title']."啦啦啦啦啦啦"?></title>
       </head>
       <body>
          <h1><?php echo $date['title'] ?></h1><br />
          作者:<?php echo $date['author'] ?><br/>
          时间:<?php echo date("Y-m-d H:i:s",$date['dateline'])?><br />
          概述: <?php echo $date['description']; ?><br />
          正文: <?php echo $date['content'] ?>
       </body>
     </html>

    代码2
    <?php
       include('../connect.php');
       $title=addslashes($_POST['title']);  //addslashes 将预定义字符串转义
       $author=addslashes($_POST['author']);
       $description=addslashes($_POST['description']);
       $content=addslashes($_POST['content']);
       $dataline=time();
       $insert="INSERT INTO article(title,author,description,content,dateline) VALUES('$title','$author','$description','$content','$dataline')";
       echo $insert;
       mysql_query("set names utf8"); //设置编码
       if($result=mysql_query($insert)){
         $num=mysql_affected_rows($con);
         echo $num;
         }
     ?>

    代码1是一个内容显示页面,通过传入的title在数据库进行查询,然后在页面调用输出,可以看到传递的参数id并没有经过过滤,可以成为一个典型的字符串GET注入,但是我们今天要讨论的是二次注入,暂时不考虑这个注入。代码2是一个添加页面,通过表单POST的数据执行INSERT语句插入数据,成功后返回数据库影响行数,而且这里的每一个参数都用addslashes函数进行了转义。两段代码结合,是一个典型的二次注入,虽然文章添加页面中过滤的非常严格,但是addslashes有一个特点就是虽然参数在过滤后会添加 “” 进行转义,但是“”并不会插入到数据库中,再配合内容显示页面中的查询是通过title查询的,所以可以利用这个构造一个二次注入。

  • 相关阅读:
    KTorrent 2.1
    Krusader-双面板文件治理器
    VirtualBox 1.3.4
    QEMU 0.9.0 & QEMU Accelerator 1.3.0pre10
    Sweep:音频编辑器材
    USBSink-优盘同步备份东西
    玩转 MPlayer(1)
    玩转 MPlayer(2)
    活动目录之迁移
    再学 GDI+[26]: TGPPen 画笔对齐 SetAlignment
  • 原文地址:https://www.cnblogs.com/Hydraxx/p/10322428.html
Copyright © 2020-2023  润新知