更新: 359 个文件 - 2026-03-16 23:30:01

这个提交包含在:
hao
2026-03-16 23:30:01 -07:00
父节点 527990f535
当前提交 2974cd9ad9
修改 359 个文件,包含 6332 行新增673 行删除

查看文件

@@ -28,6 +28,21 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import List, Dict, Tuple, Optional
import re
import sys
from pathlib import Path
SCRIPTS_DIR = Path(__file__).resolve().parents[2] / "scripts"
if str(SCRIPTS_DIR) not in sys.path:
sys.path.insert(0, str(SCRIPTS_DIR))
from tool_contract import ( # noqa: E402
add_common_args,
emit_report,
ensure_authorized,
make_report,
parse_headers,
write_evidence,
)
class Colors:
@@ -249,14 +264,21 @@ def main():
parser.add_argument("--timeout", type=int, default=10, help="超时时间")
parser.add_argument("--delay", type=float, default=0, help="请求延迟(秒)")
parser.add_argument("-v", "--verbose", action="store_true", help="详细输出")
add_common_args(parser)
args = parser.parse_args()
ensure_authorized(args, parser)
requests.packages.urllib3.disable_warnings()
bruteforcer = WebBruteForcer(
threads=args.threads, timeout=args.timeout, delay=args.delay
)
bruteforcer.session.headers.update(parse_headers(args.header))
if args.proxy:
bruteforcer.session.proxies.update({"http": args.proxy, "https": args.proxy})
if args.format != "text":
bruteforcer.print_result = lambda *_args, **_kwargs: None # type: ignore[assignment]
usernames = []
if args.userlist:
@@ -276,10 +298,6 @@ def main():
bruteforcer.print_result("ERROR", "请提供密码 (--pass 或 -P)")
sys.exit(1)
print(f"\n{Colors.BOLD}{'=' * 60}{Colors.END}")
print(f"{Colors.BOLD}Web Brute Force Tool{Colors.END}")
print(f"{Colors.BOLD}{'=' * 60}{Colors.END}\n")
bruteforcer.print_result("INFO", f"目标: {args.url}")
bruteforcer.print_result("INFO", f"用户数: {len(usernames)}")
bruteforcer.print_result("INFO", f"密码数: {len(passwords)}")
@@ -295,23 +313,45 @@ def main():
data_template=args.data,
success_pattern=args.success,
fail_pattern=args.fail,
verbose=args.verbose,
verbose=args.verbose and args.format == "text",
)
elapsed = time.time() - bruteforcer.start_time
rate = bruteforcer.attempts / elapsed if elapsed > 0 else 0
print(f"\n{Colors.BOLD}{'=' * 60}{Colors.END}")
bruteforcer.print_result("INFO", f"总尝试: {bruteforcer.attempts}")
bruteforcer.print_result("INFO", f"耗时: {elapsed:.2f}s ({rate:.1f} req/s)")
if results:
bruteforcer.print_result("SUCCESS", f"发现 {len(results)} 个有效凭证!")
for r in results:
print(f" - {r['username']}:{r['password']}")
else:
bruteforcer.print_result("INFO", "未发现有效凭证")
print(f"{Colors.BOLD}{'=' * 60}{Colors.END}\n")
evidence_refs = []
ref = write_evidence(
args,
"web-brute-results.json",
{"results": results, "attempts": bruteforcer.attempts, "elapsed": elapsed, "rate": rate},
)
if ref:
evidence_refs.append(ref)
status = "verified" if results else "needs-review"
severity = "high" if results else "medium"
report = make_report(
tool="web-brute",
mode="credential-spray-lab",
target=args.url,
status=status,
severity=severity,
payload_or_probe={"results": results, "username_count": len(usernames), "password_count": len(passwords)},
request_summary={"method": args.method, "threads": args.threads, "delay": args.delay, "rate": rate},
evidence_refs=evidence_refs,
destructive_risk="medium",
args=args,
)
text_lines = [
"=" * 60,
"Web Brute Force Tool",
"=" * 60,
f"Target: {args.url}",
f"Attempts: {bruteforcer.attempts}",
f"Elapsed: {elapsed:.2f}s",
f"Hits: {len(results)}",
f"Status: {status}",
]
emit_report(args, report, text_lines)
if __name__ == "__main__":

查看文件

