mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 21:54:56 +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
159 lines
6.3 KiB
Python
159 lines
6.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Agent for building cloud security posture management across AWS/Azure/GCP."""
|
|
|
|
import os
|
|
import json
|
|
import argparse
|
|
from datetime import datetime
|
|
|
|
import boto3
|
|
from botocore.exceptions import ClientError
|
|
|
|
|
|
def check_s3_public_buckets(session):
|
|
"""Check for publicly accessible S3 buckets."""
|
|
s3 = session.client("s3")
|
|
buckets = s3.list_buckets()["Buckets"]
|
|
findings = []
|
|
for b in buckets:
|
|
name = b["Name"]
|
|
try:
|
|
pab = s3.get_public_access_block(Bucket=name)
|
|
config = pab["PublicAccessBlockConfiguration"]
|
|
if not all([config.get("BlockPublicAcls"), config.get("IgnorePublicAcls"),
|
|
config.get("BlockPublicPolicy"), config.get("RestrictPublicBuckets")]):
|
|
findings.append({"bucket": name, "issue": "Incomplete public access block", "severity": "HIGH"})
|
|
except ClientError:
|
|
findings.append({"bucket": name, "issue": "No public access block configured", "severity": "HIGH"})
|
|
return findings
|
|
|
|
|
|
def check_unencrypted_ebs(session):
|
|
"""Check for unencrypted EBS volumes."""
|
|
ec2 = session.client("ec2")
|
|
volumes = ec2.describe_volumes()["Volumes"]
|
|
unencrypted = [
|
|
{"volume_id": v["VolumeId"], "state": v["State"], "size_gb": v["Size"]}
|
|
for v in volumes if not v.get("Encrypted")
|
|
]
|
|
return unencrypted
|
|
|
|
|
|
def check_public_security_groups(session):
|
|
"""Check for security groups allowing unrestricted inbound access."""
|
|
ec2 = session.client("ec2")
|
|
sgs = ec2.describe_security_groups()["SecurityGroups"]
|
|
findings = []
|
|
dangerous_ports = [22, 3389, 3306, 5432, 1433, 27017]
|
|
for sg in sgs:
|
|
for rule in sg.get("IpPermissions", []):
|
|
for ip_range in rule.get("IpRanges", []):
|
|
if ip_range.get("CidrIp") == "0.0.0.0/0":
|
|
from_port = rule.get("FromPort", 0)
|
|
to_port = rule.get("ToPort", 65535)
|
|
severity = "CRITICAL" if any(from_port <= p <= to_port for p in dangerous_ports) else "HIGH"
|
|
findings.append({
|
|
"sg_id": sg["GroupId"],
|
|
"sg_name": sg.get("GroupName"),
|
|
"port_range": f"{from_port}-{to_port}",
|
|
"source": "0.0.0.0/0",
|
|
"severity": severity,
|
|
})
|
|
return findings
|
|
|
|
|
|
def check_iam_users_without_mfa(session):
|
|
"""Check for IAM users without MFA enabled."""
|
|
iam = session.client("iam")
|
|
users = iam.list_users()["Users"]
|
|
no_mfa = []
|
|
for user in users:
|
|
mfa_devices = iam.list_mfa_devices(UserName=user["UserName"])["MFADevices"]
|
|
if not mfa_devices:
|
|
no_mfa.append({"username": user["UserName"], "created": str(user["CreateDate"])})
|
|
return no_mfa
|
|
|
|
|
|
def check_rds_public_access(session):
|
|
"""Check for RDS instances with public accessibility."""
|
|
rds = session.client("rds")
|
|
instances = rds.describe_db_instances()["DBInstances"]
|
|
public = [
|
|
{"instance": db["DBInstanceIdentifier"], "engine": db["Engine"], "endpoint": db.get("Endpoint", {}).get("Address", "")}
|
|
for db in instances if db.get("PubliclyAccessible")
|
|
]
|
|
return public
|
|
|
|
|
|
def check_cloudtrail_enabled(session):
|
|
"""Check if CloudTrail is enabled with multi-region logging."""
|
|
ct = session.client("cloudtrail")
|
|
trails = ct.describe_trails()["trailList"]
|
|
multiregion = [t for t in trails if t.get("IsMultiRegionTrail")]
|
|
if not multiregion:
|
|
return {"status": "FAIL", "detail": "No multi-region CloudTrail found"}
|
|
return {"status": "PASS", "trails": len(multiregion)}
|
|
|
|
|
|
def calculate_posture_score(findings_summary):
|
|
"""Calculate an overall security posture score."""
|
|
total_checks = sum(findings_summary.values())
|
|
if total_checks == 0:
|
|
return 100
|
|
critical = findings_summary.get("critical", 0)
|
|
high = findings_summary.get("high", 0)
|
|
medium = findings_summary.get("medium", 0)
|
|
deductions = (critical * 15) + (high * 8) + (medium * 3)
|
|
return max(0, 100 - deductions)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Cloud Security Posture Management Agent")
|
|
parser.add_argument("--profile", default=os.getenv("AWS_PROFILE"))
|
|
parser.add_argument("--region", default=os.getenv("AWS_DEFAULT_REGION", "us-east-1"))
|
|
parser.add_argument("--output", default="cspm_report.json")
|
|
args = parser.parse_args()
|
|
|
|
session = boto3.Session(profile_name=args.profile, region_name=args.region)
|
|
account = session.client("sts").get_caller_identity()["Account"]
|
|
print(f"[+] CSPM scan for account {account}")
|
|
|
|
report = {"account": account, "scan_date": datetime.utcnow().isoformat(), "findings": {}}
|
|
|
|
print("[+] Checking S3 bucket public access...")
|
|
report["findings"]["s3_public"] = check_s3_public_buckets(session)
|
|
print(f" Issues: {len(report['findings']['s3_public'])}")
|
|
|
|
print("[+] Checking unencrypted EBS volumes...")
|
|
report["findings"]["unencrypted_ebs"] = check_unencrypted_ebs(session)
|
|
print(f" Unencrypted: {len(report['findings']['unencrypted_ebs'])}")
|
|
|
|
print("[+] Checking public security groups...")
|
|
report["findings"]["public_sgs"] = check_public_security_groups(session)
|
|
print(f" Open rules: {len(report['findings']['public_sgs'])}")
|
|
|
|
print("[+] Checking IAM users without MFA...")
|
|
report["findings"]["no_mfa_users"] = check_iam_users_without_mfa(session)
|
|
print(f" Without MFA: {len(report['findings']['no_mfa_users'])}")
|
|
|
|
print("[+] Checking public RDS instances...")
|
|
report["findings"]["public_rds"] = check_rds_public_access(session)
|
|
print(f" Public: {len(report['findings']['public_rds'])}")
|
|
|
|
print("[+] Checking CloudTrail...")
|
|
report["findings"]["cloudtrail"] = check_cloudtrail_enabled(session)
|
|
|
|
critical = sum(1 for f in report["findings"].get("public_sgs", []) if f.get("severity") == "CRITICAL")
|
|
high = len(report["findings"]["s3_public"]) + len(report["findings"]["no_mfa_users"])
|
|
medium = len(report["findings"]["unencrypted_ebs"])
|
|
report["posture_score"] = calculate_posture_score({"critical": critical, "high": high, "medium": medium})
|
|
print(f"\n[+] Posture Score: {report['posture_score']}/100")
|
|
|
|
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()
|