更新: 359 个文件 - 2026-03-16 23:30:01
这个提交包含在:
@@ -26,6 +26,23 @@ import re
|
||||
import urllib.parse
|
||||
from typing import List, Dict, Tuple, Optional
|
||||
import time
|
||||
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_cookie_string,
|
||||
parse_headers,
|
||||
write_evidence,
|
||||
)
|
||||
|
||||
|
||||
class Colors:
|
||||
@@ -345,16 +362,19 @@ def main():
|
||||
"--all-categories", action="store_true", help="测试所有Payload类别"
|
||||
)
|
||||
parser.add_argument("--timeout", type=int, default=10, help="超时时间")
|
||||
add_common_args(parser)
|
||||
|
||||
args = parser.parse_args()
|
||||
ensure_authorized(args, parser)
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
fuzzer = XSSFuzzer(timeout=args.timeout)
|
||||
|
||||
print(f"\n{Colors.BOLD}{'=' * 60}{Colors.END}")
|
||||
print(f"{Colors.BOLD}XSS Fuzzer{Colors.END}")
|
||||
print(f"{Colors.BOLD}{'=' * 60}{Colors.END}\n")
|
||||
fuzzer.session.headers.update(parse_headers(args.header))
|
||||
if args.proxy:
|
||||
fuzzer.session.proxies.update({"http": args.proxy, "https": args.proxy})
|
||||
if args.format != "text":
|
||||
fuzzer.print_result = lambda *_args, **_kwargs: None # type: ignore[assignment]
|
||||
|
||||
data = {}
|
||||
if args.data:
|
||||
@@ -363,13 +383,9 @@ def main():
|
||||
k, v = pair.split("=", 1)
|
||||
data[k] = v
|
||||
|
||||
cookies = {}
|
||||
if args.cookie:
|
||||
for pair in args.cookie.split(";"):
|
||||
if "=" in pair:
|
||||
k, v = pair.strip().split("=", 1)
|
||||
cookies[k] = v
|
||||
cookies = parse_cookie_string(args.cookie)
|
||||
|
||||
csp_result = {"has_csp": False, "weaknesses": []}
|
||||
if args.check_csp:
|
||||
fuzzer.print_result("INFO", "检查 CSP 策略...")
|
||||
csp_result = fuzzer.check_csp(args.url, cookies)
|
||||
@@ -384,6 +400,7 @@ def main():
|
||||
for w in csp_result["weaknesses"]:
|
||||
fuzzer.print_result("WARNING", f" - {w}")
|
||||
|
||||
dom_results = []
|
||||
if args.dom_scan:
|
||||
fuzzer.print_result("INFO", "扫描 DOM XSS...")
|
||||
dom_results = fuzzer.scan_dom_xss(args.url, cookies)
|
||||
@@ -396,18 +413,58 @@ def main():
|
||||
fuzzer.print_result("INFO", "上下文分析:")
|
||||
for ctx, status in context.items():
|
||||
color = Colors.YELLOW if status == "未过滤" else Colors.GREEN
|
||||
print(f" {color}{ctx}: {status}{Colors.END}")
|
||||
if args.format == "text":
|
||||
print(f" {color}{ctx}: {status}{Colors.END}")
|
||||
|
||||
results = fuzzer.test_reflected(args.url, args.param, args.method, data, cookies)
|
||||
|
||||
print(f"\n{Colors.BOLD}{'=' * 60}{Colors.END}")
|
||||
if results:
|
||||
fuzzer.print_result("SUCCESS", f"发现 {len(results)} 个 XSS 漏洞!")
|
||||
for r in results:
|
||||
print(f" - [{r['category']}] {r['param']}: {r['payload'][:60]}...")
|
||||
else:
|
||||
fuzzer.print_result("INFO", "未发现反射型 XSS 漏洞")
|
||||
print(f"{Colors.BOLD}{'=' * 60}{Colors.END}\n")
|
||||
evidence_refs = []
|
||||
for name, payload in [
|
||||
("xss-context.json", context),
|
||||
("xss-reflected.json", results),
|
||||
("xss-dom.json", dom_results),
|
||||
("xss-csp.json", csp_result),
|
||||
]:
|
||||
ref = write_evidence(args, name, payload)
|
||||
if ref:
|
||||
evidence_refs.append(ref)
|
||||
status = "verified" if results else "suspected" if dom_results or csp_result.get("weaknesses") else "needs-review"
|
||||
severity = "high" if results else "medium" if dom_results else "low" if csp_result.get("weaknesses") else "info"
|
||||
report = make_report(
|
||||
tool="xss-fuzzer",
|
||||
mode="dom-and-reflected-xss",
|
||||
target=args.url,
|
||||
status=status,
|
||||
severity=severity,
|
||||
payload_or_probe={
|
||||
"reflected_hits": results,
|
||||
"dom_hits": dom_results,
|
||||
"context": context,
|
||||
"csp": csp_result,
|
||||
},
|
||||
request_summary={
|
||||
"method": args.method,
|
||||
"param": args.param,
|
||||
"has_body_template": bool(args.data),
|
||||
"header_names": sorted(parse_headers(args.header).keys()),
|
||||
},
|
||||
evidence_refs=evidence_refs,
|
||||
destructive_risk="low",
|
||||
args=args,
|
||||
)
|
||||
text_lines = [
|
||||
"=" * 60,
|
||||
"XSS Fuzzer",
|
||||
"=" * 60,
|
||||
f"Target: {args.url}",
|
||||
f"Method: {args.method}",
|
||||
f"Param: {args.param}",
|
||||
f"Reflected Hits: {len(results)}",
|
||||
f"DOM Findings: {len(dom_results)}",
|
||||
f"CSP Weaknesses: {len(csp_result.get('weaknesses', []))}",
|
||||
f"Status: {status}",
|
||||
]
|
||||
emit_report(args, report, text_lines)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
在新工单中引用
屏蔽一个用户