Fixlet Debugger: Regex Error - No preceding re for repetition op

Trying to evaluate the following regex expression in Fixlet Debugger to pull out the “DOMAIN\username” from Security Event Viewer logon events (ID 4624; logon type = 2):

q: (parenthesized parts of (matches (regex "(?<=New Logon:%0d%0a%09Security ID:%09%09)(.*)(?=%0d%0a%09Account Name:%09%09)") of description of it)) of records whose (event id of it = 4624 AND description of it as lowercase contains "Logon Type:%09%09%092" as lowercase AND time generated of it >(now-30*day)) of security event log

E: The expression could not be evaluated: Regex Error - No preceding re for repetition op.

It’s working fine through regex tester site: https://regex101.com/#javascript where:

The Test String =

New Logon:%0d%0a%09Security ID:%09%09DOMAIN\myusername.admin%0d%0a%09Account Name:%09%09myusername.admin

And the Regular Expression =

(?<=New Logon:%0d%0a%09Security ID:%09%09)(.*)(?=%0d%0a%09Account Name:%09%09)

Yields desired Result = DOMAIN\myusername.admin

I think it’s the look ahead/look behind functions ?<= and ?= in Debugger that are causing the problem… anyone know how to escape this for Fixlet Debugger testing?

Thank you :slight_smile:

Hey it_cat, I think you are correct in thinking the lookahead & lookbehind functionality is the culprit. I poked around and found that they are not supported in the POSIX regex flavor that BigFix uses. If you go here and choose “POSIX BRE” as one of the dropdown selections, you’ll see that the results show no or n/a for pretty much all those advanced functions.

That being said, I’m sure we can come up with an alternate solution. Now I don’t know if this will pass your real world data, but here is a workaround that seems to behave with your test string (plus some other junk I added based on my event log data):

q: (parenthesized parts of (matches (regex "New Logon:.*Security ID:%09.+(.*)%0d%0a%09Account Name:") of it)) of "Account Domain:%09%09BLAH%0d%0a%09Logon ID:%09%090x3e7%0d%0a%0d%0aLogon Type:%09%09%092%0d%0a%0d%0aNew Logon:%0d%0a%09Security ID:%09%09DOMAIN\myusername.admin%0d%0a%09Account Name:%09%09myusername.admin%0d%0a%09Account Domain:%09%09BLAH%0d%0a%09Logon ID:%09%090x1e77f7d%0d%0a%09SomeOtherJunk"
A: DOMAIN\myusername.admin
T: 0.467 ms
I: plural substring

Please give this regex a shot against your security event data and see how it goes:

(parenthesized parts of (matches (regex "New Logon:.*Security ID:%09.+(.*)%0d%0a%09Account Name:") of description of it)) of records whose (event id of it = 4624 AND description of it as lowercase contains "Logon Type:%09%09%092" as lowercase AND time generated of it >(now-30*day)) of security event log

1 Like

@Sean - thanks for this. Looks like we are heading in the right direction, but even though I can see my DOMAIN\username.admin in the actual Event Logs, the only result I am returning is one where the Security IS is an SID (and not a username):

A: S-1-5-21-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxxx

However, I don’t think there is anything wrong with the code you provided… this is actually due to the data only returning results where the Security ID is actually an SID… Here is an example of the full data returned, without any filtering/regex:

A: An account was successfully logged on.%0d%0a%0d%0aSubject:%0d%0a%09Security ID:%09%09S-1-5-21-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxxx%0d%0a%09Account Name:%09%09myusername.admin%0d%0a%09Account Domain:%09%09DOMAIN%0d%0a%09Logon ID:%09%090x1234567%0d%0a%0d%0aLogon Type:%09%09%092%0d%0a%0d%0aNew Logon:%0d%0a%09Security ID:%09%09S-1-5-21-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxxx%0d%0a%09Account Name:%09%09myusername.admin%0d%0a%09Account Domain:%09%09INTERNAL%0d%0a%09Logon ID:%09%090xabcdefgh%0d%0a%09Logon GUID:%09%09{YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY}%0d%0a%0d%0aProcess Information:%0d%0a%09Process ID:%09%090x178%0d%0a%09Process Name:%09%09C:\Windows\System32\svchost.exe%0d%0a%0d%0aNetwork Information:%0d%0a%09Workstation Name:%09MYLAPTOP%0d%0a%09 blah blah blah

In easier to read format:

Subject:%0d%0a%09
Security ID:%09%09 S-1-5-21-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxxx %0d%0a%09
Account Name:%09%09myusername.admin%0d%0a%09
Account Domain:%09%09DOMAIN%0d%0a%09
Logon ID:%09%090x1234567%0d%0a%0d%0a
Logon Type:%09%09%092%0d%0a%0d%0a
New Logon:%0d%0a%09
Security ID:%09%09 S-1-5-21-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxxx %0d%0a%09
Account Name:%09%09 myusername.admin %0d%0a%09
Account Domain:%09%09 DOMAIN %0d%0a%09
Logon ID:%09%090xabcdefgh%0d%0a%09
Logon GUID:%09%09{YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY}%0d%0a%0d%0a
Process Information:%0d%0a%09
Process ID:%09%090x178%0d%0a%09Process Name:%09%09C:\Windows\System32\svchost.exe%0d%0a%0d%0a
Network Information:%0d%0a%09
Workstation Name:%09MYLAPTOP%0d%0a%09
blah blah blah

Not sure why it is not working to pull back instances where the Security ID is my actual DOMAIN\myusername.admin. For example, after rebooting my laptop this morning, I logged in (using cached credentials). If I remove the check to pin my logon instance down to a specific type - and just return all - I only see a long list of SIDs. As mentioned previously, in the Event Viewer - Security, I see a Logon Type: 7 at 08:29am this morning with data in this format:

New Logon:
Security ID: DOMAIN\myusername.admin
Account Name: First.Last
Account Domain: DOMAIN
Logon ID: 0x1234567

Etc.

Any idea what could be going awry here?

I looked at my own 4624 security events and I think what’s going on is that the Event Viewer application is helpfully showing the username instead of the SID when displaying the event in that General tab view that is shown by default.

Because if you switch to the Details tab and look at the raw XML, there is no field that has the combined <username> result. I believe we are viewing the translation of the TargetUserSid field, perhaps with the TargetDomainName.

So like you said I don’t think the query is wrong, it’s just that we don’t have anything translating this raw SID value.

But since we do have the Account Domain and Account Name information, and unless I’m mistaken about what that means then we can use that instead of the SID.

So instead of using this:

q: (parenthesized parts of (matches (regex "New Logon:.*Security ID:%09.+(.*)%0d%0a%09Account Name:") of description of it)) of records whose (event id of it = 4624 AND description of it as lowercase contains "Logon Type:%09%09%092" as lowercase AND time generated of it >(now-30*day)) of security event log A: S-1-5-21-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxxx A: S-1-5-21-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxxx A: S-1-5-21-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxxx I: plural substring

You might be able to use this:

q: ((parenthesized part 2 of it & "\" & parenthesized part 1 of it) of (matches (regex "New Logon:.*Account Name:%09.+(.*)%0d%0a%09Account Domain:%09%09(.*)%0d%0a%09Logon ID") of description of it)) of records whose (event id of it = 4624 AND description of it as lowercase contains "Logon Type:%09%09%092" as lowercase AND time generated of it >(now-30*day)) of security event log A: DOMAIN\userX A: DOMAIN\userX A: DOMAIN\userX I: plural string

1 Like

@Sean - bingo! That worked great, thank you so much :slight_smile:

For anyone who is interested, here is the updated code to include the “time generated of it” and includes the slight change in Win10 parameters for this type of event in the last (1) day:

if (not windows of operating system) then "N/A" else if (name of operating system does not contain "Win10") then (((parenthesized part 2 of it & "\" & parenthesized part 1 of it) of (matches (regex "New Logon:.*Account Name:%09.+(.*)%0d%0a%09Account Domain:%09%09(.*)%0d%0a%09Logon ID") of description of it)),time generated of it) of records whose (event id of it = 4624 AND description of it as lowercase contains "Logon Type:%09%09%092" as lowercase AND time generated of it >(now-1*day)) of security event log as string else (((parenthesized part 2 of it & "\" & parenthesized part 1 of it) of (matches (regex "New Logon:.*Account Name:%09.+(.*)%0d%0a%09Account Domain:%09%09(.*)%0d%0a%09Logon ID") of description of it)),time generated of it) of records whose (event id of it = 4624 AND description of it as lowercase contains "Logon Type:%09%092%0d%0a%09" as lowercase AND time generated of it >(now-1*day)) of security event log as string

2 Likes

Awesome work guys !!

2 Likes

It is definitely important to be careful with slow event log relevance, and make sure it is not evaluating “every report”.

I have found in some cases where searching only recent log entries (TimeGenerated) for something, WMI can be faster than the Relevance Event Log inspectors, which is usually the opposite of the typical advice for writing relevance.

In this case, it seems like the above relevance is better than using WMI for the same, but just to give a similar WMI example:

( (parenthesized part 2 of it & " \ " & parenthesized part 1 of it) of matches (regex "New Logon:.*Account Name:%09.+(.*)%0d%0a%09Account Domain:%09%09(.*)%0d%0a%09Logon ID") of it) of string values whose(it contains "Logon Type:%09%092" OR it contains "Logon Type:%09%09%092") of selects "Message FROM Win32_NTLogEvent WHERE Logfile = 'Security' AND TimeGenerated > '20181115163047.000000-480' AND EventCode = '4624'" of wmis