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:
mukul975
2026-03-10 21:02:12 +01:00
parent c74d52fa30
commit 27c6414ca5
1390 changed files with 106806 additions and 0 deletions
@@ -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,59 @@
# API Reference: OAuth Misconfiguration Assessment Agent
## Dependencies
| Library | Version | Purpose |
|---------|---------|---------|
| requests | >=2.28 | HTTP client for OAuth flow testing |
## CLI Usage
```bash
python scripts/agent.py \
--url https://auth.example.com \
--client-id APP_CLIENT_ID \
--redirect-uri https://app.example.com/callback \
--output oauth_report.json
```
## Functions
### `discover_oidc_config(base_url) -> dict`
Fetches `/.well-known/openid-configuration` or `/.well-known/oauth-authorization-server`.
### `test_redirect_uri_bypasses(auth_endpoint, client_id, legitimate_uri) -> list`
Tests 10 redirect_uri manipulation techniques: subdomain hijack, path traversal, case variation, protocol downgrade, CRLF injection.
### `test_state_parameter(auth_endpoint, client_id, redirect_uri) -> dict`
Submits authorization request without `state` to check CSRF protection.
### `test_pkce_requirement(auth_endpoint, client_id, redirect_uri) -> dict`
Tests whether `code_challenge` parameter is required. Generates S256 challenge for comparison.
### `test_code_reuse(token_endpoint, auth_code, client_id, client_secret, redirect_uri) -> dict`
Exchanges an authorization code twice to check single-use enforcement.
### `test_scope_escalation(auth_endpoint, client_id, redirect_uri) -> dict`
Requests elevated scopes (`admin`, `write`, `delete`) to test scope validation.
### `run_assessment(config, client_id, redirect_uri) -> dict`
Orchestrates all tests and compiles findings.
## OAuth Endpoints Tested
| Endpoint | Source | Test |
|----------|--------|------|
| `authorization_endpoint` | OIDC config | Redirect URI, state, PKCE, scope |
| `token_endpoint` | OIDC config | Code reuse, scope escalation |
## Output Schema
```json
{
"oidc_config": {"authorization_endpoint": "...", "token_endpoint": "..."},
"redirect_uri_tests": [{"redirect_uri": "https://evil.com", "accepted": false}],
"state_parameter": {"csrf_risk": false},
"pkce": {"pkce_required": true},
"findings": []
}
```
@@ -0,0 +1,232 @@
#!/usr/bin/env python3
# For authorized testing in lab/CTF environments only
"""OAuth 2.0 misconfiguration detection agent for testing redirect URI, state, and PKCE."""
import argparse
import json
import logging
import sys
import urllib.parse
from typing import List
try:
import requests
except ImportError:
sys.exit("requests is required: pip install requests")
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
def discover_oidc_config(base_url: str) -> dict:
"""Discover OpenID Connect / OAuth configuration endpoints."""
endpoints = [
"/.well-known/openid-configuration",
"/.well-known/oauth-authorization-server",
]
for ep in endpoints:
try:
resp = requests.get(f"{base_url}{ep}", timeout=10, verify=False)
if resp.status_code == 200:
config = resp.json()
logger.info("OIDC config found at %s%s", base_url, ep)
return config
except (requests.RequestException, ValueError):
continue
logger.warning("No OIDC configuration endpoint found")
return {}
def test_redirect_uri_bypasses(auth_endpoint: str, client_id: str,
legitimate_uri: str) -> List[dict]:
"""Test redirect_uri validation with common bypass techniques."""
parsed = urllib.parse.urlparse(legitimate_uri)
domain = parsed.netloc
bypass_uris = [
"https://evil.com",
f"https://{domain}.evil.com/callback",
f"https://{domain}@evil.com/callback",
f"https://evil.com/.{domain}",
f"https://{domain}/callback/../../../evil.com",
f"https://{domain}/callback?next=https://evil.com",
f"https://{domain.upper()}/callback",
f"http://{domain}/callback",
f"https://{domain}/CALLBACK",
f"https://{domain}/callback%0d%0aLocation:https://evil.com",
]
results = []
for uri in bypass_uris:
params = {
"response_type": "code",
"client_id": client_id,
"redirect_uri": uri,
"scope": "openid",
"state": "test123",
}
try:
resp = requests.get(auth_endpoint, params=params, timeout=10,
allow_redirects=False, verify=False)
accepted = resp.status_code in (302, 301, 200)
location = resp.headers.get("Location", "")
results.append({
"redirect_uri": uri,
"status_code": resp.status_code,
"accepted": accepted,
"redirected_to": location[:120] if location else "",
})
if accepted:
logger.warning("Redirect URI bypass accepted: %s", uri)
except requests.RequestException as exc:
results.append({"redirect_uri": uri, "error": str(exc)})
return results
def test_state_parameter(auth_endpoint: str, client_id: str,
redirect_uri: str) -> dict:
"""Test if the state parameter is required and validated."""
params = {
"response_type": "code",
"client_id": client_id,
"redirect_uri": redirect_uri,
"scope": "openid",
}
resp = requests.get(auth_endpoint, params=params, timeout=10,
allow_redirects=False, verify=False)
no_state_accepted = resp.status_code in (302, 301, 200)
params["state"] = "aaaa"
resp2 = requests.get(auth_endpoint, params=params, timeout=10,
allow_redirects=False, verify=False)
return {
"state_required": not no_state_accepted,
"no_state_status": resp.status_code,
"predictable_state_status": resp2.status_code,
"csrf_risk": no_state_accepted,
}
def test_pkce_requirement(auth_endpoint: str, client_id: str,
redirect_uri: str) -> dict:
"""Test if PKCE (code_challenge) is required."""
params = {
"response_type": "code",
"client_id": client_id,
"redirect_uri": redirect_uri,
"scope": "openid",
"state": "pkce_test",
}
resp_no_pkce = requests.get(auth_endpoint, params=params, timeout=10,
allow_redirects=False, verify=False)
import hashlib, base64, os
verifier = base64.urlsafe_b64encode(os.urandom(32)).rstrip(b"=").decode()
challenge = base64.urlsafe_b64encode(
hashlib.sha256(verifier.encode()).digest()
).rstrip(b"=").decode()
params["code_challenge"] = challenge
params["code_challenge_method"] = "S256"
resp_with_pkce = requests.get(auth_endpoint, params=params, timeout=10,
allow_redirects=False, verify=False)
return {
"pkce_required": resp_no_pkce.status_code >= 400,
"without_pkce_status": resp_no_pkce.status_code,
"with_pkce_status": resp_with_pkce.status_code,
"risk": "HIGH" if resp_no_pkce.status_code < 400 else "LOW",
}
def test_code_reuse(token_endpoint: str, auth_code: str, client_id: str,
client_secret: str, redirect_uri: str) -> dict:
"""Test if authorization codes can be reused."""
data = {
"grant_type": "authorization_code",
"code": auth_code,
"redirect_uri": redirect_uri,
"client_id": client_id,
"client_secret": client_secret,
}
resp1 = requests.post(token_endpoint, data=data, timeout=10, verify=False)
resp2 = requests.post(token_endpoint, data=data, timeout=10, verify=False)
return {
"first_exchange_status": resp1.status_code,
"second_exchange_status": resp2.status_code,
"code_reusable": resp2.status_code == 200,
"risk": "MEDIUM" if resp2.status_code == 200 else "LOW",
}
def test_scope_escalation(auth_endpoint: str, client_id: str,
redirect_uri: str) -> dict:
"""Test if additional scopes beyond authorization can be requested."""
elevated_scopes = "openid profile email admin write delete"
params = {
"response_type": "code",
"client_id": client_id,
"redirect_uri": redirect_uri,
"scope": elevated_scopes,
"state": "scope_test",
}
resp = requests.get(auth_endpoint, params=params, timeout=10,
allow_redirects=False, verify=False)
return {
"requested_scopes": elevated_scopes,
"status_code": resp.status_code,
"accepted": resp.status_code in (302, 301, 200),
}
def run_assessment(config: dict, client_id: str, redirect_uri: str) -> dict:
"""Run the full OAuth security assessment."""
auth_ep = config.get("authorization_endpoint", "")
findings = []
redirect_tests = test_redirect_uri_bypasses(auth_ep, client_id, redirect_uri) if auth_ep else []
bypasses = [t for t in redirect_tests if t.get("accepted")]
if bypasses:
findings.append(f"HIGH: {len(bypasses)} redirect_uri bypass(es) accepted")
state_test = test_state_parameter(auth_ep, client_id, redirect_uri) if auth_ep else {}
if state_test.get("csrf_risk"):
findings.append("MEDIUM: State parameter not required (CSRF risk)")
pkce_test = test_pkce_requirement(auth_ep, client_id, redirect_uri) if auth_ep else {}
if not pkce_test.get("pkce_required", True):
findings.append("HIGH: PKCE not required")
scope_test = test_scope_escalation(auth_ep, client_id, redirect_uri) if auth_ep else {}
return {
"oidc_config": config,
"redirect_uri_tests": redirect_tests,
"state_parameter": state_test,
"pkce": pkce_test,
"scope_escalation": scope_test,
"findings": findings,
}
def main():
parser = argparse.ArgumentParser(description="OAuth Misconfiguration Assessment Agent")
parser.add_argument("--url", required=True, help="OAuth provider base URL")
parser.add_argument("--client-id", required=True, help="OAuth client ID")
parser.add_argument("--redirect-uri", required=True, help="Legitimate redirect URI")
parser.add_argument("--output", default="oauth_report.json")
args = parser.parse_args()
config = discover_oidc_config(args.url)
report = run_assessment(config, args.client_id, args.redirect_uri)
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
logger.info("Report saved to %s", args.output)
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()