Potential IIS code injection attempt
Description
'Potential code injection into web server roles via IIS logs scan. Represents attempt to gain initial access using drive-by compromise technique. Detection flags events for review and filtering of authorized activity.'
Query · kql
// set cIP and csMethod count limit to indicate potentially noisy events, this will be listed at the top of the results
// for any returns that are gt or equal to the default of 50
let cIP_MethodCountLimit = 50;
// Exclude common csMethods, add/modify this list as needed for your environment
let csMethodExclude = dynamic(['GET', 'DEBUG', 'DELETE', 'LOCK', 'MKCOL', 'MOVE', 'PATCH', 'POST', 'PROPPATCH',
'PUT', 'SEARCH', 'TRACE', 'TRACK', 'UNLOCK', 'OPTIONS', 'HEAD', 'RPC_IN_DATA', 'RPC_OUT_DATA', 'PROPFIND','BITS_POST','CCM_POST']);
// Include in the list expected IPs where remote methods such as vuln scanning may be expected for your environment
let expectedIPs = dynamic(['X.X.X.X', 'Y.Y.Y.Y']);
let codeInjectionAttempts = W3CIISLog
// Exclude private ip ranges from cIP list
| where ipv4_is_private(cIP) == false
| where cIP != "::1"
| where cIP !in (expectedIPs)
| project TimeGenerated, cIP, csUserName, csMethod, csCookie, csHost, sIP, scStatus, csUriStem, csUriQuery, csUserAgent, csReferer
// Throwing entire record into a single string column for attributable string matching
| extend pak = tostring(pack_all())
// Adding "arr" column containing indicators of matched suspicious strings
| extend arr = dynamic([])
| extend arr = iff(pak contains '<script' , array_concat(arr, pack_array('STRING MATCH : script')), arr)
| extend arr = iff(pak contains '%3Cscript' , array_concat(arr, pack_array('STRING MATCH : script')), arr)
| extend arr = iff(pak contains '%73%63%72%69%70%74' , array_concat(arr, pack_array('STRING MATCH : encoded script')), arr)
| extend arr = iff(pak contains '<img' , array_concat(arr, pack_array('STRING MATCH : img')), arr)
| extend arr = iff(pak contains '%3Cimg' , array_concat(arr, pack_array('STRING MATCH : img')), arr)
| extend arr = iff(pak contains 'passwd' , array_concat(arr, pack_array('STRING MATCH : passwd')), arr)
| extend arr = iff(csUserAgent contains 'nmap' , array_concat(arr, pack_array('STRING MATCH : nmap')), arr)
| extend arr = iff(csUserAgent contains 'nessus' , array_concat(arr, pack_array('STRING MATCH : nessus')), arr)
| extend arr = iff(csUserAgent contains 'qualys' , array_concat(arr, pack_array('STRING MATCH : qualys')), arr)
| extend arr = iff(csMethod !in (csMethodExclude), array_concat(arr, pack_array('INVALID HTTP METHOD')), arr)
| extend arr = iff(csUriStem == '/current_config/passwd' , array_concat(arr, pack_array('STRING MATCH : dahua scan url' )), arr)
| extend arr = iff(csUriQuery contains '..' and csUriQuery !endswith '...', array_concat(arr, pack_array('BACKTRACK ATTEMPT IN QUERY')), arr)
| extend arr = iff(csUriQuery contains 'http://www.webscantest.com' , array_concat(arr, pack_array('STRING MATCH : webscantest')), arr)
| extend arr = iff(csUriQuery contains 'http://appspidered.rapid7.com' , array_concat(arr, pack_array('STRING MATCH : appspider')), arr)
| where array_length(arr) > 0
| project-away pak;
let cIP_MethodHighCount = codeInjectionAttempts
| summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), cIP_MethodCount = count()
by cIP, tostring(arr), cIP_MethodCountType = "High Count of cIP and csMethod, this may be noise"
| where cIP_MethodCount >= cIP_MethodCountLimit;
let codeInjectAtt =
codeInjectionAttempts
| summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), cIP_MethodCount = count()
by cIP, cIP_MethodCountType = "Count of repeated entries, this is to reduce rowsets returned", csMethod,
tostring(arr), csHost, scStatus, sIP, csUriStem, csUriQuery, csUserName, csUserAgent, csCookie, csReferer;
// union the events and sort by cIP_MethodCount to identify potentially noisy entries. Additionally, cIP_MethodCountType
// indicates whether it is a high count or simply a count of repeated entries
(union isfuzzy=true
cIP_MethodHighCount, codeInjectAtt
| sort by cIP_MethodCount desc, cIP desc, StartTime desc)
| extend timestamp = StartTime, IPCustomEntity = cIP, HostCustomEntity = csHost, AccountCustomEntity = csUserName, URLCustomEntity = csUriQuery