feat(ntlm): setting wrong values for Target{Info,Name}*#4973
feat(ntlm): setting wrong values for Target{Info,Name}*#4973p-l- wants to merge 1 commit intosecdev:masterfrom
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #4973 +/- ##
=======================================
Coverage 80.31% 80.31%
=======================================
Files 381 381
Lines 93630 93640 +10
=======================================
+ Hits 75202 75211 +9
- Misses 18428 18429 +1
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR extends Scapy’s NTLM server-side token customization (NTLM_VALUES) to allow spoofing Target{Name,Info}{Len,MaxLen,BufferOffset} in NTLM CHALLENGE messages via byte-level patching, avoiding payload-layout-driven padding/allocations.
Changes:
- Add server-side byte-patching for
TargetName*andTargetInfo*security-buffer header fields in NTLM CHALLENGE serialization. - Add unit tests validating correct patch offsets, no excessive allocation, and survival through SPNEGO/ASN.1 re-encoding.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
scapy/layers/ntlm.py |
Implements byte-level patching of CHALLENGE header fields when NTLM_VALUES requests spoofed TargetName* / TargetInfo* values. |
test/scapy/layers/ntlm.uts |
Adds regression tests ensuring patched bytes are present at correct offsets and do not trigger large allocations, including via SPNEGO wrapping. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if _byte_patches: | ||
| # Serialize now, patch the bytes, then replace tok with a | ||
| # thin wrapper whose bytes() returns the patched bytes | ||
| # directly — this survives re-encoding in SPNEGO/ASN.1. | ||
| _tok_bytes = bytearray(bytes(tok)) | ||
| for off, fmt, val in _byte_patches: | ||
| sz = struct.calcsize(fmt) | ||
| _tok_bytes[off : off + sz] = struct.pack(fmt, val) | ||
|
|
||
| class _PatchedTok(object): | ||
| """Wrapper: bytes() returns pre-built patched NTLM bytes.""" | ||
|
|
||
| def __bytes__(self_inner): | ||
| return bytes(_tok_bytes) | ||
|
|
||
| tok = _PatchedTok() | ||
|
|
||
| # Store for next step | ||
| Context.chall_tok = tok |
There was a problem hiding this comment.
When _byte_patches is non-empty, tok is replaced by _PatchedTok and then stored in Context.chall_tok. This breaks the subsequent server-side authentication path because _checkLogin() (and NTLMSSP_DOMAIN._getSessionBaseKey()) later access Context.chall_tok.ServerChallenge, NegotiateFlags, etc., which _PatchedTok does not provide. Keep Context.chall_tok as the real NTLM_CHALLENGE packet (e.g., store the original tok in the context and only wrap/patch the returned token), or implement a proxy that delegates attribute access to the underlying packet while overriding __bytes__.
| sz = struct.calcsize(fmt) | ||
| _tok_bytes[off : off + sz] = struct.pack(fmt, val) |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Checklist:
tox)This allows setting fake values for Target{Name,Info}* in NTLM.