Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills

Complete skill folder anatomy across all cybersecurity skills:
- scripts/agent.py: 80-150 line Python agents using real libraries (impacket,
  boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.)
- references/api-reference.md: real API documentation with method signatures
- LICENSE: MIT license for all skill folders
This commit is contained in:
mukul975
2026-03-10 21:02:12 +01:00
parent c74d52fa30
commit 27c6414ca5
1390 changed files with 106806 additions and 0 deletions
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Anthropic Agent Skills Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,41 @@
---
name: analyzing-api-gateway-access-logs
description: >
Parses API Gateway access logs (AWS API Gateway, Kong, Nginx) to detect BOLA/IDOR
attacks, rate limit bypass, credential scanning, and injection attempts. Uses pandas
for statistical analysis of request patterns and anomaly detection. Use when
investigating API abuse or building API-specific threat detection rules.
---
# Analyzing API Gateway Access Logs
## Instructions
Parse API gateway access logs to identify attack patterns including broken object
level authorization (BOLA), excessive data exposure, and injection attempts.
```python
import pandas as pd
df = pd.read_json("api_gateway_logs.json", lines=True)
# Detect BOLA: same user accessing many different resource IDs
bola = df.groupby(["user_id", "endpoint"]).agg(
unique_ids=("resource_id", "nunique")).reset_index()
suspicious = bola[bola["unique_ids"] > 50]
```
Key detection patterns:
1. BOLA/IDOR: sequential resource ID enumeration
2. Rate limit bypass via header manipulation
3. Credential scanning (401 surges from single source)
4. SQL/NoSQL injection in query parameters
5. Unusual HTTP methods (DELETE, PATCH) on read-only endpoints
## Examples
```python
# Detect 401 surges indicating credential scanning
auth_failures = df[df["status_code"] == 401]
scanner_ips = auth_failures.groupby("source_ip").size()
scanners = scanner_ips[scanner_ips > 100]
```
@@ -0,0 +1,58 @@
# API Reference: Analyzing API Gateway Access Logs
## AWS API Gateway Log Fields
```json
{
"requestId": "abc-123",
"ip": "203.0.113.50",
"httpMethod": "GET",
"resourcePath": "/api/users/{id}",
"status": 200,
"requestTime": "2025-03-15T14:00:00Z",
"responseLength": 1024
}
```
## Pandas Log Analysis
```python
import pandas as pd
df = pd.read_json("access_logs.json", lines=True)
# BOLA detection
df.groupby("user_id")["resource_id"].nunique()
# Auth failure surge
df[df["status_code"] == 401].groupby("source_ip").size()
# Request velocity
df.set_index("timestamp").resample("1min").size()
```
## OWASP API Top 10 Patterns
| Risk | Detection Pattern |
|------|-------------------|
| BOLA (API1) | User accessing > 50 unique resource IDs |
| Broken Auth (API2) | > 100 401/403 from single IP |
| Excessive Data (API3) | Response size > 10x average |
| Rate Limit (API4) | > 100 req/min from single IP |
| BFLA (API5) | DELETE/PUT on read-only endpoints |
| Injection (API8) | SQL/NoSQL patterns in params |
## Injection Regex Patterns
```python
sql = r"union\s+select|drop\s+table|'\s*or\s+'1'"
nosql = r"\$ne|\$gt|\$regex|\$where"
xss = r"<script|javascript:|onerror="
path_traversal = r"\.\./\.\./|/etc/passwd"
```
### References
- OWASP API Security Top 10: https://owasp.org/API-Security/
- AWS API Gateway logging: https://docs.aws.amazon.com/apigateway/latest/developerguide/
- pandas: https://pandas.pydata.org/docs/
@@ -0,0 +1,179 @@
#!/usr/bin/env python3
"""Agent for analyzing API Gateway access logs for security threats."""
import os
import re
import json
import argparse
from datetime import datetime
from collections import defaultdict
import pandas as pd
import numpy as np
def load_api_logs(log_path):
"""Load API gateway logs from JSON lines or CSV."""
if log_path.endswith(".csv"):
return pd.read_csv(log_path, parse_dates=["timestamp"])
return pd.read_json(log_path, lines=True)
def detect_bola_attacks(df, threshold=50):
"""Detect Broken Object Level Authorization (BOLA/IDOR) attacks."""
findings = []
if "resource_id" not in df.columns:
path_col = "request_path" if "request_path" in df.columns else "path"
df["resource_id"] = df[path_col].str.extract(r'/(\d+)(?:/|$|\?)')
df_with_ids = df.dropna(subset=["resource_id"])
if df_with_ids.empty:
return findings
user_col = "user_id" if "user_id" in df.columns else "source_ip"
grouped = df_with_ids.groupby([user_col]).agg(
unique_resources=("resource_id", "nunique"),
total_requests=("resource_id", "count"),
).reset_index()
bola_suspects = grouped[grouped["unique_resources"] >= threshold]
for _, row in bola_suspects.iterrows():
findings.append({
"user": row[user_col],
"unique_resources_accessed": int(row["unique_resources"]),
"total_requests": int(row["total_requests"]),
"type": "BOLA/IDOR",
"severity": "CRITICAL",
})
return findings
def detect_auth_scanning(df, threshold=100):
"""Detect credential scanning via 401/403 response surges."""
findings = []
auth_failures = df[df["status_code"].isin([401, 403])]
if auth_failures.empty:
return findings
ip_col = "source_ip" if "source_ip" in df.columns else "client_ip"
ip_failures = auth_failures.groupby(ip_col).agg(
failure_count=("status_code", "count"),
unique_endpoints=("request_path", "nunique") if "request_path" in df.columns
else ("path", "nunique"),
).reset_index()
scanners = ip_failures[ip_failures["failure_count"] >= threshold]
for _, row in scanners.iterrows():
findings.append({
"source_ip": row[ip_col],
"auth_failures": int(row["failure_count"]),
"endpoints_probed": int(row["unique_endpoints"]),
"type": "credential_scanning",
"severity": "HIGH",
})
return findings
def detect_injection_attempts(df):
"""Detect SQL/NoSQL injection attempts in request parameters."""
injection_patterns = [
r"(?:union\s+select|select\s+.*\s+from|drop\s+table|insert\s+into)",
r"(?:'\s*or\s+'1'\s*=\s*'1|'\s*or\s+1\s*=\s*1)",
r'(?:\$ne|\$gt|\$lt|\$regex|\$where)',
r'(?:<script|javascript:|onerror=|onload=)',
r'(?:\.\./\.\./|/etc/passwd|/proc/self)',
]
findings = []
path_col = "request_path" if "request_path" in df.columns else "path"
query_col = "query_string" if "query_string" in df.columns else path_col
for _, row in df.iterrows():
request_str = str(row.get(query_col, "")) + str(row.get("request_body", ""))
for pattern in injection_patterns:
if re.search(pattern, request_str, re.IGNORECASE):
findings.append({
"source_ip": row.get("source_ip", row.get("client_ip", "")),
"path": row.get(path_col, ""),
"pattern_matched": pattern,
"type": "injection_attempt",
"severity": "HIGH",
})
break
return findings[:500]
def detect_rate_limit_bypass(df, window="1min", threshold=100):
"""Detect rate limit bypass attempts."""
findings = []
ip_col = "source_ip" if "source_ip" in df.columns else "client_ip"
df_copy = df.copy()
df_copy["timestamp"] = pd.to_datetime(df_copy["timestamp"])
df_copy = df_copy.set_index("timestamp")
for ip, group in df_copy.groupby(ip_col):
resampled = group.resample(window).size()
bursts = resampled[resampled > threshold]
if len(bursts) > 0:
findings.append({
"source_ip": ip,
"max_requests_per_min": int(resampled.max()),
"burst_periods": len(bursts),
"type": "rate_limit_bypass",
"severity": "MEDIUM",
})
return sorted(findings, key=lambda x: x["max_requests_per_min"], reverse=True)[:50]
def detect_unusual_methods(df):
"""Detect unusual HTTP methods on typically read-only endpoints."""
findings = []
dangerous_methods = {"DELETE", "PUT", "PATCH"}
method_col = "method" if "method" in df.columns else "http_method"
path_col = "request_path" if "request_path" in df.columns else "path"
unusual = df[df[method_col].str.upper().isin(dangerous_methods)]
for _, row in unusual.iterrows():
findings.append({
"source_ip": row.get("source_ip", row.get("client_ip", "")),
"method": row[method_col],
"path": row[path_col],
"status_code": int(row.get("status_code", 0)),
"type": "unusual_method",
"severity": "MEDIUM",
})
return findings[:200]
def main():
parser = argparse.ArgumentParser(description="API Gateway Log Analysis Agent")
parser.add_argument("--log-file", required=True, help="API gateway log file")
parser.add_argument("--output", default="api_gateway_report.json")
parser.add_argument("--action", choices=[
"bola", "auth_scan", "injection", "rate_limit", "full_analysis"
], default="full_analysis")
args = parser.parse_args()
df = load_api_logs(args.log_file)
report = {"generated_at": datetime.utcnow().isoformat(), "total_requests": len(df),
"findings": {}}
print(f"[+] Loaded {len(df)} API requests")
if args.action in ("bola", "full_analysis"):
findings = detect_bola_attacks(df)
report["findings"]["bola"] = findings
print(f"[+] BOLA suspects: {len(findings)}")
if args.action in ("auth_scan", "full_analysis"):
findings = detect_auth_scanning(df)
report["findings"]["auth_scanning"] = findings
print(f"[+] Auth scanners: {len(findings)}")
if args.action in ("injection", "full_analysis"):
findings = detect_injection_attempts(df)
report["findings"]["injection_attempts"] = findings
print(f"[+] Injection attempts: {len(findings)}")
if args.action in ("rate_limit", "full_analysis"):
findings = detect_rate_limit_bypass(df)
report["findings"]["rate_limit_bypass"] = findings
print(f"[+] Rate limit bypasses: {len(findings)}")
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"[+] Report saved to {args.output}")
if __name__ == "__main__":
main()