mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-05 23:38: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
191 lines
6.5 KiB
Python
191 lines
6.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Agent for auditing AWS S3 bucket permissions using boto3."""
|
|
|
|
import os
|
|
import json
|
|
import argparse
|
|
from datetime import datetime
|
|
|
|
import boto3
|
|
from botocore.exceptions import ClientError
|
|
|
|
|
|
def get_session(profile=None, region=None):
|
|
"""Create a boto3 session."""
|
|
kwargs = {}
|
|
if profile:
|
|
kwargs["profile_name"] = profile
|
|
if region:
|
|
kwargs["region_name"] = region
|
|
return boto3.Session(**kwargs)
|
|
|
|
|
|
def list_all_buckets(session):
|
|
"""List all S3 buckets in the account."""
|
|
s3 = session.client("s3")
|
|
response = s3.list_buckets()
|
|
buckets = []
|
|
for b in response.get("Buckets", []):
|
|
loc = s3.get_bucket_location(Bucket=b["Name"])
|
|
region = loc.get("LocationConstraint") or "us-east-1"
|
|
buckets.append({"name": b["Name"], "created": str(b["CreationDate"]), "region": region})
|
|
return buckets
|
|
|
|
|
|
def check_public_access_block(session, bucket_name):
|
|
"""Check bucket-level public access block settings."""
|
|
s3 = session.client("s3")
|
|
try:
|
|
response = s3.get_public_access_block(Bucket=bucket_name)
|
|
config = response["PublicAccessBlockConfiguration"]
|
|
return {
|
|
"configured": True,
|
|
"block_public_acls": config.get("BlockPublicAcls", False),
|
|
"ignore_public_acls": config.get("IgnorePublicAcls", False),
|
|
"block_public_policy": config.get("BlockPublicPolicy", False),
|
|
"restrict_public_buckets": config.get("RestrictPublicBuckets", False),
|
|
}
|
|
except ClientError:
|
|
return {"configured": False}
|
|
|
|
|
|
def check_bucket_acl(session, bucket_name):
|
|
"""Check bucket ACL for public grants."""
|
|
s3 = session.client("s3")
|
|
acl = s3.get_bucket_acl(Bucket=bucket_name)
|
|
public_grants = []
|
|
public_uris = [
|
|
"http://acs.amazonaws.com/groups/global/AllUsers",
|
|
"http://acs.amazonaws.com/groups/global/AuthenticatedUsers",
|
|
]
|
|
for grant in acl.get("Grants", []):
|
|
grantee = grant.get("Grantee", {})
|
|
if grantee.get("URI") in public_uris:
|
|
public_grants.append({
|
|
"grantee": grantee.get("URI"),
|
|
"permission": grant.get("Permission"),
|
|
})
|
|
return public_grants
|
|
|
|
|
|
def check_bucket_policy(session, bucket_name):
|
|
"""Check bucket policy for wildcard principals."""
|
|
s3 = session.client("s3")
|
|
try:
|
|
policy_str = s3.get_bucket_policy(Bucket=bucket_name)["Policy"]
|
|
policy = json.loads(policy_str)
|
|
issues = []
|
|
for stmt in policy.get("Statement", []):
|
|
principal = stmt.get("Principal", {})
|
|
if principal == "*" or principal == {"AWS": "*"}:
|
|
issues.append({
|
|
"effect": stmt.get("Effect"),
|
|
"action": stmt.get("Action"),
|
|
"condition": stmt.get("Condition", "NONE"),
|
|
})
|
|
return {"has_policy": True, "wildcard_issues": issues}
|
|
except ClientError:
|
|
return {"has_policy": False, "wildcard_issues": []}
|
|
|
|
|
|
def check_encryption(session, bucket_name):
|
|
"""Check if default encryption is enabled."""
|
|
s3 = session.client("s3")
|
|
try:
|
|
enc = s3.get_bucket_encryption(Bucket=bucket_name)
|
|
rules = enc.get("ServerSideEncryptionConfiguration", {}).get("Rules", [])
|
|
if rules:
|
|
algo = rules[0].get("ApplyServerSideEncryptionByDefault", {}).get("SSEAlgorithm")
|
|
return {"enabled": True, "algorithm": algo}
|
|
except ClientError:
|
|
pass
|
|
return {"enabled": False, "algorithm": None}
|
|
|
|
|
|
def check_versioning(session, bucket_name):
|
|
"""Check if versioning is enabled."""
|
|
s3 = session.client("s3")
|
|
resp = s3.get_bucket_versioning(Bucket=bucket_name)
|
|
return {"status": resp.get("Status", "Disabled")}
|
|
|
|
|
|
def check_logging(session, bucket_name):
|
|
"""Check if server access logging is enabled."""
|
|
s3 = session.client("s3")
|
|
resp = s3.get_bucket_logging(Bucket=bucket_name)
|
|
enabled = "LoggingEnabled" in resp
|
|
return {"enabled": enabled}
|
|
|
|
|
|
def audit_bucket(session, bucket_name):
|
|
"""Run full security audit on a single bucket."""
|
|
return {
|
|
"bucket": bucket_name,
|
|
"public_access_block": check_public_access_block(session, bucket_name),
|
|
"public_acl_grants": check_bucket_acl(session, bucket_name),
|
|
"bucket_policy": check_bucket_policy(session, bucket_name),
|
|
"encryption": check_encryption(session, bucket_name),
|
|
"versioning": check_versioning(session, bucket_name),
|
|
"logging": check_logging(session, bucket_name),
|
|
}
|
|
|
|
|
|
def classify_risk(audit_result):
|
|
"""Classify risk level for a bucket based on audit findings."""
|
|
risk = "LOW"
|
|
if audit_result["public_acl_grants"]:
|
|
risk = "CRITICAL"
|
|
elif audit_result["bucket_policy"]["wildcard_issues"]:
|
|
risk = "HIGH"
|
|
elif not audit_result["encryption"]["enabled"]:
|
|
risk = "MEDIUM"
|
|
elif not audit_result["public_access_block"]["configured"]:
|
|
risk = "MEDIUM"
|
|
audit_result["risk_level"] = risk
|
|
return audit_result
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="AWS S3 Bucket Permissions Audit Agent")
|
|
parser.add_argument("--profile", default=os.getenv("AWS_PROFILE"))
|
|
parser.add_argument("--region", default=os.getenv("AWS_DEFAULT_REGION"))
|
|
parser.add_argument("--bucket", help="Audit a specific bucket")
|
|
parser.add_argument("--output", default="s3_audit_report.json")
|
|
args = parser.parse_args()
|
|
|
|
session = get_session(args.profile, args.region)
|
|
account_id = session.client("sts").get_caller_identity()["Account"]
|
|
print(f"[+] Auditing S3 buckets in account {account_id}")
|
|
|
|
if args.bucket:
|
|
buckets = [{"name": args.bucket}]
|
|
else:
|
|
buckets = list_all_buckets(session)
|
|
print(f"[+] Found {len(buckets)} buckets")
|
|
|
|
results = []
|
|
for b in buckets:
|
|
name = b["name"]
|
|
print(f" Auditing {name}...")
|
|
audit = audit_bucket(session, name)
|
|
audit = classify_risk(audit)
|
|
results.append(audit)
|
|
if audit["risk_level"] in ("CRITICAL", "HIGH"):
|
|
print(f" [{audit['risk_level']}] {name}")
|
|
|
|
report = {
|
|
"account": account_id,
|
|
"audit_date": datetime.utcnow().isoformat(),
|
|
"total_buckets": len(results),
|
|
"critical": sum(1 for r in results if r["risk_level"] == "CRITICAL"),
|
|
"high": sum(1 for r in results if r["risk_level"] == "HIGH"),
|
|
"buckets": results,
|
|
}
|
|
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()
|