A little bit about my project: I wanted to create slick & quick web application and I need authentication mechanism simple yet secure;I didn’t wanted to use heavy and slow IIS;I didn’t wanted to purchase SSL certificates;I didn’t wanted to keep users data in my database;I was limited to Intranet only;
Challenge-response — that’s why NTLM is also referenced as “negotiation protocol”.Connection oriented — not session oriented, thus authentication process will fail if connection will break during negotiation.This negotiation need to take place for every TCP connection to the server, for each resource on the web page, thus number of challenges and responses will grow.
String is base64 encoded byte array, which holds NTLM Messages
Out of scope: Samba — since we need it’s Linux oriented, replacing Active Directory, thus will not applicable for Windows.
Shytikov on NTLM Authentication
Was ist das NTLM?• NTLM is Microsoft-designed security protocol;• Since it’s Microsoft-designed, it’s weak;• It’s so weak even MS does not recommend to use it;• Despite this fact it is widely used in Intranet solutions;• And for authentication in enterprise-oriented applications, such as IIS, MS SQL Server, MS Exchange;• Specification is not available;• Reverse-engeneered by Samba team;
NTLM in more details:• NTLM provides a challenge-response authentication mechanism;• NTLM is connection oriented rather session oriented protocol;• NTLM could multiply your network traffic if connection become broken;• NTLM uses one way hash algorithms to hide user-related information;• Doubles information in two hashes: newer NT (weak) and older LM (even more weaker);• Uses little-endian byte arrays for communication;
NT in more details:• NT stands for New Technology (originally by Microsoft);• There are two versions of NT hashes;• NT hashes (version 1) are made by using outdated MD4 algorithm;• Collision in MD4 hashes could be found in about an hour;• NT hashes (version 2) are made by using HMAC-MD5 algorithm;• Hashes are ‘salted’ with random 8-byte challenge from server;
LM in more details:• LM stands for LAN Manager (originally by OS/2 & NetBIOS);• LM hashes support passwords of 7 symbols long maximum;• Longer passwords are breaking in 7 symbol chunks and encoded;• 7 symbols LM chunks could be brute-forced separately;• DES cryptographic algorithm was used.
So why should I use it?• It’s simple;• It’s supported in all browsers;• It’s most time works seamlessly for users (single sign-in);• It’s available by default in most of Microsoft’s products;• It does not expose user credentials even without using SSL encryption (no need to purchase certificates);• It’s secure enough for trusted environments, such as company intranet;
NTLM HTTP Authentication:• Client first request: GET /index.html HTTP/1.1• Server first response: HTTP/1.1 401 Unauthorized WWW-Authenticate: NTLM Connection: close• Client second request (Message Type 1): GET /index.html HTTP/1.1 Authorization: NTLM TlRMTVNTUAABAAAABzIAAAYABgArAAAACwALACAAAABXT1 JLU1RBVElPTkRPTUFJTg==• Server second response (Message Type 2): HTTP/1.1 401 Unauthorized WWW-Authenticate: NTLM TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mrze8 AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTA EUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHI ALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA=• Client third request (Message Type 3): GET /index.html HTTP/1.1 Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGoAAAAYABgAggAAAAwADABAAA AACAAIAEwAAAAWABYAVAAAAAAAAACaAAAAAQIAAEQATwBNAEEASQBOAHUAcwBlAHIA VwBPAFIASwBTAFQAQQBUAEkATwBOAMM3zVy9RPyXgqZnr21CfG3mfCDC0+d8ViWpjB wx6BhHRmspst9GgPOZWPuMITqcxg==• Server third response: HTTP/1.1 200 OK
But HOW I could do it from .NET?Nobody knows!!!
Ok, there are some ways:• Include IIS to your setup Pros: don’t worry, be happy! Cons: you have limited control, large memory footprint, poor performance;• Use Mono.Security.Protocol.Ntlm Pros: sources available; Cons: works only for client side;• Try to access via System.Net.Security.NegotiateStream class Pros: native .NET way to do the job; Cons: need to un-wrap underlying stream to get credentials;• Call to native code of Security Support Provider Interface (SSPI); Pros: more straightforward way to do the job; Cons: calling unsafe code, comply with C procedure calls;
SSPI — exporting from secur32.dll: [DllImport("secur32.dll", CharSet = CharSet.Auto, SetLastError = false)] private static extern int AcquireCredentialsHandle( string pszPrincipal, string pszPackage, int fCredentialUse, IntPtr PAuthenticationID, IntPtr pAuthData, int pGetKeyFn, IntPtr pvGetKeyArgument, ref Common.SecurityHandle phCredential, ref Common.SecurityInteger ptsExpiry); [DllImport("secur32.dll", CharSet = CharSet.Auto, SetLastError = false)] private static extern int AcceptSecurityContext(ref Common.SecurityHandle phCredential, IntPtr phContext, ref Common.SecurityBufferDesciption pInput, uint fContextReq, uint TargetDataRep, out Common.SecurityHandle phNewContext, out Common.SecurityBufferDesciption pOutput, out uint pfContextAttr, out Common.SecurityInteger ptsTimeStamp); [DllImport("secur32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern int AcceptSecurityContext(ref Common.SecurityHandle phCredential, ref Common.SecurityHandle phContext, ref Common.SecurityBufferDesciption pInput, uint fContextReq, uint TargetDataRep, out Common.SecurityHandle phNewContext, out Common.SecurityBufferDesciption pOutput, out uint pfContextAttr, out Common.SecurityInteger ptsTimeStamp);
Process is simple (for server):• When Message Type 1 received — initiate SSPI by calling AcquireCredentialsHandle;• Use acquired credentials for getting 8-byte challenge and composing Message Type 2 by calling AcceptSecurityContext;• Sending Message Type 2 to client;• Receiving Message Type 3 from client and validating it by calling AcceptSecurityContext;• In case of success allow access;• In case of failure, show an error;
Process is simple (for client):• This is was not my task actually, so only in theory;• After receiving Error 401, compose Message Type 1 using libraries available in Mono.Security.Protocol.Ntlm;• Sending Message Type 1 to server;• Receiving Message Type 2 from server, extracting 8-byte challenge;• Using 8-byte challenge compose Message Type 3 using libraries available in Mono.Security.Protocol.Ntlm;• Send Message Type 3 and pray…
More on NTLM:• http://davenport.sourceforge.net/ntlm.html• http://pinvoke.net/default.aspx/secur32/InitializeSecurityContext.html• https://github.com/mono/mono/tree/master/mcs/class/Mono.Security/Mon o.Security.Protocol.Ntlm• https://github.com/toolchain/Nancy.Authentication.Ntlm