Files
2026-07-28 09:39:37 +08:00

140 lines
5.7 KiB
Python

"""
waf 黑盒用户模拟测试 — 正常请求通行 vs 攻击载荷拦截。
用户旅程:
1. 正常请求 → 通过
2. SQL 注入载荷 → 403 blocked by WAF
3. XSS 跨站脚本载荷 → 403
4. 命令注入载荷 → 403
5. 路径遍历载荷 → 403
6. 扫描器 User-Agent → 403
注意: WAF 监听 443 端口 (TLS),测试时需注意证书验证。
"""
import ssl
import urllib.request
import urllib.error
from helpers import (
http_get,
assert_eq, assert_status, assert_true, assert_contains,
skip, Counter, check_service,
)
from config import get_url
WAF_URL = "https://127.0.0.1:443" # WAF 监听 443 需要 HTTPS
def _waf_get(base_url: str, path: str, headers: dict = None):
"""通过 WAF 发送 HTTPS GET 请求(跳过证书验证)。"""
ctx = ssl._create_unverified_context()
url = f"{base_url}{path}"
hdrs = headers or {}
req = urllib.request.Request(url, headers=hdrs, method="GET")
try:
with urllib.request.urlopen(req, timeout=10.0, context=ctx) as resp:
return resp.status, resp.read().decode("utf-8", errors="replace"), dict(resp.headers)
except urllib.error.HTTPError as e:
body = e.read().decode("utf-8", errors="replace") if e.fp else ""
return e.code, body, dict(e.headers) if e.headers else {}
except Exception as e:
return 0, str(e), {}
def run(url: str = None):
"""waf 用户模拟测试入口。返回 (passed, failed, skipped)。"""
wu = url or WAF_URL
c = Counter()
print(f"\n--- waf 安全防护流程 ---\n")
# ------------------------------------------------------------------
# 0. 检查服务可用性
# ------------------------------------------------------------------
reachable, detail = check_service(wu)
if not reachable:
skip("全部测试", f"WAF 不可达: {detail}", c)
return c.passed, c.failed, c.skipped
# ------------------------------------------------------------------
# 场景 1: 正常请求应通过
# ------------------------------------------------------------------
status, body, headers = _waf_get(wu, "/")
assert_true(
status != 403,
"正常请求-通过", c,
f"status={status}",
)
# ------------------------------------------------------------------
# 场景 2: SQL 注入 — UNION SELECT
# ------------------------------------------------------------------
status, body, headers = _waf_get(wu, "/?id=1 UNION SELECT * FROM users")
assert_eq(status, 403, "SQLi-UNION SELECT-拦截 (403)", c)
assert_contains(body, "blocked by WAF", "SQLi-响应体 blocked", c)
# ------------------------------------------------------------------
# 场景 3: SQL 注入 — SQL 注释符
# ------------------------------------------------------------------
status, body, headers = _waf_get(wu, "/?user=admin'--")
assert_eq(status, 403, "SQLi-注释符-拦截 (403)", c)
# ------------------------------------------------------------------
# 场景 4: XSS — script 标签
# ------------------------------------------------------------------
status, body, headers = _waf_get(wu, "/?q=<script>alert(1)</script>")
assert_eq(status, 403, "XSS-script标签-拦截 (403)", c)
# ------------------------------------------------------------------
# 场景 5: XSS — onerror 事件
# ------------------------------------------------------------------
status, body, headers = _waf_get(wu, "/?q=<img onerror=alert(1)>")
assert_eq(status, 403, "XSS-onerror-拦截 (403)", c)
# ------------------------------------------------------------------
# 场景 6: 命令注入 — cat /etc/passwd
# ------------------------------------------------------------------
status, body, headers = _waf_get(wu, "/?cmd=; cat /etc/passwd")
assert_eq(status, 403, "命令注入-cat-拦截 (403)", c)
# ------------------------------------------------------------------
# 场景 7: 命令注入 — id 命令
# ------------------------------------------------------------------
status, body, headers = _waf_get(wu, "/?x=| id")
assert_eq(status, 403, "命令注入-id-拦截 (403)", c)
# ------------------------------------------------------------------
# 场景 8: 路径遍历
# ------------------------------------------------------------------
status, body, headers = _waf_get(wu, "/?file=../../../etc/passwd")
assert_eq(status, 403, "路径遍历-拦截 (403)", c)
# ------------------------------------------------------------------
# 场景 9: 路径遍历 — URL 编码
# ------------------------------------------------------------------
status, body, headers = _waf_get(wu, "/?file=..%2f..%2f..%2fetc%2fpasswd")
assert_eq(status, 403, "路径遍历-URL编码-拦截 (403)", c)
# ------------------------------------------------------------------
# 场景 10: 扫描器 User-Agent
# ------------------------------------------------------------------
status, body, headers = _waf_get(wu, "/", headers={"User-Agent": "sqlmap/1.0"})
assert_eq(status, 403, "扫描器UA-sqlmap-拦截 (403)", c)
# ------------------------------------------------------------------
# 场景 11: 扫描器 User-Agent — Nikto
# ------------------------------------------------------------------
status, body, headers = _waf_get(wu, "/", headers={"User-Agent": "Nikto"})
assert_eq(status, 403, "扫描器UA-nikto-拦截 (403)", c)
# ------------------------------------------------------------------
# 汇总
# ------------------------------------------------------------------
print(f"\n waf 测试完成: {c.summary()}")
return c.passed, c.failed, c.skipped
if __name__ == "__main__":
run()