Adversaries may attempt to exploit SQL injection vulnerabilities through the Application Gateway WAF by injecting malicious SQL code into application inputs, leveraging T1211 and T1059 techniques to exfiltrate data or execute arbitrary commands. SOC teams should proactively hunt for this behavior in Azure Sentinel to detect and mitigate potential data breaches and unauthorized system access early.
KQL Query
let Threshold = 3;
AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Matched"
| project transactionId_g, hostname_s, requestUri_s, TimeGenerated, clientIp_s, Message, details_message_s, details_data_s
| join kind = inner(
AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Blocked"
| parse Message with MessageText 'Total Inbound Score: ' TotalInboundScore ' - SQLI=' SQLI_Score ',XSS=' XSS_Score ',RFI=' RFI_Score ',LFI=' LFI_Score ',RCE=' RCE_Score ',PHPI=' PHPI_Score ',HTTP=' HTTP_Score ',SESS=' SESS_Score '): ' Blocked_Reason '; individual paranoia level scores:' Paranoia_Score
| where Blocked_Reason contains "SQL Injection Attack" and toint(SQLI_Score) >=10 and toint(TotalInboundScore) >= 15) on transactionId_g
| extend Uri = strcat(hostname_s,requestUri_s)
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), TransactionID = make_set(transactionId_g), Message = make_set(Message), Detail_Message = make_set(details_message_s), Detail_Data = make_set(details_data_s), Total_TransactionId = dcount(transactionId_g) by clientIp_s, Uri, action_s, SQLI_Score, TotalInboundScore
| where Total_TransactionId >= Threshold
id: 68c0b6bb-6bd9-4ef4-9011-08998c8ef90f
name: Application Gateway WAF - SQLi Detection
description: |
'Identifies a match for SQL Injection attack in the Application gateway WAF logs. The Threshold value in the query can be changed as per your infrastructure's requirement.
References: https://owasp.org/Top10/A03_2021-Injection/'
severity: High
requiredDataConnectors:
- connectorId: WAF
dataTypes:
- AzureDiagnostics
queryFrequency: 6h
queryPeriod: 6h
triggerOperator: gt
triggerThreshold: 0
tactics:
- DefenseEvasion
- Execution
- InitialAccess
- PrivilegeEscalation
relevantTechniques:
- T1211
- T1059
- T1190
- T0890
tags:
- SQL Injection
query: |
let Threshold = 3;
AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Matched"
| project transactionId_g, hostname_s, requestUri_s, TimeGenerated, clientIp_s, Message, details_message_s, details_data_s
| join kind = inner(
AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Blocked"
| parse Message with MessageText 'Total Inbound Score: ' TotalInboundScore ' - SQLI=' SQLI_Score ',XSS=' XSS_Score ',RFI=' RFI_Score ',LFI=' LFI_Score ',RCE=' RCE_Score ',PHPI=' PHPI_Score ',HTTP=' HTTP_Score ',SESS=' SESS_Score '): ' Blocked_Reason '; individual paranoia level scores:' Paranoia_Score
| where Blocked_Reason contains "SQL Injection Attack" and toint(SQLI_Score) >=10 and toint(TotalInboundScore) >= 15) on transactionId_g
| extend Uri = strcat(hostname_s,requestUri_s)
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), TransactionID = make_set(transactionId_g), Message = make_set(Message), Detail_Message = make_set(details_message_s), Detail_Data = make_set(details_data_s), Total_TransactionId = dcount(transactionId_g) by clientIp_s, Uri, action_s, SQLI_Score, TotalInboundScore
| where Total_TransactionId >= Threshold
# The Threshold value above can be changed as per your infrastructure's requirement
entityMappings:
- entityType: URL
fieldMappings:
- identifier: Url
columnName: Uri
- entityType: IP
fieldMappings:
- identifier: Address
columnName: clientIp_s
version: 1.0.1
kind: Scheduled
metadata:
source:
kind: Community
author:
name: shabaz-github
support:
tier: Community
categories:
domains: [ "Security - Threat Protection", "Platform" ]
| Sentinel Table | Notes |
|---|---|
AzureDiagnostics | Ensure this data connector is enabled |
Scenario: Legitimate Database Query via API
Description: A developer’s application sends a valid SQL query to a database through an API endpoint, which is flagged as SQLi by the WAF.
Filter/Exclusion: Exclude traffic from known internal IP ranges (e.g., src_ip IN ('10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16')) or add a custom header like X-Internal-Request: true and create a rule to exclude requests with that header.
Scenario: Scheduled Job Performing Database Maintenance
Description: A scheduled job (e.g., cron job or Windows Task Scheduler) runs a database maintenance script that includes SQL commands, triggering the SQLi detection rule.
Filter/Exclusion: Exclude requests with a specific user-agent string (e.g., User-Agent: /cron/) or add a filter for request_uri LIKE '/maintenance%' and exclude those requests.
Scenario: Log Management Tool Sending SQL Queries
Description: A log management tool like ELK Stack or Splunk sends SQL-like queries to a database for log analysis, which is misinterpreted as SQLi.
Filter/Exclusion: Exclude traffic from the log management tool’s IP address or add a filter for request_method = 'POST' AND request_uri LIKE '/log-query%' and exclude those requests.
Scenario: User Input with SQL-Like Characters in Form Submission
Description: A user submits a form with input containing SQL-like characters (e.g., ' OR 1=1 --) for a legitimate purpose, such as a search feature, which triggers the rule.
Filter/Exclusion: Exclude requests where the input is part of