Detection rules › Splunk

HTTP Scripting Tool User Agent

Status
production
Severity
low
Group by
Web.src, Web.status, c-useragent, cs-host, dest, http_user_agent, src, status
Author
Raven Tait, Splunk
Source
github.com/splunk/security_content

This Splunk query analyzes web access logs to identify and categorize non-browser user agents, detecting various types of security tools, scripting languages, automation frameworks, and suspicious patterns. This activity can signify malicious actors attempting to interact with web endpoints in non-standard ways.

Known false positives

  • False positives may be present if the activity is part of diagnostics or testing. Filter as needed.

MITRE ATT&CK coverage

Rule body

name: HTTP Scripting Tool User Agent
id: 04430b4e-5ca8-4e88-98b5-d6bcf54f8393
version: 6
creation_date: '2025-10-21'
modification_date: '2026-06-15'
author: Raven Tait, Splunk
status: production
type: Anomaly
description: This Splunk query analyzes web access logs to identify and categorize non-browser user agents, detecting various types of security tools, scripting languages, automation frameworks, and suspicious patterns. This activity can signify malicious actors attempting to interact with web endpoints in non-standard ways.
data_source:
    - Nginx Access
search: |-
    | tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime
    from datamodel=Web where
    Web.http_user_agent =*
    NOT Web.http_user_agent IN (
        "-",
        "unknown"
    )
    by Web.http_user_agent Web.dest Web.src Web.status
    | `security_content_ctime(firstTime)`
    | `security_content_ctime(lastTime)`
    | `drop_dm_object_name(Web)`
    | eval http_user_agent = lower(http_user_agent)
    | lookup scripting_tools_user_agents tool_user_agent AS http_user_agent OUTPUT tool
    | where isnotnull(tool)
    | stats count
        min(firstTime) as first_seen
        max(lastTime) as last_seen
        values(tool) as tool
    by http_user_agent dest src status
    | `security_content_ctime(first_seen)`
    | `security_content_ctime(last_seen)`
    | `http_scripting_tool_user_agent_filter`
how_to_implement: This analytic necessitates the collection of web data, which can be achieved through Splunk Stream or by utilizing the Splunk Add-on for Apache Web Server. No additional configuration is required for this analytic.
known_false_positives: False positives may be present if the activity is part of diagnostics or testing. Filter as needed.
references:
    - https://portswigger.net/web-security/request-smuggling#what-is-http-request-smuggling
    - https://portswigger.net/research/http1-must-die
    - https://www.vaadata.com/blog/what-is-http-request-smuggling-exploitations-and-security-best-practices/
    - https://www.securityweek.com/new-http-request-smuggling-attacks-impacted-cdns-major-orgs-millions-of-websites/
    - https://github.com/SigmaHQ/sigma/blob/master/rules/web/proxy_generic/proxy_ua_hacktool.yml
    - https://help.aikido.dev/zen-firewall/miscellaneous/bot-protection-details
intermediate_findings:
    entities:
        - field: dest
          type: system
          score: 20
          message: Known scripting tool was used against a web request. The source IP/Host is $src$ and the destination is $dest$.
threat_objects:
    - field: src
      type: ip_address
    - field: http_user_agent
      type: http_user_agent
analytic_story:
    - HTTP Request Smuggling
    - Suspicious User Agents
asset_type: Network
mitre_attack_id:
    - T1071.001
product:
    - Splunk Enterprise
    - Splunk Enterprise Security
    - Splunk Cloud
category: web
security_domain: network

Stages and Predicates

Stage 1: tstats

| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime
from datamodel=Web where
Web.http_user_agent =*
NOT Web.http_user_agent IN (
    "-",
    "unknown"
)
by Web.http_user_agent Web.dest Web.src Web.status

Stage 2: search

| `security_content_ctime(firstTime)`

Stage 3: search

| `security_content_ctime(lastTime)`

Stage 4: search

| `drop_dm_object_name(Web)`

Stage 5: eval

| eval http_user_agent = lower(http_user_agent)

Stage 6: lookup

| lookup scripting_tools_user_agents tool_user_agent AS http_user_agent OUTPUT tool
Lookup table
scripting_tools_user_agents
Key field
tool_user_agent as http_user_agent
Output columns
['tool', 'tool']

Stage 7: where

| where isnotnull(tool)

Stage 8: stats

| stats count
    min(firstTime) as first_seen
    max(lastTime) as last_seen
    values(tool) as tool
by http_user_agent dest src status

Stage 9: search

| `security_content_ctime(first_seen)`

Stage 10: search

| `security_content_ctime(last_seen)`

Stage 11: search

| `http_scripting_tool_user_agent_filter`

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
Web.http_user_agentin"-", "unknown"excludes:Web.http_user_agent

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Web.http_user_agenteq
  • "*"
field:"c-useragent" kind:eq
toolis_not_null
  • (no value, null check)
field:"tool" kind:is_not_null