mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-06 07:48:57 +03:00
27c6414ca5
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
209 lines
7.5 KiB
Python
209 lines
7.5 KiB
Python
#!/usr/bin/env python3
|
|
"""S3 bucket misconfiguration remediation agent using boto3."""
|
|
|
|
import json
|
|
import sys
|
|
|
|
try:
|
|
import boto3
|
|
from botocore.exceptions import ClientError
|
|
except ImportError:
|
|
print("Install: pip install boto3")
|
|
sys.exit(1)
|
|
|
|
|
|
def get_s3_client(region="us-east-1"):
|
|
return boto3.client("s3", region_name=region)
|
|
|
|
|
|
def list_all_buckets(s3):
|
|
"""List all S3 buckets in the account."""
|
|
resp = s3.list_buckets()
|
|
return [b["Name"] for b in resp.get("Buckets", [])]
|
|
|
|
|
|
def check_public_access_block(s3, bucket):
|
|
"""Check if S3 Block Public Access is enabled."""
|
|
try:
|
|
config = s3.get_public_access_block(Bucket=bucket)
|
|
block = config["PublicAccessBlockConfiguration"]
|
|
all_blocked = all([
|
|
block.get("BlockPublicAcls", False),
|
|
block.get("IgnorePublicAcls", False),
|
|
block.get("BlockPublicPolicy", False),
|
|
block.get("RestrictPublicBuckets", False),
|
|
])
|
|
return {"bucket": bucket, "block_config": block, "fully_blocked": all_blocked}
|
|
except ClientError as e:
|
|
if e.response["Error"]["Code"] == "NoSuchPublicAccessBlockConfiguration":
|
|
return {"bucket": bucket, "block_config": None, "fully_blocked": False}
|
|
raise
|
|
|
|
|
|
def check_bucket_policy(s3, bucket):
|
|
"""Check bucket policy for public access grants."""
|
|
try:
|
|
policy = json.loads(s3.get_bucket_policy(Bucket=bucket)["Policy"])
|
|
findings = []
|
|
for stmt in policy.get("Statement", []):
|
|
principal = stmt.get("Principal", {})
|
|
effect = stmt.get("Effect", "")
|
|
if principal == "*" or principal == {"AWS": "*"}:
|
|
if effect == "Allow":
|
|
findings.append({
|
|
"sid": stmt.get("Sid", "unnamed"),
|
|
"effect": effect,
|
|
"principal": str(principal),
|
|
"action": stmt.get("Action"),
|
|
"risk": "CRITICAL",
|
|
})
|
|
return {"bucket": bucket, "has_policy": True, "public_statements": findings}
|
|
except ClientError as e:
|
|
if e.response["Error"]["Code"] == "NoSuchBucketPolicy":
|
|
return {"bucket": bucket, "has_policy": False, "public_statements": []}
|
|
raise
|
|
|
|
|
|
def check_bucket_acl(s3, bucket):
|
|
"""Check bucket ACL for public grants."""
|
|
acl = s3.get_bucket_acl(Bucket=bucket)
|
|
public_grants = []
|
|
for grant in acl.get("Grants", []):
|
|
grantee = grant.get("Grantee", {})
|
|
uri = grantee.get("URI", "")
|
|
if "AllUsers" in uri or "AuthenticatedUsers" in uri:
|
|
public_grants.append({
|
|
"grantee": uri,
|
|
"permission": grant.get("Permission"),
|
|
"risk": "CRITICAL" if grant.get("Permission") in ("FULL_CONTROL", "WRITE") else "HIGH",
|
|
})
|
|
return {"bucket": bucket, "public_grants": public_grants}
|
|
|
|
|
|
def check_encryption(s3, bucket):
|
|
"""Check if default encryption is enabled."""
|
|
try:
|
|
config = s3.get_bucket_encryption(Bucket=bucket)
|
|
rules = config.get("ServerSideEncryptionConfiguration", {}).get("Rules", [])
|
|
encryption = None
|
|
for rule in rules:
|
|
sse = rule.get("ApplyServerSideEncryptionByDefault", {})
|
|
encryption = sse.get("SSEAlgorithm")
|
|
return {"bucket": bucket, "encrypted": True, "algorithm": encryption}
|
|
except ClientError as e:
|
|
if e.response["Error"]["Code"] == "ServerSideEncryptionConfigurationNotFoundError":
|
|
return {"bucket": bucket, "encrypted": False, "algorithm": None}
|
|
raise
|
|
|
|
|
|
def check_versioning(s3, bucket):
|
|
"""Check if versioning is enabled."""
|
|
resp = s3.get_bucket_versioning(Bucket=bucket)
|
|
return {
|
|
"bucket": bucket,
|
|
"status": resp.get("Status", "Disabled"),
|
|
"mfa_delete": resp.get("MFADelete", "Disabled"),
|
|
}
|
|
|
|
|
|
def check_logging(s3, bucket):
|
|
"""Check if access logging is enabled."""
|
|
resp = s3.get_bucket_logging(Bucket=bucket)
|
|
logging_config = resp.get("LoggingEnabled")
|
|
return {
|
|
"bucket": bucket,
|
|
"logging_enabled": logging_config is not None,
|
|
"target_bucket": logging_config.get("TargetBucket") if logging_config else None,
|
|
}
|
|
|
|
|
|
def enable_public_access_block(s3, bucket):
|
|
"""Enable S3 Block Public Access on a bucket."""
|
|
s3.put_public_access_block(
|
|
Bucket=bucket,
|
|
PublicAccessBlockConfiguration={
|
|
"BlockPublicAcls": True,
|
|
"IgnorePublicAcls": True,
|
|
"BlockPublicPolicy": True,
|
|
"RestrictPublicBuckets": True,
|
|
},
|
|
)
|
|
return {"bucket": bucket, "action": "block_public_access", "status": "applied"}
|
|
|
|
|
|
def enable_encryption(s3, bucket, algorithm="aws:kms"):
|
|
"""Enable default encryption on a bucket."""
|
|
config = {
|
|
"Rules": [{
|
|
"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": algorithm},
|
|
"BucketKeyEnabled": True,
|
|
}]
|
|
}
|
|
s3.put_bucket_encryption(
|
|
Bucket=bucket,
|
|
ServerSideEncryptionConfiguration=config,
|
|
)
|
|
return {"bucket": bucket, "action": "enable_encryption", "algorithm": algorithm}
|
|
|
|
|
|
def enable_versioning(s3, bucket):
|
|
"""Enable versioning on a bucket."""
|
|
s3.put_bucket_versioning(
|
|
Bucket=bucket,
|
|
VersioningConfiguration={"Status": "Enabled"},
|
|
)
|
|
return {"bucket": bucket, "action": "enable_versioning", "status": "Enabled"}
|
|
|
|
|
|
def audit_all_buckets(s3):
|
|
"""Run full security audit across all buckets."""
|
|
buckets = list_all_buckets(s3)
|
|
results = []
|
|
for bucket in buckets:
|
|
finding = {"bucket": bucket, "issues": []}
|
|
pab = check_public_access_block(s3, bucket)
|
|
if not pab["fully_blocked"]:
|
|
finding["issues"].append("Public access block not fully enabled")
|
|
policy = check_bucket_policy(s3, bucket)
|
|
if policy["public_statements"]:
|
|
finding["issues"].append(f"{len(policy['public_statements'])} public policy statement(s)")
|
|
acl = check_bucket_acl(s3, bucket)
|
|
if acl["public_grants"]:
|
|
finding["issues"].append(f"{len(acl['public_grants'])} public ACL grant(s)")
|
|
enc = check_encryption(s3, bucket)
|
|
if not enc["encrypted"]:
|
|
finding["issues"].append("No default encryption")
|
|
ver = check_versioning(s3, bucket)
|
|
if ver["status"] != "Enabled":
|
|
finding["issues"].append("Versioning disabled")
|
|
log = check_logging(s3, bucket)
|
|
if not log["logging_enabled"]:
|
|
finding["issues"].append("Access logging disabled")
|
|
finding["issue_count"] = len(finding["issues"])
|
|
finding["risk"] = "CRITICAL" if any("public" in i.lower() for i in finding["issues"]) else (
|
|
"HIGH" if finding["issue_count"] >= 3 else "MEDIUM" if finding["issue_count"] >= 1 else "LOW"
|
|
)
|
|
results.append(finding)
|
|
return sorted(results, key=lambda x: -x["issue_count"])
|
|
|
|
|
|
def print_audit_report(results):
|
|
print("S3 Bucket Security Audit Report")
|
|
print("=" * 50)
|
|
print(f"Buckets Audited: {len(results)}")
|
|
critical = sum(1 for r in results if r["risk"] == "CRITICAL")
|
|
print(f"Critical: {critical}")
|
|
for r in results:
|
|
if r["issue_count"] == 0:
|
|
continue
|
|
print(f"\n[{r['risk']}] {r['bucket']} ({r['issue_count']} issues)")
|
|
for issue in r["issues"]:
|
|
print(f" - {issue}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
region = sys.argv[1] if len(sys.argv) > 1 else "us-east-1"
|
|
s3 = get_s3_client(region)
|
|
results = audit_all_buckets(s3)
|
|
print_audit_report(results)
|