Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Correlates security events in IBM QRadar SIEM using AQL (Ariel Query Language), custom rules, building blocks, and offense management to detect multi-stage attacks across network, endpoint, and application log sources. Use when SOC analysts need to investigate QRadar offenses, build correlation rules, or tune detection logic for reducing false positives.
.claude/skills/correlating-security-events-in-qradar/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | — | — |
| case-14 | ✗→✓ | ▲ Improved | — | — |
| case-15 | ✗→✓ | ▲ Improved | — | — |
| case-09 | ✗→✓ | ▲ Improved | — | — |
| case-01 | ✗→✓ | ▲ Improved | — | — |
Use this skill when:
Do not use for log source onboarding or parsing — that requires QRadar administrator access and DSM editor knowledge.
Open an offense in QRadar and query contributing events using AQL (Ariel Query Language):
sqlSELECT DATEFORMAT(startTime, 'yyyy-MM-dd HH:mm:ss') AS event_time, sourceIP, destinationIP, username, LOGSOURCENAME(logSourceId) AS log_source, QIDNAME(qid) AS event_name, category, magnitude FROM events WHERE INOFFENSE(12345) ORDER BY startTime ASC LIMIT 500
Pivot on the source IP to find all activity:
sqlSELECT DATEFORMAT(startTime, 'yyyy-MM-dd HH:mm:ss') AS event_time, destinationIP, destinationPort, username, QIDNAME(qid) AS event_name, eventCount, category FROM events WHERE sourceIP = '192.168.1.105' AND startTime > NOW() - 24*60*60*1000 ORDER BY startTime ASC LIMIT 1000
Create a multi-condition rule detecting brute force followed by successful login:
Rule 1 — Brute Force Detection (Building Block):
Rule Type: Event
Rule Name: BB: Multiple Failed Logins from Same Source
Tests:
- When the event(s) were detected by one or more of [Local]
- AND when the event QID is one of [Authentication Failure (5000001)]
- AND when at least 10 events are seen with the same Source IP
in 5 minutes
Rule Action: Dispatch new event (Category: Authentication, QID: Custom_BruteForce)Rule 2 — Brute Force Succeeded (Correlation Rule):
Rule Type: Offense
Rule Name: COR: Brute Force with Subsequent Successful Login
Tests:
- When an event matches the building block BB: Multiple Failed Logins from Same Source
- AND when an event with QID [Authentication Success (5000000)] is detected
from the same Source IP within 10 minutes
- AND the Destination IP is the same for both events
Rule Action: Create offense, set severity to High, set relevance to 8Correlate authentication failures with network flows to detect lateral movement:
sqlSELECT e.sourceIP, e.destinationIP, e.username, QIDNAME(e.qid) AS event_name, e.eventCount, f.sourceBytes, f.destinationBytes FROM events e LEFT JOIN flows f ON e.sourceIP = f.sourceIP AND e.destinationIP = f.destinationIP AND f.startTime BETWEEN e.startTime AND e.startTime + 300000 WHERE e.category = 'Authentication' AND e.sourceIP IN ( SELECT sourceIP FROM events WHERE QIDNAME(qid) = 'Authentication Failure' AND startTime > NOW() - 3600000 GROUP BY sourceIP HAVING COUNT(*) > 20 ) AND e.startTime > NOW() - 3600000 ORDER BY e.startTime ASC
Detect data exfiltration by correlating DNS queries with large outbound flows:
sqlSELECT sourceIP, destinationIP, SUM(sourceBytes) AS total_bytes_out, COUNT(*) AS flow_count FROM flows WHERE sourceIP IN ( SELECT sourceIP FROM events WHERE QIDNAME(qid) ILIKE '%DNS%' AND destinationIP NOT IN ( SELECT ip FROM reference_data.sets('Internal_DNS_Servers') ) AND startTime > NOW() - 86400000 GROUP BY sourceIP HAVING COUNT(*) > 500 ) AND destinationPort NOT IN (80, 443, 53) AND startTime > NOW() - 86400000 GROUP BY sourceIP, destinationIP HAVING SUM(sourceBytes) > 104857600 ORDER BY total_bytes_out DESC
Create reference sets for dynamic whitelists and watchlists:
bash# Create reference set via QRadar API curl -X POST "https://qradar.example.com/api/reference_data/sets" \ -H "SEC: YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Known_Pen_Test_IPs", "element_type": "IP", "timeout_type": "LAST_SEEN", "time_to_live": "30 days" }' # Add entries curl -X POST "https://qradar.example.com/api/reference_data/sets/Known_Pen_Test_IPs" \ -H "SEC: YOUR_API_TOKEN" \ -d "value=10.0.5.100"
Use reference sets in rule conditions to exclude known benign activity:
Test: AND when the Source IP is NOT contained in any of [Known_Pen_Test_IPs]
Test: AND when the Destination IP is contained in any of [Critical_Asset_IPs]Reduce false positives by adding building block filters:
sql-- Find top false positive generators SELECT QIDNAME(qid) AS event_name, LOGSOURCENAME(logSourceId) AS log_source, COUNT(*) AS event_count, COUNT(DISTINCT sourceIP) AS unique_sources FROM events WHERE INOFFENSE( SELECT offenseId FROM offenses WHERE status = 'CLOSED' AND closeReason = 'False Positive' AND startTime > NOW() - 30*24*60*60*1000 ) GROUP BY qid, logSourceId ORDER BY event_count DESC LIMIT 20
Apply tuning:
Create a QRadar Pulse dashboard with key correlation metrics:
sql-- Active offenses by category SELECT offenseType, status, COUNT(*) AS offense_count, AVG(magnitude) AS avg_magnitude FROM offenses WHERE status = 'OPEN' GROUP BY offenseType, status ORDER BY offense_count DESC -- Mean time to close offenses SELECT DATEFORMAT(startTime, 'yyyy-MM-dd') AS day, AVG(closeTime - startTime) / 60000 AS avg_close_minutes, COUNT(*) AS closed_count FROM offenses WHERE status = 'CLOSED' AND startTime > NOW() - 30*24*60*60*1000 GROUP BY DATEFORMAT(startTime, 'yyyy-MM-dd') ORDER BY day
| Term | Definition | |------|-----------| | AQL | Ariel Query Language — QRadar's SQL-like query language for searching events, flows, and offenses | | Offense | QRadar's correlated incident grouping multiple events/flows under a single investigation unit | | Building Block | Reusable rule component that categorizes events without generating offenses, used as input to correlation rules | | Magnitude | QRadar's calculated offense severity combining relevance, severity, and credibility scores (1-10) | | Reference Set | Dynamic lookup table in QRadar for whitelists, watchlists, and enrichment data used in rules | | QID | QRadar Identifier — unique numeric ID mapping vendor-specific events to normalized categories | | Coalescing | QRadar's mechanism for grouping related events into a single offense to reduce analyst workload |
QRADAR OFFENSE INVESTIGATION — Offense #12345
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Offense Type: Brute Force with Subsequent Access
Magnitude: 8/10 (Severity: 8, Relevance: 9, Credibility: 7)
Created: 2024-03-15 14:23:07 UTC
Contributing: 247 events from 3 log sources
Correlation Chain:
14:10-14:22 — 234 Authentication Failures (EventCode 4625) from 192.168.1.105 to DC-01
14:23:07 — Authentication Success (EventCode 4624) from 192.168.1.105 to DC-01 (user: admin)
14:25:33 — New Process: cmd.exe spawned by admin on DC-01
14:26:01 — Net.exe user /add detected on DC-01
Sources Correlated:
Windows Security Logs (DC-01)
Sysmon (DC-01)
Firewall (Palo Alto PA-5260)
Disposition: TRUE POSITIVE — Escalated to Incident Response
Ticket: IR-2024-0432| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +23 percentage points is the difference between those two pass rates over the 22 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.