某管理系统代码审计
浏览 695 | 评论 0 | 字数 5284
硝基苯
2022年01月31日
  • 第一次搞,希望师傅们喷轻点
    本文章旨在技术交流。已脱敏处理

    黑盒测试

    漏洞点一:sqli

    登录日志可以查询
    03643-f4wc4hm9dbl.png
    返回
    43377-otto29mwmjs.png
    双引号
    53846-eye23e1i1ss.png
    怀疑注入,抓包
    26487-zdxsibxrcx.png
    确实是注入,随便打

    漏洞点二:上传

    14350-vwqi49o81sk.png
    可以添加打印模块
    25963-esggunf25k5.png
    上传点
    38643-ob3fu7up48.png
    85670-bqaoqlhmjz.png
    check白名单
    85111-j6qagmpq7y.png
    读了png
    98313-k2den2fb9g.png
    上传双后缀
    09922-lf97l8v23c.png
    发现php成功上传
    找路径
    87768-3ovutl3slm3.png
    成功getshell
    46861-gjbplpexmcw.png
    漏洞点挺多,但是主要是为了学习代码审计,黑盒就随便玩玩


    代码审计

    注:这个cms有些垃圾,高版本会报错,用了5.3版本的PHP,xdebug没有适配的,所以不再用debug进行调试
    文件结构
    14140-8b4ivfj82ze.png
    可以看到是tp二开的。tp3
    直接看Application可以看到
    25677-pr6oq1b3on9.png
    多了Controller.class。虽然能猜出个大概,但是还是老老实实,先看路由
    ./index.php
    92121-9y2c6zbpzmt.png
    引入./ThinkPHP/ThinkPHP.php
    在倒数第二行中,我们发现这个文件名的端倪,在加载核心Think类时,进行了拼接
    CORE_PATH通过回溯发现为./ThinkPHP/Library/Think
    52462-8wpz1qtrkub.png
    回溯EXT,开头定义了EXT,const用于声明常量,且不能被更改
    70283-j08al9mygu.png
    后续的路由规则都差不多
    35997-9e5pdudwzup.png
    所以只是文件名稍微改了一下而已。
    (这也是tp3的特点)控制器文件的命名方式是:类名+class.php(类文件后缀)

    上传

    发现上传
    55733-hrw880lsrkv.png
    访问
    17426-czlni5hmwro.png
    $src由$upload_path拼接$newname而成。
    $newname由$xname[0]拼接$xname[1];$xname[0]时随机生成,不可控。而上一行代码可以看到,$xname由.分隔$file['name'],取第一个元素和第二个元素。直接找到$name
    正着读代码:文件名传给了$name;通过strrpos函数获取最后一个.的位置。并用substr提取出来,进行check
    66127-ls1lgxa3129.png
    通过前面的$newname可知,我们将文件名中的.分割为数组元素,后缀取的是第二个点,但是check是check最后一个点的位置。于是就有了双后缀绕过。
    上传文件名123.php.jpg
    .jpg被进行check
    .php被进行拼接

    鸡肋上传

    这个上传点需要配合截断使用,但是是练习,所以进行记录。方便日后的复习
    跟进
    09948-o4ejmm3svt.png
    该方法名为ajax_upload
    全局搜索调用情况
    96566-uxz0lzf8v4a.png
    不存在调用。但第三个有调用,恰好在模块内,可以直接调用
    27053-qe3hlcbll6h.png
    先不着急往下跟,看看$path是否可控
    $xqid可控(var_dump为笔者调试时所写)
    36286-jj4dhx7mepc.png
    就是在获取参数。这也是tp3的做法,用I直接获取指定参数
    因为路径可控,所以我们继续往下看ajax_upload_xq,位置Admin/common/function.php
    对path进行了拼接
    80224-atmkz8lngsg.png
    做了上传
    63778-ahbg440e7ld.png
    这是tp3保存文件的方法,跟进看看
    获取后缀
    36457-ysy5xm80rl.png
    白名单
    33578-rorze2wdjxp.png
    获取文件名
    77400-5fd87abbm9x.png
    跟进getSaveName
    18544-y0w5hdfpiwf.png
    文件名命名规则
    46524-ozf5s0m223.png
    所以文件名不可控
    在一开始,我们是控制住了Path
    50230-09cqys60597b.png
    现在发挥作用了
    87866-sb4d1wbbb5.png
    最后生成的文件就是路径可控,文件名和后缀没办法控制
    通过upload()保存文件后
    继续下面
    00041-zcmdnk6o06.png
    随后利用上传的图片生成新的缩略图,删除并覆盖
    特定环境下,我们能截断路径,从而达到上传php

    注入点一:鸡肋注入

    ./install/index.php
    86077-hqpxzkg2lwf.png
    92664-pgfl8rqcet9.png
    没有过滤,可直接注入,但是过于鸡肋,因为在install时才能注入
    85033-wrk4vrzpyh.png

    注入点二:

    我直接就标出来大伙,一眼就看出来了。但是seay没扫出来
    96788-rncuab327k.png
    构造出payload
    22601-s80f7i4yurn.png

    小计

    • 后门新思路
      在./ThinkPHP/Library/Behavior/ReadHtmlCacheBehavior.class.php中发现这样一行代码
    1. $rule = preg_replace_callback('/{(\w+)\|(\w+)}/', function($match){return $match[2]($_GET[$match[1]]);}, $rule);

    可以看到其用了preg_replace_callback与replace相似,但是第二个参数是回调函数,
    他会将第三个参数中符合第一个参数的正则作为匿名函数的参数传入
    例如:
    59186-95bbe1x1mja.png
    $match作为一个数组,match[0]为完整匹配,而match[1]为子匹配
    04953-a7vlxd4czzb.png
    结合原语句,构造出利用方法
    95279-8rozp2jyzr.png

    • 预编译的写法,学习一下
      10625-94zbf6l7i3q.png

    只出来了2
    47813-nljwhisfz0j.png
    漏洞会出现在拼接后再进行sql语句执行
    07331-3xj7o1wlqtn.png

    本文作者:硝基苯
    本文链接:https://www.c6sec.com/index.php/archives/528/
    最后修改时间:2022-02-01 00:20:25
    本站未注明转载的文章均为原创,并采用 CC BY-NC-SA 4.0 授权协议,转载请注明来源,谢谢!
    评论已关闭
    评论列表
    暂无评论
    目录
    1. 黑盒测试
    2. 代码审计
    3. 小计
    文章如有不对指出,请联系斧正
    OK
    中午了,工作了一个上午,现在是午餐时间!