Potential Malicious User Agents

In this brief Splunk tip for defenders we are going to talk web proxy logs and analyzing user agent strings. We will identify some common ones and show a search you can modify to fit your needs.

Target User Agents

When we started this we identified the following base strings to look for:

  • Cross Site Scripting
  • Iceweasel - Web browser built into Kali
  • Meterpreter
  • Nikto - Vulnerability scanner
  • Dirb - Directory exploring tool
  • Wscript - Windows scripts

We thought this gave us a good base to handle the alerts and learn more about our web traffic. I already hear the pentesters "we can change user agent strings" and they totally can. This is meant to help clear that lower level attacker so you can focus more on hunting those great whites ;)


Extract User Agents

We were doing this with logs from a Cisco WSA and we had to extract the user agents in order to do searches on them. Below is the regex we used for this:

Field name: wsa_user_agent
Extraction: ^[^>\n]*>\s+\-\s+"(?P<wsa_user_agent>[^"]+)

You may need to adjust this for your environment but we wanted to pull the hood up to reveal how we are doing it.


The Search

Below is the main search. It can be used to show a chart on a dashboard or for an alert depending on how you want to leverage it. Also, this leverages a whitelist lookup concept we covered in a previous post, CURING ALERT FATIGUE THROUGH SUPPRESSION AND FIDELITY


| multisearch

[ search index=cisco_wsa "script"
| search wsa_user_agent="*script*"
| fields _time, wsa_user_agent, wsa_host_ip, wsa_dest_url] 

[ search index=cisco_wsa "Iceweasel"
| search wsa_user_agent="*Iceweasel*"
| fields _time, wsa_user_agent, wsa_host_ip, wsa_dest_url]

[ search index=cisco_wsa "Meterpreter/Windows"
| search wsa_user_agent="*Meterpreter/Windows"
| fields _time, wsa_user_agent, wsa_host_ip, wsa_dest_url]

[ search index=cisco_wsa "Mozilla/5.00 (Nikto/"
| search wsa_user_agent="Mozilla/5.00 (Nikto/*"
| fields _time, wsa_user_agent, wsa_host_ip, wsa_dest_url]

[ search index=cisco_wsa "dirb"
| search wsa_user_agent="*dirb*"
| fields _time, wsa_user_agent, wsa_host_ip, wsa_dest_url]

[ search index=cisco_wsa "WinHttp.WinHttpRequest"
| search wsa_user_agent="*Win32; WinHttp.WinHttpRequest*"
| fields _time, wsa_user_agent, wsa_host_ip, wsa_dest_url]

| eval suspect_issue=if(like(wsa_user_agent,"%script%"),"Cross Site Scripting",suspect_issue)
| eval suspect_issue=if(like(wsa_user_agent,"%Iceweasel%"),"Kali",suspect_issue)
| eval suspect_issue=if(like(wsa_user_agent,"%Meterpreter%"),"Meterpreter",suspect_issue)
| eval suspect_issue=if(like(wsa_user_agent,"%(Nikto/%"),"Nikto Scanning",suspect_issue)
| eval suspect_issue=if(like(wsa_user_agent,"%dirb%"),"DirbScanning",suspect_issue)
| eval suspect_issue=if(like(wsa_user_agent,"%WinHttp.WinHttpRequest%"),"WScript",suspect_issue)
| stats latest(_time) AS Latest, values(wsa_dest_url) as wsa_dest_url by wsa_user_agent, suspect_issue, wsa_host_ip
| eval Latest =strftime(Latest , "%Y-%d-%m %H:%M")

| lookup dnslookup clientip as wsa_host_ip|eval temp=split(clienthost,".") 
| eval nt_host=mvindex(temp,0)
| rex field=wsa_dest_url "\/\/(?<wsa_domain>\\w+[\\.\-\\w]+)"
| search wsa_domain!="*.microsoftaik.azure.net"
| rename wsa_host_ip as src_ip

| `whitelist_trusted_internal_ips`
| stats values(suspect_issue) as subject, values(nt_host) as src, values(wsa_user_agent) as wsa_user_agent, values(wsa_domain) as dest, values(wsa_dest_url) as url by src_ip
| fillnull value="" src,src_ip,subject,dest

| search NOT [
| inputlookup ess_whitelist_potential_malicious_user_agent.csv
| eval current_date=strftime(now(), "%Y-%m-%d")
| eval expire_date=strptime(expire_date, "%Y-%m-%d")
| eval expire_date=strftime(expire_date, "%Y-%m-%d")
| where expire_date > current_date
| fields src src_ip subject dest]



By no means is this exhaustive but rather hopefully a start to get you comfortable with the web proxy logs and user agent strings. Another idea could be using the rare values function ;)