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

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

查看文件

@@ -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__":