Question Analysis
On a Linux host, review account management activity in Syslog or process event logs to pinpoint which command was executed to create a new local user. What was the name of the tool invoked?
02a91c34-8a5b-4bed-87af-501103eb5357
Question ID
17/23
Models Correct
1
Valid Answer
74%
Success Rate
Reference Answer
Human-validated correct answer for this question
useradd
Model Performance Comparison
See how different AI models performed on this question
Model | Answer | KQL Query | Status | Attempts | Time | Cost |
---|---|---|---|---|---|---|
gemini-2.5-flash-preview-04-17 | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0394 |
gpt-35-turbo | useradd | DeviceProcessEvents
| where ActionType == 'ProcessCreated' and ProcessCommandLine contains 'useradd'
| project ProcessCommandLine | Correct | 1 | 4.49s | 0.0033 |
gpt-4-turbo-2024-04-09 | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.2262 |
gpt-4.1 | useradd | DeviceProcessEvents
| where FileName in~ ("useradd", "adduser", "usermod")
or ProcessCommandLine has_any ("useradd", "adduser", "usermod")
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine | Correct | 1 | 5.22s | 0.0200 |
gpt-4.1-finetuned | useradd | DeviceProcessEvents
| where ProcessCommandLine contains "useradd"
or ProcessCommandLine contains "userdel"
or ProcessCommandLine contains "usermod"
| summarize arglist = make_set(ProcessCommandLine) by FileName, DeviceName
| extend timestamp = now(), HostName = DeviceName, ProcessName = FileName | Correct | 2 | 14.63s | 0.0161 |
gpt-4.1-mini | useradd | DeviceProcessEvents
| where InitiatingProcessCommandLine has_any ("useradd", "adduser", "usermod")
| project TimeGenerated, DeviceName, InitiatingProcessCommandLine, InitiatingProcessFileName
| sort by TimeGenerated desc | Correct | 2 | 6.50s | 0.0063 |
gpt-4.1-nano | useradd | DeviceProcessEvents
| where FileName in ('bash', 'sh', 'sudo', 'zsh') and ProcessCommandLine has_any ('useradd', 'adduser', 'addgroup', 'groupadd')
| project TimeGenerated, DeviceName, InitiatingProcessCommandLine, InitiatingProcessFileName, InitiatingProcessAccountName | Correct | 1 | 3.27s | 0.0007 |
gpt-4o | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0641 |
gpt-5-high | useradd | let LinuxDevices = DeviceInfo
| where OSPlatform =~ "Linux"
| project DeviceId, DeviceName;
// Process executions likely used to create a local user
let FromProcess = DeviceProcessEvents
| join kind=inner LinuxDevices on DeviceId
| where tolower(ProcessCommandLine) has_any ("useradd", "adduser") or FileName in~ ("useradd", "adduser")
| extend ToolVerb = tolower(extract(@"\b(adduser|useradd)\b", 1, ProcessCommandLine))
| extend FirstTokenPath = extract(@"(?:^|\s)(?:sudo\s+)?(?<tool>[\w\-/\.]+)", 1, ProcessCommandLine)
| extend FirstToken = tolower(extract(@"([^/\s]+)$", 1, FirstTokenPath))
| extend ToolInvoked = coalesce(ToolVerb, FirstToken, tolower(FileName))
| project TimeGenerated, DeviceId, DeviceName, AccountName, ToolInvoked, ProcessCommandLine, InitiatingProcessParentFileName, InitiatingProcessCommandLine;
// File modifications that happen when a user is created; pivot back to the initiating process (and its command line)
let FromFileMod = DeviceFileEvents
| join kind=inner LinuxDevices on DeviceId
| where FolderPath == "/etc" and FileName in~ ("passwd", "shadow", "gshadow", "group")
| where ActionType in~ ("FileModified", "FileCreated", "FileRenamed")
| extend ToolVerb = tolower(extract(@"\b(adduser|useradd)\b", 1, InitiatingProcessCommandLine))
| extend FirstTokenPath = extract(@"(?:^|\s)(?:sudo\s+)?(?<tool>[\w\-/\.]+)", 1, InitiatingProcessCommandLine)
| extend FirstToken = tolower(extract(@"([^/\s]+)$", 1, FirstTokenPath))
| extend ToolInvoked = coalesce(ToolVerb, FirstToken, tolower(InitiatingProcessFileName))
| project TimeGenerated, DeviceId, DeviceName, AccountName=InitiatingProcessAccountName, ToolInvoked, ProcessCommandLine=InitiatingProcessCommandLine, InitiatingProcessParentFileName, InitiatingProcessCommandLine;
union FromProcess, FromFileMod
| summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), SampleCommandline=any(ProcessCommandLine) by DeviceId, DeviceName, ToolInvoked
| order by LastSeen desc | Correct | 1 | 67.91s | 0.0627 |
gpt-5-mini-high | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0191 |
gpt-5-mini-low | useradd | let userPattern = "(?i)\\b(useradd|adduser|passwd|usermod|groupadd|newusers|addgroup|userdel|chpasswd|pw|adduser\\.sh)\\b";
let fileHint1 = "/etc/passwd";
let fileHint2 = "/etc/shadow";
let fileHint3 = "/etc/group";
let fileHint4 = "/home/";
let procMatches = DeviceProcessEvents
| where isnotempty(ProcessCommandLine) or isnotempty(InitiatingProcessCommandLine) or isnotempty(InitiatingProcessFileName)
| extend TriggerCommand = coalesce(ProcessCommandLine, InitiatingProcessCommandLine, InitiatingProcessFileName)
// look for known user-management commands or obvious file edits
| where TriggerCommand matches regex userPattern
or tostring(InitiatingProcessFileName) matches regex userPattern
or TriggerCommand contains fileHint1 or TriggerCommand contains fileHint2 or TriggerCommand contains fileHint3 or TriggerCommand contains fileHint4
| extend MatchedKeywords = extract_all(@"(?i)\\b(useradd|adduser|passwd|usermod|groupadd|newusers|addgroup|userdel|chpasswd|pw|adduser\\.sh)\\b", tostring(TriggerCommand))
| extend Hints = pack_array(
iff(TriggerCommand contains fileHint1, fileHint1, ""),
iff(TriggerCommand contains fileHint2, fileHint2, ""),
iff(TriggerCommand contains fileHint3, fileHint3, ""),
iff(TriggerCommand contains fileHint4, fileHint4, "")
)
| extend RawTool = coalesce(InitiatingProcessFileName, FileName, tostring(split(TriggerCommand, " ")[0]))
| extend ToolInvoked = tolower(extract(@"([^/\\]+)$", 1, RawTool))
| project TimeGenerated, DeviceName, AccountName, AccountDomain, ToolInvoked, TriggerCommand, MatchedKeywords, Hints, ProcessId, InitiatingProcessId, InitiatingProcessAccountName, InitiatingProcessAccountDomain;
let syslogMatches = DeviceEvents
| where isnotempty(AdditionalFields) or isnotempty(ProcessCommandLine) or FileName contains "syslog" or FolderPath contains "syslog" or FileName contains "message" or FileName contains "messages"
| extend AF = tostring(AdditionalFields)
| extend TriggerCommand = coalesce(ProcessCommandLine, AF)
| where TriggerCommand matches regex userPattern or AF matches regex userPattern or TriggerCommand contains fileHint1 or TriggerCommand contains fileHint2 or TriggerCommand contains fileHint3 or TriggerCommand contains fileHint4
| extend MatchedKeywords = extract_all(@"(?i)\\b(useradd|adduser|passwd|usermod|groupadd|newusers|addgroup|userdel|chpasswd|pw|adduser\\.sh)\\b", tostring(TriggerCommand))
| extend Hints = pack_array(
iff(TriggerCommand contains fileHint1, fileHint1, ""),
iff(TriggerCommand contains fileHint2, fileHint2, ""),
iff(TriggerCommand contains fileHint3, fileHint3, ""),
iff(TriggerCommand contains fileHint4, fileHint4, "")
)
| extend RawTool = coalesce(InitiatingProcessFileName, FileName, tostring(split(TriggerCommand, " ")[0]))
| extend ToolInvoked = tolower(extract(@"([^/\\\s]+)$", 1, RawTool))
| project TimeGenerated, DeviceName, AccountName, AccountDomain, ToolInvoked, TriggerCommand, MatchedKeywords, Hints, ProcessId = InitiatingProcessId, InitiatingProcessAccountName, InitiatingProcessAccountDomain;
union isfuzzy=true procMatches, syslogMatches
| where array_length(MatchedKeywords) > 0 or array_length(Hints) > 0
| extend ToolInvoked = iff(isempty(ToolInvoked) or ToolInvoked == "", tolower(extract(@"^([^\s/\\]+)", 1, tostring(TriggerCommand))), ToolInvoked)
| summarize Count = count(), Earliest = min(TimeGenerated), Latest = max(TimeGenerated), AnyCommand = make_list(TriggerCommand, 5), Devices = make_set(DeviceName), Accounts = make_set(AccountName), InitiatingAccounts = make_set(InitiatingProcessAccountName) by ToolInvoked
| order by Earliest desc
| project ToolInvoked, Count, Earliest, Latest, Devices, Accounts, InitiatingAccounts, AnyCommand | Correct | 4 | 68.30s | 0.0200 |
gpt-5-mini-medium | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0249 |
gpt-5-nano-high | useradd | let LinuxAccountCreateCommands = materialize(
(
DeviceEvents
| where TimeGenerated >= ago(1d)
| where InitiatingProcessCommandLine has_any ("useradd","adduser","/usr/sbin/useradd","/usr/bin/useradd","/usr/sbin/adduser","/usr/bin/adduser")
| extend ToolInvoked = coalesce(InitiatingProcessFileName, "Unknown")
| project TimeGenerated, DeviceName, AccountName, ToolInvoked, InitiatingProcessCommandLine, InitiatingProcessFileName
)
);
let LinuxProcEvents = materialize(
(
DeviceProcessEvents
| where TimeGenerated >= ago(1d)
| where InitiatingProcessCommandLine has_any ("useradd","adduser","/usr/sbin/useradd","/usr/bin/useradd","/usr/sbin/adduser","/usr/bin/adduser")
| extend ToolInvoked = coalesce(InitiatingProcessFileName, "Unknown")
| project TimeGenerated, DeviceName, AccountName = InitiatingProcessAccountName, ToolInvoked, InitiatingProcessCommandLine
)
);
LinuxAccountCreateCommands
| union (LinuxProcEvents)
| sort by TimeGenerated desc
| take 200 | Correct | 1 | 33.06s | 0.0024 |
gpt-5-nano-medium | useradd | union DeviceProcessEvents, DeviceEvents
| extend CmdLine = tolower(coalesce(InitiatingProcessCommandLine, ProcessCommandLine, ""))
| where CmdLine contains "useradd" or CmdLine contains "adduser" or InitiatingProcessFileName in ("useradd", "adduser")
| extend ToolName = case(CmdLine contains "useradd", "useradd", CmdLine contains "adduser", "adduser", "unknown")
| extend Username = tostring(extract(@"(?:^|\\s)(?:useradd|adduser)(?:\\s+[^-\\s]+)*\\s+([^\\s]+)", 1, CmdLine))
| project TimeGenerated, DeviceName, DeviceId, ToolName, Username, InitiatingProcessFileName, InitiatingProcessCommandLine, ProcessCommandLine
| sort by TimeGenerated desc
| take 100 | Correct | 2 | 77.19s | 0.0045 |
grok-3-beta | useradd | DeviceProcessEvents
| where ProcessCommandLine has_any ("useradd", "adduser")
| project DeviceName, ProcessCommandLine, InitiatingProcessFileName, ProcessCreationTime, AccountName
| order by ProcessCreationTime desc | Correct | 1 | 9.23s | 0.0305 |
grok-3-mini-beta | useradd | let linuxDevices = DeviceInfo | where OSPlatform contains "Linux" | distinct DeviceId;
DeviceProcessEvents
| where DeviceId in (linuxDevices)
| where ProcessCommandLine contains "useradd" or ProcessCommandLine contains "adduser"
| project Timestamp, DeviceName, ProcessCommandLine, ToolName=FileName
| order by Timestamp desc
| limit 10 | Correct | 1 | 13.30s | 0.0018 |
o1-high | useradd | let LinuxDevices = DeviceInfo
| where OSPlatform == "Linux"
| distinct DeviceId;
DeviceProcessEvents
| where DeviceId in (LinuxDevices)
| where ActionType == "ProcessCreated"
| where isnotempty(ProcessCommandLine)
| where ProcessCommandLine has_any ("useradd", "adduser")
| project TimeGenerated, DeviceName, FileName, ProcessCommandLine, AccountDomain, AccountName, InitiatingProcessAccountName | Correct | 1 | 23.92s | 0.2374 |
o1-low | useradd | DeviceProcessEvents
| where ActionType == "ProcessCreated"
| where FileName in~ ("useradd", "adduser")
| join kind=inner (DeviceInfo
| where OSPlatform == "Linux"
) on DeviceId
| project TimeGenerated, DeviceName, FileName, FolderPath, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine
| order by TimeGenerated desc | Correct | 2 | 37.90s | 0.3520 |
o3-high | useradd | // Time filter will be injected by the portal/time picker
let linuxDevices = DeviceInfo
| where OSPlatform =~ "Linux"
| distinct DeviceId;
DeviceProcessEvents
| where DeviceId in (linuxDevices)
// Typical Linux utilities used to add or modify local users
| where FileName in~ ("useradd", "adduser", "newusers", "usermod", "chpasswd")
or ProcessCommandLine matches regex @"\b(useradd|adduser|newusers|usermod|chpasswd)\b"
| project TimeGenerated,
DeviceName,
CreatedByAccount = tostring(InitiatingProcessAccountName),
ToolInvoked = tostring(FileName),
CommandLine = ProcessCommandLine
| summarize Executions = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by ToolInvoked
| order by Executions desc | Correct | 1 | 34.86s | 0.0238 |
o3-mini-high | useradd | union DeviceEvents, DeviceProcessEvents
| where isnotempty(InitiatingProcessCommandLine)
| where InitiatingProcessCommandLine has_any ("useradd", "adduser")
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine
| summarize FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by DeviceName, InitiatingProcessFileName
| sort by FirstSeen desc | Correct | 1 | 13.98s | 0.0091 |
o3-mini-low | useradd | DeviceProcessEvents
| where InitiatingProcessCommandLine has "useradd" or InitiatingProcessCommandLine has "adduser"
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine
| sort by TimeGenerated desc | Correct | 1 | 13.20s | 0.0135 |
o4-mini-high | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0590 |
o4-mini-low | useradd | // Identify syslog entries where a user‐add command was recorded
let SyslogUserAdd = DeviceEvents
| where SourceSystem == "Syslog"
| where AdditionalFields.syslog_message has_any ("useradd","adduser")
| extend Program = tostring(AdditionalFields.syslog_program),
Command = tostring(AdditionalFields.syslog_message)
| project TimeGenerated, DeviceName, Program, Command;
// Identify kernel‐level process events where the user‐add binary was executed
let ProcUserAdd = DeviceProcessEvents
| where FileName has_any ("useradd","adduser")
| extend Program = FileName,
Command = ProcessCommandLine
| project TimeGenerated, DeviceName, Program, Command;
// Combine and display
SyslogUserAdd
| union ProcUserAdd
| sort by TimeGenerated desc | Correct | 1 | 27.61s | 0.0122 |