@@ -30,6 +30,16 @@ import time
from typing import Dict, Optional, Tuple, List
import sys
import re
from pathlib import Path
import contextlib
import io
SCRIPTS_DIR = Path(__file__).resolve().parents[2] / "scripts"
if str(SCRIPTS_DIR) not in sys.path:
sys.path.insert(0, str(SCRIPTS_DIR))
from tool_contract import add_common_args, emit_report, ensure_authorized, make_report, write_evidence # noqa: E402
class Colors:
@@ -307,57 +317,33 @@ def main():
parser.add_argument("--kid-injection", default="/dev/null", help="KID 注入值")
parser.add_argument("--analyze", action="store_true", help="分析 JWT")
parser.add_argument("-v", "--verbose", action="store_true", help="详细输出")
add_common_args(parser, include_network=False)
args = parser.parse_args()
ensure_authorized(args, parser)
cracker = JWTCracker()
print(f"\n{Colors.BOLD}{'=' * 60}{Colors.END}")
print(f"{Colors.BOLD}JWT Cracker & Analyzer{Colors.END}")
print(f"{Colors.BOLD}{'=' * 60}{Colors.END}\n")
try:
header, payload, _ = cracker.decode(args.token)
print(f"{Colors.CYAN}Header:{Colors.END}")
print(f" {json.dumps(header, indent=2)}")
print(f"\n{Colors.CYAN}Payload:{Colors.END}")
print(f" {json.dumps(payload, indent=2)}")
if args.format == "text":
print(f"{Colors.CYAN}Header:{Colors.END}")
print(f" {json.dumps(header, indent=2)}")
print(f"\n{Colors.CYAN}Payload:{Colors.END}")
print(f" {json.dumps(payload, indent=2)}")
except Exception as e:
cracker.print_result("ERROR", str(e))
sys.exit(1)
if args.analyze:
print(f"\n{Colors.CYAN}Analysis:{Colors.END}")
analysis = cracker.analyze(args.token)
if "issues" in analysis:
for issue in analysis["issues"]:
color = (
Colors.RED
if issue["severity"] == "HIGH"
else Colors.YELLOW
if issue["severity"] == "MEDIUM"
else Colors.BLUE
)
print(f" {color}[{issue['severity']}]{Colors.END} {issue['issue']}")
print(f" {issue['description']}")
if args.attack:
print(f"\n{Colors.CYAN}Attack: {args.attack}{Colors.END}")
if args.attack == "none":
forged = cracker.attack_none_algorithm(args.token)
cracker.print_result("SUCCESS", f"Forged Token (none): {forged}")
elif args.attack == "kid":
forged = cracker.attack_kid_injection(args.token, args.kid_injection)
cracker.print_result("SUCCESS", f"Forged Token (kid): {forged}")
elif args.attack == "confusion":
forged = cracker.attack_algorithm_confusion(args.token)
cracker.print_result("INFO", "需要公钥来利用算法混淆攻击")
analysis = cracker.analyze(args.token) if args.analyze else {"issues": []}
forged = None
if args.attack == "none":
forged = cracker.attack_none_algorithm(args.token)
elif args.attack == "kid":
forged = cracker.attack_kid_injection(args.token, args.kid_injection)
elif args.attack == "confusion":
forged = cracker.attack_algorithm_confusion(args.token)
wordlist = None
if args.wordlist:
@@ -368,24 +354,62 @@ def main():
cracker.print_result("ERROR", f"字典文件不存在: {args.wordlist}")
sys.exit(1)
print(f"\n{Colors.CYAN}Cracking...{Colors.END}")
stdout_buffer = io.StringIO()
capture = contextlib.redirect_stdout(stdout_buffer) if args.format != "text" else contextlib.nullcontext()
start = time.time()
secret = cracker.crack(args.token, wordlist, args.verbose)
with capture:
secret = cracker.crack(args.token, wordlist, args.verbose and args.format == "text")
elapsed = time.time() - start
if secret:
cracker.print_result("FOUND", f"密钥破解成功: {secret}")
cracker.print_result("INFO", f"耗时: {elapsed:.2f}s")
forged = cracker.encode(header, payload, secret, header.get("alg", "HS256"))
cracker.print_result("SUCCESS", f"可以伪造任意 Token")
else:
cracker.print_result(
"WARNING",
f"未能破解密钥 (尝试了 {len(wordlist) if wordlist else len(cracker.common_secrets)} 个)",
)
print(f"\n{Colors.BOLD}{'=' * 60}{Colors.END}\n")
evidence_refs = []
ref = write_evidence(
args,
"jwt-analysis.json",
{
"header": header,
"payload": payload,
"analysis": analysis,
"attack": args.attack,
"secret_found": bool(secret),
"captured_stdout": stdout_buffer.getvalue()[-1000:],
},
)
if ref:
evidence_refs.append(ref)
status = "verified" if secret or forged else "needs-review"
severity = "high" if secret else "medium" if analysis.get("issues") else "info"
report = make_report(
tool="jwt-cracker",
mode="jwt-analysis-and-weak-secret-test",
target="jwt-token",
status=status,
severity=severity,
payload_or_probe={
"header": header,
"payload_keys": sorted(payload.keys()),
"issues": analysis.get("issues", []),
"attack": args.attack,
"secret_found": bool(secret),
},
request_summary={"wordlist": args.wordlist or "builtin-common", "elapsed_seconds": round(elapsed, 2)},
evidence_refs=evidence_refs,
destructive_risk="low",
args=args,
extra={"forged_token_present": bool(forged)},
)
text_lines = [
"=" * 60,
"JWT Cracker & Analyzer",
"=" * 60,
f"Token Alg: {header.get('alg', 'unknown')}",
f"Issues: {len(analysis.get('issues', []))}",
f"Secret Found: {'yes' if secret else 'no'}",
f"Status: {status}",
]
emit_report(args, report, text_lines)
if __name__ == "__main__":

