mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-24 21:40:58 +03:00
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:
@@ -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,56 @@
|
||||
# API Reference: Securing API Gateway with AWS WAF
|
||||
|
||||
## boto3 WAFv2 Client
|
||||
|
||||
### Installation
|
||||
```bash
|
||||
pip install boto3
|
||||
```
|
||||
|
||||
### Client Initialization
|
||||
```python
|
||||
client = boto3.client("wafv2", region_name="us-east-1")
|
||||
```
|
||||
|
||||
### Key Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `create_web_acl()` | Create a new Web ACL with rules and default action |
|
||||
| `update_web_acl()` | Modify rules, requires `LockToken` for optimistic concurrency |
|
||||
| `get_web_acl()` | Retrieve full Web ACL configuration and lock token |
|
||||
| `list_web_acls()` | List all Web ACLs in a scope (REGIONAL or CLOUDFRONT) |
|
||||
| `associate_web_acl()` | Attach Web ACL to API Gateway, ALB, or AppSync |
|
||||
| `get_sampled_requests()` | Retrieve sampled requests for a specific rule metric |
|
||||
| `get_rate_based_statement_managed_keys()` | Get IPs currently rate-limited |
|
||||
| `put_logging_configuration()` | Configure WAF logging to Firehose/S3 |
|
||||
| `list_resources_for_web_acl()` | List resources associated with a Web ACL |
|
||||
|
||||
### Managed Rule Groups
|
||||
| Rule Group | Protection |
|
||||
|-----------|------------|
|
||||
| `AWSManagedRulesCommonRuleSet` | OWASP Top 10 common attacks |
|
||||
| `AWSManagedRulesSQLiRuleSet` | SQL injection patterns |
|
||||
| `AWSManagedRulesKnownBadInputsRuleSet` | Known bad request patterns |
|
||||
| `AWSManagedRulesAmazonIpReputationList` | Malicious IP blocking |
|
||||
| `AWSManagedRulesBotControlRuleSet` | Bot detection and management |
|
||||
|
||||
### Rate-Based Rule Parameters
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `Limit` | int | Max requests per 5-minute window (min: 100) |
|
||||
| `AggregateKeyType` | str | `IP` or `FORWARDED_IP` |
|
||||
| `ScopeDownStatement` | dict | Optional filter to scope rate limiting |
|
||||
|
||||
### CloudWatch Metrics (Namespace: AWS/WAFV2)
|
||||
| Metric | Description |
|
||||
|--------|-------------|
|
||||
| `AllowedRequests` | Requests allowed by WAF |
|
||||
| `BlockedRequests` | Requests blocked by WAF |
|
||||
| `CountedRequests` | Requests matched in Count mode |
|
||||
| `PassedRequests` | Requests not matching any rule |
|
||||
|
||||
## References
|
||||
- boto3 WAFv2 docs: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/wafv2.html
|
||||
- AWS WAF Developer Guide: https://docs.aws.amazon.com/waf/latest/developerguide/
|
||||
- AWS Managed Rules list: https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-list.html
|
||||
@@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for managing AWS WAF Web ACLs protecting API Gateway endpoints."""
|
||||
|
||||
import boto3
|
||||
import json
|
||||
import sys
|
||||
import argparse
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
|
||||
def get_waf_client(region="us-east-1"):
|
||||
"""Create WAFv2 client for regional resources."""
|
||||
return boto3.client("wafv2", region_name=region)
|
||||
|
||||
|
||||
def list_web_acls(client, scope="REGIONAL"):
|
||||
"""List all Web ACLs in the account."""
|
||||
response = client.list_web_acls(Scope=scope)
|
||||
acls = response.get("WebACLs", [])
|
||||
print(f"[*] Found {len(acls)} Web ACL(s)")
|
||||
for acl in acls:
|
||||
print(f" - {acl['Name']} (ID: {acl['Id']})")
|
||||
return acls
|
||||
|
||||
|
||||
def get_web_acl_details(client, name, acl_id, scope="REGIONAL"):
|
||||
"""Get detailed Web ACL configuration including all rules."""
|
||||
response = client.get_web_acl(Name=name, Scope=scope, Id=acl_id)
|
||||
acl = response["WebACL"]
|
||||
lock_token = response["LockToken"]
|
||||
print(f"\n[*] Web ACL: {acl['Name']}")
|
||||
print(f" ARN: {acl['ARN']}")
|
||||
print(f" Default Action: {list(acl['DefaultAction'].keys())[0]}")
|
||||
print(f" Rules: {len(acl.get('Rules', []))}")
|
||||
for rule in acl.get("Rules", []):
|
||||
action = list(rule.get("Action", rule.get("OverrideAction", {})).keys())[0]
|
||||
print(f" [{rule['Priority']}] {rule['Name']} -> {action}")
|
||||
return acl, lock_token
|
||||
|
||||
|
||||
def check_waf_association(client, web_acl_arn):
|
||||
"""Check which resources are associated with a Web ACL."""
|
||||
resource_types = ["API_GATEWAY", "APPLICATION_LOAD_BALANCER", "APPSYNC", "COGNITO_USER_POOL"]
|
||||
associations = []
|
||||
for rt in resource_types:
|
||||
try:
|
||||
resp = client.list_resources_for_web_acl(WebACLArn=web_acl_arn, ResourceType=rt)
|
||||
for arn in resp.get("ResourceArns", []):
|
||||
associations.append({"type": rt, "arn": arn})
|
||||
print(f" [+] Associated: {rt} -> {arn}")
|
||||
except client.exceptions.WAFInvalidParameterException:
|
||||
continue
|
||||
if not associations:
|
||||
print(" [-] No resources associated with this Web ACL")
|
||||
return associations
|
||||
|
||||
|
||||
def get_sampled_requests(client, web_acl_arn, rule_metric, scope="REGIONAL", minutes=60):
|
||||
"""Get sampled requests for a specific rule to analyze blocks."""
|
||||
end_time = datetime.now(timezone.utc)
|
||||
start_time = end_time - timedelta(minutes=minutes)
|
||||
try:
|
||||
response = client.get_sampled_requests(
|
||||
WebAclArn=web_acl_arn, RuleMetricName=rule_metric, Scope=scope,
|
||||
TimeWindow={"StartTime": start_time, "EndTime": end_time}, MaxItems=50,
|
||||
)
|
||||
samples = response.get("SampledRequests", [])
|
||||
print(f"\n[*] Sampled requests for rule '{rule_metric}': {len(samples)}")
|
||||
for s in samples[:10]:
|
||||
req = s["Request"]
|
||||
print(f" [{s.get('Action', '?')}] {req['Method']} {req.get('URI', '/')} "
|
||||
f"from {req.get('ClientIP', '?')} at {s.get('Timestamp', '?')}")
|
||||
return samples
|
||||
except Exception as e:
|
||||
print(f" [-] Error getting samples: {e}")
|
||||
return []
|
||||
|
||||
|
||||
def get_rate_based_keys(client, name, acl_id, rule_name, scope="REGIONAL"):
|
||||
"""Get IPs currently rate-limited by a rate-based rule."""
|
||||
try:
|
||||
response = client.get_rate_based_statement_managed_keys(
|
||||
Scope=scope, WebACLName=name, WebACLId=acl_id, RuleName=rule_name,
|
||||
)
|
||||
keys = response.get("ManagedKeysIPV4", {}).get("Addresses", [])
|
||||
keys += response.get("ManagedKeysIPV6", {}).get("Addresses", [])
|
||||
print(f"\n[*] Rate-limited IPs for rule '{rule_name}': {len(keys)}")
|
||||
for ip in keys:
|
||||
print(f" [!] {ip}")
|
||||
return keys
|
||||
except Exception as e:
|
||||
print(f" [-] Error: {e}")
|
||||
return []
|
||||
|
||||
|
||||
def get_waf_metrics(region="us-east-1", acl_name="api-gateway-waf", hours=24):
|
||||
"""Get WAF CloudWatch metrics for blocked and allowed requests."""
|
||||
cw = boto3.client("cloudwatch", region_name=region)
|
||||
end_time = datetime.now(timezone.utc)
|
||||
start_time = end_time - timedelta(hours=hours)
|
||||
metrics = {}
|
||||
for metric_name in ["AllowedRequests", "BlockedRequests"]:
|
||||
response = cw.get_metric_statistics(
|
||||
Namespace="AWS/WAFV2", MetricName=metric_name,
|
||||
Dimensions=[{"Name": "WebACL", "Value": acl_name}, {"Name": "Rule", "Value": "ALL"}],
|
||||
StartTime=start_time, EndTime=end_time, Period=3600, Statistics=["Sum"],
|
||||
)
|
||||
total = sum(dp["Sum"] for dp in response.get("Datapoints", []))
|
||||
metrics[metric_name] = total
|
||||
print(f" {metric_name}: {int(total):,}")
|
||||
return metrics
|
||||
|
||||
|
||||
def audit_web_acl(client, name, acl_id, scope="REGIONAL"):
|
||||
"""Run a security audit on a Web ACL configuration."""
|
||||
acl, _ = get_web_acl_details(client, name, acl_id, scope)
|
||||
findings = []
|
||||
rules = acl.get("Rules", [])
|
||||
rule_names = [r["Name"] for r in rules]
|
||||
recommended = ["AWSManagedRulesCommonRuleSet", "AWSManagedRulesKnownBadInputsRuleSet",
|
||||
"AWSManagedRulesSQLiRuleSet", "AWSManagedRulesAmazonIpReputationList"]
|
||||
for rec in recommended:
|
||||
if not any(rec in rn for rn in rule_names):
|
||||
findings.append(f"MISSING: Recommended managed rule group '{rec}' not found")
|
||||
has_rate_rule = any("RateBasedStatement" in json.dumps(r.get("Statement", {})) for r in rules)
|
||||
if not has_rate_rule:
|
||||
findings.append("MISSING: No rate-based rule configured")
|
||||
default_action = list(acl["DefaultAction"].keys())[0]
|
||||
if default_action == "Allow":
|
||||
print(" [INFO] Default action is Allow (standard for WAF)")
|
||||
print(f"\n[*] Audit findings: {len(findings)}")
|
||||
for f in findings:
|
||||
print(f" [!] {f}")
|
||||
return findings
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="AWS WAF API Gateway Security Agent")
|
||||
parser.add_argument("action", choices=["list", "details", "audit", "metrics", "samples", "rate-keys"])
|
||||
parser.add_argument("--name", help="Web ACL name")
|
||||
parser.add_argument("--id", help="Web ACL ID")
|
||||
parser.add_argument("--region", default="us-east-1")
|
||||
parser.add_argument("--rule-metric", help="Rule metric name for sampling")
|
||||
parser.add_argument("--rule-name", help="Rate-based rule name")
|
||||
parser.add_argument("--hours", type=int, default=24, help="Lookback hours for metrics")
|
||||
args = parser.parse_args()
|
||||
|
||||
client = get_waf_client(args.region)
|
||||
|
||||
if args.action == "list":
|
||||
list_web_acls(client)
|
||||
elif args.action == "details":
|
||||
acl, _ = get_web_acl_details(client, args.name, args.id)
|
||||
check_waf_association(client, acl["ARN"])
|
||||
elif args.action == "audit":
|
||||
audit_web_acl(client, args.name, args.id)
|
||||
elif args.action == "metrics":
|
||||
get_waf_metrics(args.region, args.name or "api-gateway-waf", args.hours)
|
||||
elif args.action == "samples":
|
||||
acls = list_web_acls(client)
|
||||
acl_arn = next((a["ARN"] for a in acls if a["Name"] == args.name), None)
|
||||
if acl_arn:
|
||||
get_sampled_requests(client, acl_arn, args.rule_metric or "ALL")
|
||||
elif args.action == "rate-keys":
|
||||
get_rate_based_keys(client, args.name, args.id, args.rule_name or "RateLimitPerIP")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user