Files
T
mukul975 c21af3347e Complete folder anatomy for all 649 cybersecurity skills + update LICENSE to Mahipal
- Add scripts/agent.py and references/api-reference.md to all remaining skills
- Update all 648 LICENSE files: copyright now reads 'Mahipal'
- Add implementing-security-monitoring-with-datadog (new skill with full anatomy)
- All 649 skills now have: SKILL.md, LICENSE, scripts/agent.py, references/api-reference.md
2026-03-11 00:22:12 +01:00

122 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""Agent for testing race condition (TOCTOU) vulnerabilities in web applications."""
import argparse
import json
import sys
import threading
import time
from datetime import datetime, timezone
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
def send_concurrent_requests(url, method, data, headers, count, results_list):
"""Send multiple identical requests concurrently to trigger race conditions."""
if not HAS_REQUESTS:
return
barrier = threading.Barrier(count)
def worker(idx):
try:
barrier.wait(timeout=5)
if method == "POST":
resp = requests.post(url, json=data, headers=headers, timeout=15, verify=False)
elif method == "PUT":
resp = requests.put(url, json=data, headers=headers, timeout=15, verify=False)
else:
resp = requests.get(url, headers=headers, timeout=15, verify=False)
results_list.append({
"thread": idx,
"status_code": resp.status_code,
"response_length": len(resp.content),
"response_preview": resp.text[:200],
"elapsed": resp.elapsed.total_seconds(),
})
except Exception as e:
results_list.append({"thread": idx, "error": str(e)[:100]})
threads = []
for i in range(count):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join(timeout=20)
def analyze_results(results):
"""Analyze concurrent request results for race condition indicators."""
indicators = []
success_count = sum(1 for r in results if r.get("status_code") == 200)
if success_count > 1:
indicators.append(f"{success_count} successful responses (expected 1 for idempotent operations)")
response_bodies = [r.get("response_preview", "") for r in results if r.get("status_code") == 200]
unique_bodies = set(response_bodies)
if len(unique_bodies) > 1:
indicators.append(f"Different response bodies across concurrent requests: {len(unique_bodies)} unique")
status_codes = [r.get("status_code") for r in results if r.get("status_code")]
if len(set(status_codes)) > 1:
indicators.append(f"Mixed status codes: {set(status_codes)}")
return indicators
def test_race_condition(url, method, data, token, concurrency):
"""Execute race condition test."""
headers = {"Authorization": f"Bearer {token}"} if token else {}
headers["Content-Type"] = "application/json"
results = []
send_concurrent_requests(url, method, data, headers, concurrency, results)
indicators = analyze_results(results)
return {
"url": url,
"method": method,
"concurrency": concurrency,
"responses": results,
"race_indicators": indicators,
"potential_race": len(indicators) > 0,
}
def main():
parser = argparse.ArgumentParser(
description="Test race condition vulnerabilities (authorized testing only)"
)
parser.add_argument("--url", required=True, help="Target URL")
parser.add_argument("--method", default="POST", choices=["GET", "POST", "PUT"])
parser.add_argument("--data", default="{}", help="JSON payload")
parser.add_argument("--token", help="Bearer token")
parser.add_argument("--concurrency", type=int, default=10, help="Concurrent requests")
parser.add_argument("--output", "-o", help="Output JSON report")
args = parser.parse_args()
print("[*] Race Condition Testing Agent")
print("[!] For authorized security testing only")
data = json.loads(args.data)
result = test_race_condition(args.url, args.method, data, args.token, args.concurrency)
report = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"test_result": result,
"risk_level": "HIGH" if result["potential_race"] else "LOW",
}
print(f"[*] Race condition detected: {result['potential_race']}")
if args.output:
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
print(f"[*] Report saved to {args.output}")
else:
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()