2019年11月

MipCms后台getshell

先看前台一个模版包含,通过id从数据库中查询出template
/app/article/controller/Article.php

$id = input('param.id');
if ($id) {
            $categoryInfo = model($this->itemCategoryModelNameSpace)->getCategoryInfo($id);
            if (!$categoryInfo) {
                $this->error('分类不存在','');
            }
            $currentCid = $categoryInfo['id'];
        }
        
...
  
        $templateName = $categoryInfo['template'] ? $categoryInfo['template'] : $this->itemType;
        $templateName = str_replace('.html', '', $templateName);
        
        return $this->mipView($this->itemType. '/' .$templateName);

在看修改template部分代码
/app/article/controller/ApiAdminArticleCategory.php

  public function categoryAdd()
    {
        $data = $this->request->post();
        if (!$data['name']) {
            return jsonError('请输入名称');
        }
        if (!$data['url_name']) {
          return jsonError('请输入URL别名');
        }
        $itemCategoryInfo = db($this->itemCategory)->where('name',$data['name'])->find();
        if ($itemCategoryInfo) {
            return jsonError('添加项已存在');
        }
        $itemInfo = db($this->itemCategory)->where('url_name',$data['url_name'])->find();
        if ($itemInfo) {
            return jsonError('别名已存在,请重新输入');
        }
        $res = model($this->itemCategoryModelNameSpace)->categoryAdd($data);
        if ($res) {
            return jsonSuccess('操作成功');
        } else {
            return jsonError('操作失败');
        }
    }

通过上述代码可以发现直接把post数据给caltegory去添加了,那么就可以操作任意的列,正常添加的post数据如下

{
  "id": 1,
  "pid": 0,
  "name": "test",
  "url_name": "test",
  "seo_title": "",
  "template": "xxx",
  "detail_template": "articleDetail.html",
  "category_url": "/article/<url_name>/",
  "category_page_url": "<category_url>index_<page>.html",
  "detail_url": "/article/<id>.html",
  "description": "",
  "keywords": "",
  "is_page": "0",
  "content": ""
}

其中template就是我们可以控制的字符,就可以达到修改template包含任意html文件的目的,那么我们还需要一个写入任意html的点。

/addons/collectHuochetou/controller/ApiUserCollectHuochetou.php
这里就可以看前台一个采集插件,

