[8.18](backport #44026) Fix EvtVarTypeAnsiString conversion in winlogbeat#45229
Merged
[8.18](backport #44026) Fix EvtVarTypeAnsiString conversion in winlogbeat#45229
Conversation
* Naive first fix * Fix import order * Update strings_windows.go * Update CHANGELOG.next.asciidoc --------- Co-authored-by: Marc Guasch <marc-gr@users.noreply.github.com> (cherry picked from commit 6e1d4ea)
3 tasks
Contributor
|
Pinging @elastic/sec-windows-platform (Team:Security-Windows Platform) |
marc-gr
approved these changes
Jul 8, 2025
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Handle null terminator in ANSIBytesToString
WHAT:
Trim
AnsiStringValto the null terminator in theANSIBytesToStringfunction.WHY:
In
winlogbeat/sys/wineventlog/syscall_windows.go, there's a recurring pattern of_EvtGet*WinAPI functions called twice, first with anilbuffer pointer, to establish the required buffer size. Indeed, looking at e.g. documentation for EvtGetEventMetadataProperty this seems to be the right way. However, despite the phrase "required buffer size" in the docs, the value returned viaEventMetadataPropertyBufferUsedis not guaranteed to exactly describe the retrieved property size.The
EvtVariant.Datamethod makes an implicit assumption that variable-length event data types fill thebuf[offset:]byte slice exactly, factoring in further golang-specific interpretation. This certainly isn't true for both flavours of strings, for two reasons:wevtapi.dll!EvtGetEventMetadataPropertyoccasionally returns a buffer size rounded up to align to 4 or 8I have no clue why inflating the returned buffer size happens, but I have oberved it with my very own eyes, tracing a v9.0.0 winlogbeat on a Win10 machine with default sysmon+winlogbeat configuration. I have it on good authority that a similar thing happens on Windows Server machines.
Anyway, this detail makes no difference for consumers written in languages with first-class null-terminated strings. According to the EVT_VARIANT documentation, both
StringValandAnsiStringValare null terminated.The parsing logic for
StringVal/EvtVarTypeStringis not affected, because it relies oncommon.UTF16ToUTF8Bytes, which explicitly handles the (wide) null terminator. However, theEvtVarTypeAnsiStringcase passes the byte slice directly to aDecoderfromgolang.org/x/text/encoding, which happily interprets null bytes asU+0000.The end result is that events with fields with
inType="win:AnsiString"contain extra code points beyond the correct string; at the very least, a trailingU+0000. This is especially severe for empty strings.It's easiest to spot with the
Microsoft-Windows-Kernel-Bootevent provider (enabled and emitting events by default), event code 27, fieldLoadOptions. The decompiled manifest confirms that its type isAnsiString.(Please note that I'm not a golang developer. This was the first project I've ever compiled.)
Checklist
[ ] I have made corresponding changes to the documentation[ ] I have made corresponding change to the default configuration filesCHANGELOG.next.asciidocorCHANGELOG-developer.next.asciidoc.Disruptive User Impact
I can't imagine anyone relies on this bug.
How to test this PR locally
main) with the default configuration, but edited to useoutput.file\u0000codepoints -- see the Logs sectionTesting using an EVTX file would've been better, sure, but I couldn't get it to work. I'd be happy to provide one.
Related issues
Logs
With the bug
Example of an affected event, generated as described above. Notice the stray null byte in
winlog.event_data.LoadOptions.{ "@timestamp": "2025-04-08T23:11:57.099Z", "@metadata": { "beat": "winlogbeat", "type": "_doc", "version": "9.0.0" }, "host": { "hostname": "(REDACTED)", "architecture": "x86_64", "os": { "build": "19045.5737", "type": "windows", "platform": "windows", "version": "10.0", "family": "windows", "name": "Windows 10 Pro", "kernel": "10.0.19041.5737 (WinBuild.160101.0800)" }, "id": "b7f83483-6ced-4ed7-8a45-ff70f45f821f", "ip": [ "(REDACTED)" ], "mac": [ "(REDACTED)" ], "name": "(REDACTED)" }, "winlog": { "provider_guid": "{15CA44FF-4D7A-4BAA-BBA5-0998955E531E}", "provider_name": "Microsoft-Windows-Kernel-Boot", "computer_name": "(REDACTED)", "user": { "identifier": "S-1-5-18", "domain": "NT AUTHORITY", "name": "SYSTEM", "type": "Well Known Group" }, "event_data": { "BootType": "0", "LoadOptions": " NOEXECUTE=OPTIN NOVGA\u0000" }, "channel": "System", "version": 1, "event_id": "27", "opcode": "Info", "record_id": 1351, "process": { "pid": 4, "thread": { "id": 8 } }, "task": "BootType" }, "event": { "code": "27", "kind": "event", "provider": "Microsoft-Windows-Kernel-Boot", "action": "BootType", "created": "2025-04-22T13:13:08.659Z" }, "log": { "level": "information" }, "message": "The boot type was 0.", "ecs": { "version": "8.0.0" }, "agent": { "name": "(REDACTED)", "type": "winlogbeat", "version": "9.0.0", "ephemeral_id": "f2c28050-e72b-4c51-9851-c4162f40e256", "id": "12c3d9d7-8121-42d3-864d-c0e2cc957ab6" } }Another, more severe example, from the same machine and the same event provider (just the relevant portion):
I strongly suspect this is a leak from a re-used buffer, and what we're seing in
winlog.event_data.LoadOptionsare the remnants of "Microsoft" encoded with UTF-16LE.Patched
Just the
winlogpart:And the analogous event to the second "bugged" example; notice the
LoadOptionsare missing completely, since the field is empty.Bonus
How the ~same events look in Event Viewer:

This is an automatic backport of pull request #44026 done by [Mergify](https://mergify.com).