mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-19 05:59:40 +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,47 @@
|
||||
# API Reference: CyberArk Zero Standing Privilege
|
||||
|
||||
## CyberArk PVWA REST API v2
|
||||
|
||||
### Authentication
|
||||
```python
|
||||
POST /api/auth/CyberArk/Logon
|
||||
Body: {"username": "admin", "password": "pass"}
|
||||
Returns: Session token string
|
||||
```
|
||||
|
||||
### Key Endpoints
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| GET | `/api/Safes` | List all safes |
|
||||
| GET | `/api/Safes/{name}/Members` | List safe members and permissions |
|
||||
| GET | `/api/Platforms` | List configured platforms |
|
||||
| GET | `/api/Accounts` | List privileged accounts |
|
||||
| GET | `/api/LiveSessions` | List active privileged sessions |
|
||||
| POST | `/api/Accounts/{id}/CheckIn` | Release exclusive account access |
|
||||
|
||||
### Safe Member Permissions
|
||||
| Permission | ZSP Implication |
|
||||
|------------|----------------|
|
||||
| `useAccounts` | Can initiate privileged sessions |
|
||||
| `retrieveAccounts` | Can retrieve passwords |
|
||||
| `listAccounts` | Can see account inventory |
|
||||
| `requestsAuthorizationLevel1` | Dual-control approval required |
|
||||
|
||||
### Session Properties
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `User` | Session initiator |
|
||||
| `AccountName` | Target privileged account |
|
||||
| `Duration` | Session length in seconds |
|
||||
| `RemoteMachine` | Target host |
|
||||
|
||||
## TEA Framework
|
||||
| Component | API Field | Purpose |
|
||||
|-----------|-----------|---------|
|
||||
| Time | `MaxSessionDuration` | Auto-revoke after timeout |
|
||||
| Entitlements | `AllowedPermissions` | Scoped access per session |
|
||||
| Approvals | `requestsAuthorizationLevel` | Require approval workflow |
|
||||
|
||||
## References
|
||||
- CyberArk REST API: https://docs.cyberark.com/pam-self-hosted/latest/en/Content/SDK/CyberArk%20REST%20API.htm
|
||||
- CyberArk Secure Cloud Access: https://docs.cyberark.com/secure-cloud-access/
|
||||
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for auditing CyberArk Zero Standing Privilege (ZSP) configuration via REST API."""
|
||||
|
||||
import requests
|
||||
import json
|
||||
import argparse
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
import urllib3
|
||||
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
|
||||
|
||||
def authenticate(base_url, username, password, auth_method="CyberArk"):
|
||||
"""Authenticate to CyberArk PVWA and obtain session token."""
|
||||
url = f"{base_url}/api/auth/{auth_method}/Logon"
|
||||
payload = {"username": username, "password": password}
|
||||
resp = requests.post(url, json=payload, verify=False, timeout=30)
|
||||
resp.raise_for_status()
|
||||
token = resp.json().strip('"')
|
||||
print(f"[*] Authenticated to CyberArk PVWA as {username}")
|
||||
return {"Authorization": token}
|
||||
|
||||
|
||||
def list_safes(base_url, headers):
|
||||
"""List all safes to audit access policies."""
|
||||
url = f"{base_url}/api/Safes"
|
||||
resp = requests.get(url, headers=headers, verify=False, timeout=30)
|
||||
resp.raise_for_status()
|
||||
safes = resp.json().get("value", [])
|
||||
print(f"[*] Found {len(safes)} safes")
|
||||
for s in safes[:20]:
|
||||
print(f" {s['safeName']} (retention: {s.get('numberOfDaysRetention', 'N/A')} days)")
|
||||
return safes
|
||||
|
||||
|
||||
def audit_safe_members(base_url, headers, safe_name):
|
||||
"""Audit members and permissions of a specific safe."""
|
||||
url = f"{base_url}/api/Safes/{safe_name}/Members"
|
||||
resp = requests.get(url, headers=headers, verify=False, timeout=30)
|
||||
resp.raise_for_status()
|
||||
members = resp.json().get("value", [])
|
||||
findings = []
|
||||
for m in members:
|
||||
perms = m.get("permissions", {})
|
||||
if perms.get("useAccounts") and perms.get("retrieveAccounts"):
|
||||
if not m.get("memberType") == "Role":
|
||||
findings.append({
|
||||
"safe": safe_name, "member": m.get("memberName"),
|
||||
"issue": "Standing retrieve+use privileges (not JIT)",
|
||||
"severity": "HIGH",
|
||||
})
|
||||
print(f" [!] {m.get('memberName')} has standing access to {safe_name}")
|
||||
return findings
|
||||
|
||||
|
||||
def list_platforms(base_url, headers):
|
||||
"""List platforms to verify JIT/ZSP configuration."""
|
||||
url = f"{base_url}/api/Platforms"
|
||||
resp = requests.get(url, headers=headers, verify=False, timeout=30)
|
||||
resp.raise_for_status()
|
||||
platforms = resp.json().get("Platforms", [])
|
||||
print(f"[*] Found {len(platforms)} platforms")
|
||||
for p in platforms:
|
||||
print(f" {p.get('general', {}).get('name', 'Unknown')} - "
|
||||
f"Active: {p.get('general', {}).get('active', False)}")
|
||||
return platforms
|
||||
|
||||
|
||||
def check_jit_sessions(base_url, headers, days=7):
|
||||
"""Check recent privileged sessions for JIT compliance."""
|
||||
url = f"{base_url}/api/LiveSessions"
|
||||
resp = requests.get(url, headers=headers, verify=False, timeout=30)
|
||||
resp.raise_for_status()
|
||||
sessions = resp.json().get("LiveSessions", [])
|
||||
print(f"[*] Active privileged sessions: {len(sessions)}")
|
||||
long_sessions = []
|
||||
for s in sessions:
|
||||
duration = s.get("Duration", 0)
|
||||
if duration > 3600:
|
||||
long_sessions.append({
|
||||
"user": s.get("User"), "target": s.get("AccountName"),
|
||||
"duration_sec": duration, "severity": "MEDIUM",
|
||||
})
|
||||
print(f" [!] Long session: {s.get('User')} -> {s.get('AccountName')} "
|
||||
f"({duration // 60} min)")
|
||||
return long_sessions
|
||||
|
||||
|
||||
def audit_accounts_standing_access(base_url, headers):
|
||||
"""Find privileged accounts with standing (non-JIT) access enabled."""
|
||||
url = f"{base_url}/api/Accounts"
|
||||
params = {"limit": 100, "offset": 0}
|
||||
resp = requests.get(url, headers=headers, params=params, verify=False, timeout=30)
|
||||
resp.raise_for_status()
|
||||
accounts = resp.json().get("value", [])
|
||||
findings = []
|
||||
for a in accounts:
|
||||
props = a.get("platformAccountProperties", {})
|
||||
if not props.get("JITEnabled", False):
|
||||
findings.append({
|
||||
"account": a.get("name"), "safe": a.get("safeName"),
|
||||
"platform": a.get("platformId"), "issue": "JIT not enabled",
|
||||
"severity": "HIGH",
|
||||
})
|
||||
print(f"[*] Accounts without JIT: {len(findings)}/{len(accounts)}")
|
||||
return findings
|
||||
|
||||
|
||||
def generate_report(safe_findings, session_findings, account_findings, output_path):
|
||||
"""Generate ZSP compliance audit report."""
|
||||
report = {
|
||||
"audit_date": datetime.now(timezone.utc).isoformat(),
|
||||
"summary": {
|
||||
"standing_access_findings": len(safe_findings),
|
||||
"long_session_findings": len(session_findings),
|
||||
"non_jit_accounts": len(account_findings),
|
||||
},
|
||||
"safe_findings": safe_findings,
|
||||
"session_findings": session_findings,
|
||||
"account_findings": account_findings,
|
||||
}
|
||||
with open(output_path, "w") as f:
|
||||
json.dump(report, f, indent=2, default=str)
|
||||
print(f"\n[*] Report saved to {output_path}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="CyberArk Zero Standing Privilege Audit Agent")
|
||||
parser.add_argument("action", choices=["safes", "audit-safe", "platforms",
|
||||
"sessions", "accounts", "full-audit"])
|
||||
parser.add_argument("--url", required=True, help="CyberArk PVWA base URL")
|
||||
parser.add_argument("--username", required=True)
|
||||
parser.add_argument("--password", required=True)
|
||||
parser.add_argument("--safe", help="Specific safe name to audit")
|
||||
parser.add_argument("-o", "--output", default="zsp_audit.json")
|
||||
args = parser.parse_args()
|
||||
|
||||
headers = authenticate(args.url, args.username, args.password)
|
||||
if args.action == "safes":
|
||||
list_safes(args.url, headers)
|
||||
elif args.action == "audit-safe" and args.safe:
|
||||
audit_safe_members(args.url, headers, args.safe)
|
||||
elif args.action == "platforms":
|
||||
list_platforms(args.url, headers)
|
||||
elif args.action == "sessions":
|
||||
check_jit_sessions(args.url, headers)
|
||||
elif args.action == "accounts":
|
||||
audit_accounts_standing_access(args.url, headers)
|
||||
elif args.action == "full-audit":
|
||||
safes = list_safes(args.url, headers)
|
||||
sf = []
|
||||
for s in safes:
|
||||
sf.extend(audit_safe_members(args.url, headers, s["safeName"]))
|
||||
sess = check_jit_sessions(args.url, headers)
|
||||
acct = audit_accounts_standing_access(args.url, headers)
|
||||
generate_report(sf, sess, acct, args.output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user