public function articleAdd(Request $request) {
...
try {
                        $htmlInfo = db('Addons')->where('name','html')->find(); //需要开启了html插件
                        if ($htmlInfo) {
                            $url = config('domainStatic').'/index.php?s='; 
                            //获取数据库中的domain并访问指定页面然后写入根目录的index.html
                            $html = getData($url);
                            $path = MIP_ROOT . 'index.html';
                            file_put_contents($path, $html);
                            
                    } catch (\Exception $e) {}
                    //插件-文章静态化结束
                    //以下为发布成功标识
                    return jsonSuccess('发布成功',$result);

}

但是在这个程序中后台并没有一个插件叫html。。陷入了僵局。。后来发现后台可以添加远程数据库作为新的站点,(无后台代码,只有前台代码)

即通过绑定了一个远程的前台数据库,然后修改addons,增加一个html插件

那么需要控制domain指向我们的webshell,好让他生成我们可以控制的页面的html,已经有数据库权限了,只需要修改setting表中的articleDomain即可实现。

然后在修改template实现本地包含

记一次electron程序破解

electron会把写好的程序打包成asar,需要对asar进行解包

npm -g instal asar
asar extract app.asar app/

解包之后目录如下

➜  x ls -lahrt
total 24
-rw-r--r--   1 x  staff   335B  7 31 19:16 package.json
drwxr-xr-x  34 x  staff   1.1K  7 31 19:16 node_modules
drwxr-xr-x   6 x  staff   192B  7 31 19:25 .
-rw-r--r--@  1 x  staff   6.0K  7 31 19:25 .DS_Store
drwxr-xr-x   4 x  staff   128B  7 31 19:25 dist
drwx------+ 10 x  staff   320B  7 31 19:34 ..

源码在dist/electron中

➜  electron ls -lahrt
total 26448
-rw-r--r--   1 x  staff   5.0K  7 31 19:16 0.js
-rw-r--r--   1 x  staff   4.4K  7 31 19:16 10.js
-rw-r--r--   1 x  staff   2.0K  7 31 19:16 11.js
-rw-r--r--   1 x  staff   2.9K  7 31 19:16 12.js
-rw-r--r--   1 x  staff   2.6K  7 31 19:16 13.js
-rw-r--r--   1 x  staff   6.0K  7 31 19:16 14.js
-rw-r--r--   1 x  staff   4.4K  7 31 19:16 15.js
-rw-r--r--   1 x  staff   1.1K  7 31 19:16 16.js
-rw-r--r--   1 x  staff   2.9K  7 31 19:16 17.js
-rw-r--r--   1 x  staff   3.8K  7 31 19:16 18.js
-rw-r--r--   1 x  staff   2.1K  7 31 19:16 19.js
-rw-r--r--   1 x  staff   5.8K  7 31 19:16 2.js
-rw-r--r--   1 x  staff   3.3K  7 31 19:16 20.js
-rw-r--r--   1 x  staff   4.8K  7 31 19:16 21.js
-rw-r--r--   1 x  staff    14K  7 31 19:16 22.js
-rw-r--r--   1 x  staff   2.4K  7 31 19:16 23.js
-rw-r--r--   1 x  staff   8.1K  7 31 19:16 24.js
-rw-r--r--   1 x  staff    17K  7 31 19:16 25.js
-rw-r--r--   1 x  staff   7.8K  7 31 19:16 26.js
-rw-r--r--   1 x  staff   7.7K  7 31 19:16 27.js
-rw-r--r--   1 x  staff    17K  7 31 19:16 28.js
-rw-r--r--   1 x  staff   3.2K  7 31 19:16 29.js
-rw-r--r--   1 x  staff   3.9K  7 31 19:16 3.js
-rw-r--r--   1 x  staff   4.7K  7 31 19:16 30.js
-rw-r--r--   1 x  staff   3.2K  7 31 19:16 31.js
-rw-r--r--   1 x  staff   2.8K  7 31 19:16 32.js
-rw-r--r--   1 x  staff   8.3K  7 31 19:16 33.js
-rw-r--r--   1 x  staff   3.5K  7 31 19:16 34.js
-rw-r--r--   1 x  staff    12K  7 31 19:16 35.js
-rw-r--r--   1 x  staff   7.9K  7 31 19:16 36.js
-rw-r--r--   1 x  staff   3.8K  7 31 19:16 37.js
-rw-r--r--   1 x  staff   1.8K  7 31 19:16 38.js
-rw-r--r--   1 x  staff   1.7K  7 31 19:16 39.js
-rw-r--r--   1 x  staff   851B  7 31 19:16 4.js
-rw-r--r--   1 x  staff   6.3K  7 31 19:16 40.js
-rw-r--r--   1 x  staff   2.9K  7 31 19:16 41.js
-rw-r--r--   1 x  staff    18K  7 31 19:16 42.js
-rw-r--r--   1 x  staff    18K  7 31 19:16 43.js
-rw-r--r--   1 x  staff   6.7K  7 31 19:16 44.js
-rw-r--r--   1 x  staff   4.0K  7 31 19:16 45.js
-rw-r--r--   1 x  staff   4.9K  7 31 19:16 46.js
-rw-r--r--   1 x  staff   5.6K  7 31 19:16 47.js
-rw-r--r--   1 x  staff   1.7K  7 31 19:16 48.js
-rw-r--r--   1 x  staff   3.5K  7 31 19:16 49.js
-rw-r--r--   1 x  staff   1.8K  7 31 19:16 5.js
-rw-r--r--   1 x  staff    23K  7 31 19:16 50.js
-rw-r--r--   1 x  staff    20K  7 31 19:16 51.js
-rw-r--r--   1 x  staff    27K  7 31 19:16 52.js
-rw-r--r--   1 x  staff    14K  7 31 19:16 53.js
-rw-r--r--   1 x  staff   427K  7 31 19:16 54.js
-rw-r--r--   1 x  staff   9.1K  7 31 19:16 6.js
-rw-r--r--   1 x  staff   3.5K  7 31 19:16 7.js
-rw-r--r--   1 x  staff   4.4K  7 31 19:16 8.js
-rw-r--r--   1 x  staff   1.4K  7 31 19:16 9.js
-rw-r--r--   1 x  staff   632K  7 31 19:16 css.worker.js
-rw-r--r--   1 x  staff   105K  7 31 19:16 editor.worker.js
-rw-r--r--   1 x  staff   254K  7 31 19:16 html.worker.js
-rw-r--r--   1 x  staff   168B  7 31 19:16 index.html
-rw-r--r--   1 x  staff   194K  7 31 19:16 json.worker.js
-rw-r--r--   1 x  staff    52K  7 31 19:16 main.js
-rw-r--r--   1 x  staff   3.8M  7 31 19:16 typescript.worker.js
drwxr-xr-x   4 x  staff   128B  7 31 19:16 imgs
drwxr-xr-x  66 x  staff   2.1K  7 31 19:16 .
drwxr-xr-x   5 x  staff   160B  7 31 19:16 fonts
drwxr-xr-x   4 x  staff   128B  7 31 19:25 ..
-rw-r--r--   1 x  staff   6.3M  7 31 19:30 renderer.js

根据提示搜索字符串发现核心文件是renderer.js
代码是压缩过的,拖到chrome里面进行格式化

分析源码发现通过ispro函数进行判定有没有激活,直接修改代码return 1即可

        get isPro() {
            return 1
            //return !!this.info && (!(this.info.type === l.monthly && this.currentTime > this.info.expiredAt) && h.proLicenses.includes(this.info.type))
        }

最后重新打包

asar pack app/ app.asar

然后替换原来的app.asar即可。