菜鸡的代码审计之路

前言

本篇文章是由代码审计初学者所写,如有不正确的地方还请指出。

目标寻找

看了一段时间别人写的代码审计文章后,总归要自己上手搞搞,防止审计不出来漏洞导致抑郁,就有cnvd上瞅了一眼,然后就发现了这套电商源码

随机去官网下载了下来,搭建过程很简单,不在写了。

官网地址

安装教程

开始审计

即然已经知道了是文件上传引发的问题,所以全局搜索$_FILES

是基于thinkphp开发的cms,上来不了解TP的调用方式,本来想跟进函数调用,然后搜索发现根本就没得初始化类。后来去看了下TP框架的说明,才知道原来还有service层这个东西。不会开发的心塞。。

这里补充一下TP框架兼容路由模式,其路由形式是这样式的:http://网址/入口文件?s=/模块名(分组名)/控制器名/方法名/参数名/参数值。至于为什么后面都是html结尾呢。因为在config目录下的app配置文件中配置了url伪静态后缀。真是闲得慌,搞渗透没点开发知识有些点还真是不容易搞明白。。

// URL伪静态后缀
'url_html_suffix' =>'html',

同时结合搭建好的cms,登录到后台,其上传点也不多。简单试了下就定位到了application\service\PaymentService.php这个文件。

在后台支付方式可以新增,上传打包成zip文件的后门,就能拿到shell。虽然它会弹窗报错,但是依旧上传成功。

上传后没有路径返回,但谁让咱是代码审计呢,直接返回文件夹全局搜索4.php。发现在extend/payment/目录下

芜湖,这就完事了。

分析

回过头瞅瞅源码,看看咋会事引起的,只保留一些关键代码

// 如果不是目录则写入文件
if(!is_dir($file))
{
     // 读取这个文件
     $file_size = zip_entry_filesize($temp_resource);
     $file_content = zip_entry_read($temp_resource, $file_size);
     if(@file_put_contents($file, $file_content) !== false)
     {
          // 文件校验
          $config = self::GetPaymentConfig($payment);
          if($config === false)
               {
                    $error++;
                    @unlink($file);
               } else {
                    $success++;
}

GetPaymentConfig
    private static function GetPaymentConfig($payment)
    {
        $payment = '\payment\\'.$payment;
        
        if(class_exists($payment))
        {
            $obj = new $payment();
            if(method_exists($obj, 'Config') && method_exists($obj, 'Pay') && method_exists($obj, 'Respond'))
            {
                return $obj->Config();
            }
        }
        return false;
    }

文件写入后,会进入到GetPaymentConfig函数,class_exists函数检查类是否已定义,类使用完全限定名,然后检查是否定义了三种方法。检查不通过会返回false调用@unlink($file);删除文件。

但是这里class_exists的时候就会存在问题,后边加载上传的文件模块报错,导致并没有去删除文件,从而就形成了任意上传的效果。

同时这里正常逻辑可以构造相对应的代码结构,从而达到上传shell的目的。

<?php 
namespace payment;
class a{
public function __construct($params = [])
    {
        exec("")
    }
public function Config()
    {
    }
public function Pay()
    {
    }
public function Respond()
    {
    }
}
$b=new a();
?>

github上原来早就有人分析过了,详细可以看看这个issues

小结

这次的漏洞点还是比较好找的,但是没想到一个地方原来可能会存在这么多种问题: 1、模板上传shell 2、文件包含 3、条件竞争。漏洞点的多种利用方式也是以后要去学习的点,不能仅仅看到一面就完事了。

posted @ 2021-02-08 10:45  kidicc  阅读(104)  评论(0编辑  收藏  举报