查看文件

@@ -0,0 +1,99 @@
#!/usr/bin/env python3
"""
Session / Token Boundary Lab Tool
LAB ONLY | AUTHORIZED TARGETS ONLY
"""
from __future__ import annotations
import argparse
import re
import sys
from pathlib import Path
from typing import Any, Dict, List
import requests
SCRIPTS_DIR = Path(__file__).resolve().parents[3] / "scripts"
if str(SCRIPTS_DIR) not in sys.path:
sys.path.insert(0, str(SCRIPTS_DIR))
from tool_contract import add_common_args, emit_report, ensure_authorized, make_report, parse_headers, write_evidence # noqa: E402
COOKIE_ATTRS = ["HttpOnly", "Secure", "SameSite", "Path", "Domain"]
STORAGE_PATTERNS = {
"localStorage": re.compile(r"localStorage\.(setItem|getItem)|window\.localStorage", re.I),
"sessionStorage": re.compile(r"sessionStorage\.(setItem|getItem)|window\.sessionStorage", re.I),
"token-ish": re.compile(r"(jwt|token|authorization|bearer)", re.I),
}
def analyze(target: str, timeout: float, headers: Dict[str, str]) -> Dict[str, Any]:
response = requests.get(target, timeout=timeout, headers=headers, verify=False)
cookies = []
for raw in response.headers.get("Set-Cookie", "").split(","):
raw = raw.strip()
if not raw:
continue
attrs = {attr: (attr.lower() in raw.lower()) for attr in COOKIE_ATTRS}
cookies.append({"raw": raw[:300], "attributes": attrs})
storage_hits = []
for name, pattern in STORAGE_PATTERNS.items():
if pattern.search(response.text):
storage_hits.append(name)
suspicious_headers = []
for name in ["Set-Cookie", "Authorization", "X-Forwarded-User", "X-Original-URL"]:
if response.headers.get(name):
suspicious_headers.append({"name": name, "value": response.headers.get(name)[:200]})
return {
"status_code": response.status_code,
"cookies": cookies,
"storage_hits": storage_hits,
"suspicious_headers": suspicious_headers,
"body_excerpt": response.text[:600],
}
def main() -> int:
parser = argparse.ArgumentParser(description="Session / Token Boundary Lab Tool")
parser.add_argument("--target", required=True, help="目标 URL")
parser.add_argument("--timeout", type=float, default=8.0, help="请求超时时间")
add_common_args(parser)
args = parser.parse_args()
ensure_authorized(args, parser)
headers = parse_headers(args.header)
findings = analyze(args.target, args.timeout, headers)
evidence_refs = []
ref = write_evidence(args, "session-lab.json", findings)
if ref:
evidence_refs.append(ref)
suspicious = len(findings["cookies"]) + len(findings["storage_hits"]) + len(findings["suspicious_headers"])
report = make_report(
tool="session-lab",
mode="cookie-storage-session-boundary-check",
target=args.target,
status="verified" if suspicious else "needs-review",
severity="medium" if suspicious else "info",
payload_or_probe=findings,
request_summary={"timeout": args.timeout, "header_names": sorted(headers.keys())},
evidence_refs=evidence_refs,
destructive_risk="low",
args=args,
)
text_lines = [
"=" * 60,
"Session / Token Boundary Lab Tool",
"=" * 60,
f"Target: {args.target}",
f"Cookie Findings: {len(findings['cookies'])}",
f"Storage Hits: {len(findings['storage_hits'])}",
f"Suspicious Headers: {len(findings['suspicious_headers'])}",
]
return emit_report(args, report, text_lines)
if __name__ == "__main__":
raise SystemExit(main())