Fix EvtVarTypeAnsiString conversion in winlogbeat#44026
Fix EvtVarTypeAnsiString conversion in winlogbeat#44026marc-gr merged 6 commits intoelastic:mainfrom
Conversation
|
This pull request does not have a backport label.
To fixup this pull request, you need to add the backport labels for the needed
|
|
I would gladly label this PR with the appropriate labels, if I could edit them. Is there some special markdown syntax I'm not aware of? |
|
Pinging @elastic/sec-windows-platform (Team:Security-Windows Platform) |
|
Thanks for the contribution!
If you could add an evtx to the PR that is able to be commited (properly sanitized, etc) I am happy to set the tests up for you. If not possible let me know any way and will move on with the PR |
|
Sure, see attached a sample EVTX ( I followed this guide but I still couldn't get it to ingest any events, so I can't claim the same bug will be triggered. I've at least peeked inside the file and the |
|
/test |
|
@Mergifyio backport 8.17 8.18 8.19 9.0 9.1 |
✅ Backports have been createdDetails
|
* 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)
* 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)
* 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)
* 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)
* 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)
* Naive first fix * Fix import order * Update strings_windows.go * Update CHANGELOG.next.asciidoc --------- (cherry picked from commit 6e1d4ea) Co-authored-by: Altair <AltairQ@users.noreply.github.com> Co-authored-by: Marc Guasch <marc-gr@users.noreply.github.com>
* Naive first fix * Fix import order * Update strings_windows.go * Update CHANGELOG.next.asciidoc --------- (cherry picked from commit 6e1d4ea) Co-authored-by: Altair <AltairQ@users.noreply.github.com> Co-authored-by: Marc Guasch <marc-gr@users.noreply.github.com>
…beat (#45228) * Fix EvtVarTypeAnsiString conversion in winlogbeat (#44026) * 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) * Update CHANGELOG.next.asciidoc --------- Co-authored-by: Altair <AltairQ@users.noreply.github.com> Co-authored-by: Marc Guasch <marc-gr@users.noreply.github.com>
…beat (#45229) * Fix EvtVarTypeAnsiString conversion in winlogbeat (#44026) * 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) * Update CHANGELOG.next.asciidoc --------- Co-authored-by: Altair <AltairQ@users.noreply.github.com> Co-authored-by: Marc Guasch <marc-gr@users.noreply.github.com>
…eat (#45232) * Fix EvtVarTypeAnsiString conversion in winlogbeat (#44026) * 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) * Update CHANGELOG.next.asciidoc --------- Co-authored-by: Altair <AltairQ@users.noreply.github.com> Co-authored-by: Marc Guasch <marc-gr@users.noreply.github.com>
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:
