简介:一款用于检测HTTP请求头缺失与CORS跨域配置漏洞的Python工具,面向Web开发、安全测试及渗透测试人员,可帮助定位Content-Type、Authorization、Referer、Cookie等关键头信息的缺失或错误配置,并对Access-Control-Allow-Origin、Allow-Methods、Allow-Credentials等CORS响应头进行合规审计,同时关注X-Frame-Options、Content-Security-Policy等安全头设置,适用于开发阶段自检、生产环境定期安全巡检、渗透测试快速弱点定位等场景。压缩包共3个文件,包含主脚本、说明文档及依赖清单,整体仅3KB,轻量易用,携带方便。目前已有857人学习下载。通过模拟GET、POST、PUT、DELETE等请求分析服务器响应,工具能直接输出存在问题的请求头与CORS配置项,并给出修复建议;脚本结构清晰,便于二次扩展,是提升Web服务安全性的实用小工具。
1. 一个背着 requests 到处跑的脚本,专门帮你揪出请求头缺失和 CORS 配置漏洞
说实话,我见过太多业务站点上线前没做过请求头检查,结果线上被刷出问题才回头翻日志的场面。这个HTTP_Header_Check工具解决的就是这个事:给你一个目标 URL,它用 Python 发请求、收响应头,再对照一份安全基线,把缺失的 HTTP 请求头和配置不当的 CORS 跨域字段一条条列出来。它不需要装数据库、不用起服务,一个脚本加一个依赖文件就能跑。适合开发同学做自测、运维做定期安全巡检,也适合做渗透测试时拿来做第一轮信息摸排。我拆完这个包之后的感觉是:它的检测思路比很多商业扫描器的第一层逻辑还要实在,值得照着源码过一遍。
2. HTTP 请求头缺失检测:先搞懂为什么缺一个头就是一笔风险账
2.1 安全基线的来源:哪些请求头值得被盯住
HTTP 请求头是服务器判断客户端身份、校验请求合法性、限制内容类型的最直接依据。缺了不该缺的,或者带了不该带的,都会让服务器处理逻辑走偏。这个工具对标的是 OWASP 推荐的一组安全响应头基线,重点盯这几类:Content-Type、Authorization、Referer、Cookie、X-Frame-Options、Content-Security-Policy和Strict-Transport-Security。
Content-Type缺失会导致请求体被服务器按默认类型解析,常见的后果是 JSON 数据被当成表单参数,校验逻辑直接失效。Authorization缺失意味着认证凭证没有按规范传输,很多接口设计成从请求头取 token,这个头一旦没带,服务端要么拒绝要么放行,放行的情况就是大坑。Referer的问题是容易携带敏感信息,尤其是 URL 里带 session id 的站点。
X-Frame-Options和Content-Security-Policy这两个头直接决定页面能不能被 iframe 嵌走、能不能执行内联脚本。没有X-Frame-Options,你的支付页面就是天然的点击劫持靶子。Strict-Transport-Security没配,浏览器允许用 HTTP 明文访问,抓包就能拿到登录凭证。工具把这些头全部做成检测项,跑一遍就知道服务器到底裸奔了多少层。
2.2 工具的检测思路:发请求、抓响应头、对照基线
HTTP_Header_Check.py的核心逻辑并不复杂,更像是把安全人员手动 curl 的过程自动化了。它先对目标 URL 发起请求,收集服务器响应的头部集合,然后把响应头逐个和内置的检测清单比对。比对的目标有两个维度:一个是这个头到底有没有返回,另一个是返回的值是否符合预期配置。
举个例子,Access-Control-Allow-Origin返回*不代表一定有问题,但如果同时检测到Access-Control-Allow-Credentials: true,这俩组合在一起就是高危配置。脚本里对这种组合做了单独判定,不是简单看字段存在性。这个细节很关键,因为市面上不少检测工具只看字段是否缺失,不看字段之间的关联关系,导致误报率很高。
检测请求默认用 GET,同时支持指定其他方法。工具会在分析前先做一次普通请求来确定目标可达性,如果目标直接返回非 200 之类的异常状态码,脚本会打印提示而不是继续往下看头信息。这个设计避免了针对不可达目标的空跑。
2.3 把工具跑起来:安装依赖和执行脚本
这个包解压之后目录结构是HTTP_Header_Check-main,里面有主脚本、依赖清单和说明文档。依赖只有requests一个库,这是 Python 里做 HTTP 请求的事实标准。
cd HTTP_Header_Check-main pip install -r requirements.txt python HTTP_Header_Check.py -u https://api.example.compip install -r requirements.txt会读取文件里声明的库名和版本约束,把requests装到当前 Python 环境。-u参数指定目标 URL,脚本会拿着这个地址去发检测请求。如果你的目标站点有 HTTP 和 HTTPS 两种入口,建议显式写全协议头,避免脚本帮你做默认跳转。
python HTTP_Header_Check.py -u https://api.example.com -m POST -d '{"username":"test"}'-m强制指定请求方法,-d传入请求体。工具对 POST 请求会自动补上Content-Type: application/json和Content-Length两个头。这条命令适合测接口的认证逻辑,因为不少接口只在 POST 下才校验Authorization头。
2.4 报告怎么读:先处理高风险,再看低风险
脚本输出的报告会按缺失项名称、当前值、建议配置三列展示。我看到输出之后一般按优先级处理:涉及身份认证的缺失项最先补,比如Authorization和Cookie相关配置;其次是内容安全相关的Content-Security-Policy,再往后是X-Frame-Options这类防护加固项。
一个容易忽略的细节是,工具对同一个 URL 会跑两遍请求,一遍普通请求,一遍带常见浏览器特征的请求。这样做的原因是有些业务服务器区分浏览器和脚本客户端,返回的响应头完全不同。如果只跑一遍,很可能拿到的是一套降级后的头集合,检测结果也就会失真。
3. CORS 跨域配置审计:五个字段定义你的跨域信任边界
3.1 预检请求与字段联动
CORS 的检测不能只看单个响应头,要看五个字段共同构成的一条信任链。Access-Control-Allow-Origin决定哪些源可以访问资源,Access-Control-Allow-Methods决定哪些 HTTP 方法跨域可用,Access-Control-Allow-Headers决定哪些自定义头会被放行,Access-Control-Allow-Credentials决定是否允许携带凭证,Access-Control-Max-Age控制预检结果的缓存时长。
浏览器在发起跨域请求之前,对于非简单请求会先发一个OPTIONS预检。预检通过之后才会发起真实请求。这个工具在检测 CORS 时会先主动发一个OPTIONS请求,把服务器的预检响应完整收回来,再看这五个字段的取值。这一点做的比很多只做 GET 请求的扫描器要扎实,因为 CORS 的真实风险点基本都藏在预检响应里。
3.2 五个字段的高风险取值判定
Access-Control-Allow-Origin的值如果直接回显请求头里的Origin,说明服务端没有维护可信源列表,攻击者随便传一个Origin: https://evil.com就能拿到响应数据。这类反射型配置是工具重点标记的项。Access-Control-Allow-Credentials如果和反射型Origin同时出现,等于告诉浏览器携带 cookie 跨域读取数据,属于明确的漏洞条件,脚本会直接标红。
Access-Control-Allow-Methods里出现DELETE、PUT这类高风险方法时,工具会做提示。业务可能根本用不到这两个方法,但配置里多放一个就多一层暴露面。Access-Control-Max-Age设置过长会让浏览器长时间缓存预检结果,如果中间修改了 CORS 策略,真实请求会继续按老的缓存策略执行,这个也是工具给提示的理由。
3.3 用工具审计一个典型错误配置
假如目标接口是https://api.example.com/user/info,配置了Access-Control-Allow-Origin: *加上Access-Control-Allow-Credentials: true。工具跑完之后会在 CORS 区域里报出一条高危项,提示允许任意源携带凭证访问受保护资源。
python HTTP_Header_Check.py -u https://api.example.com/user/info -m GET -H "Origin: https://evil.example.com"这条命令手动指定了Origin: https://evil.example.com,模拟的是恶意站点的跨域请求。如果响应头里返回的Access-Control-Allow-Origin也跟着变成了https://evil.example.com,那就说明服务器在做无条件回显,属于反射型 CORS 配置。
-H参数在工具里承担自定义请求头的注入入口。我一般会同时传两个Origin值,一个正常业务源,一个随机域名,对比两次响应头的变化来判断配置策略。如果正常源拿到了Allow-Origin: 正常源,随机域名也拿到了Allow-Origin: 随机域名,那这个服务端的源校验形同虚设。
3.4 源列表校验逻辑与误报边界
工具对 CORS 字段做了分层判定,第一层是看字段是否存在,第二层是看当前值在整个值域里的位置。把*和null单独拎出来处理,因为这两个值都代表无过滤策略。null这个值特别容易被忽略,很多攻击者用sandbox属性加载 iframe,请求头里的Origin就会被置成null,服务端如果直接把null放进白名单,后果和*一样。
误报边界在于内网接口。如果目标本身就是给内部系统用的,Access-Control-Allow-Origin配成内网固定 IP 列表是合理的,工具会把这种情况和公网接口区分开。它不会把这个判断逻辑写死在代码里,而是通过 README 里的说明提示使用者自行识别。也就是说,工具输出的是检测结果,最终决策还是得靠人来拍板。
4. 依赖到报告:工具落地的完整操作链路
4.1 环境准备:Python 版本与依赖清单
这个工具跑在 Python 3 上。requirements.txt文件里面核心依赖就是requests,如果你想在隔离环境里运行,可以建一个虚拟环境再做安装,避免把依赖装到系统 Python 里造成冲突。
python -m venv venv source venv/bin/activate pip install -r requirements.txt虚拟环境是 Python 项目隔离依赖的常见做法。venv目录创建之后,source venv/bin/activate在当前 shell 里激活它,后续安装的包只会落到这个虚拟环境里,不会污染全局。pip install -r requirements.txt在这里的作用是让团队里所有人都装上同一套依赖版本,避免因为你本机的requests版本太新或太旧导致检测结果不一致。
4.2 请求方法、请求头与超时控制
工具支持的方法包括GET、POST、PUT、DELETE、OPTIONS。默认是GET,因为安全头检测只需要看响应头,GET最容易被服务器放行。OPTIONS专门用来触发 CORS 预检逻辑。
python HTTP_Header_Check.py -u https://api.example.com -m OPTIONS -H "Origin: https://app.example.com" -H "Access-Control-Request-Method: PUT"这条命令把预检请求的意图表达得相对完整:Origin告知服务器请求来源,Access-Control-Request-Method告知即将发起的真实请求方法。一个严格配置的服务端会走到 CORS 预检分支,返回完整的Access-Control-Allow-*头集合。如果服务器直接返回 405 或者忽略OPTIONS方法,那就是工具要标记的关注点。
超时参数在检测不可达域名时非常有用。默认连接超时是 10 秒,可以单独调整。
python HTTP_Header_Check.py -u http://192.168.1.88:8080 -t 5-t 5把超时压到了 5 秒,适合检测内网批量存活机器时快速跳过无响应节点。对外网域名做检测不建议把超时调得太低,弱网环境下的正常服务也可能被误判成不可达。
4.3 输出报告的结构与解读方式
工具的输出分为三个分区:HTTP 响应头缺失项、CORS 配置检测结果、HTTP 状态码与摘要信息。缺失项按风险等级排序,第一屏输出的一定是影响面最大的配置问题。
我在实际使用中拿到输出会先看HTTP 状态码那一行,确定这次检测拿到的响应是真实业务响应还是错误页。如果服务器对脚本请求返回了一个 403 或者 WAF 拦截页,后面的头信息检测再详细也没有参考价值。403、405这类异常状态码需要先解决访问问题,再去看头配置。
4.3.1 风险等级与处理顺序参考
| 等级 | 检测项特征 | 建议动作 |
|---|---|---|
| 高危 | 反射型 Origin + Credentials 同时出现 | 立即修复源校验逻辑 |
| 高危 | CSP 缺失且页面含用户输入渲染点 | 补 CSP 并做灰度验证 |
| 中危 | X-Frame-Options未配置 | 按业务形态配DENY或SAMEORIGIN |
| 中危 | Access-Control-Allow-Methods包含 DELETE | 收敛到实际使用的方法集合 |
| 低危 | Max-Age未配置或过长 | 设置明确的预检缓存时间 |
这个表格是我自己处理报告时总结的一套优先级,不是工具自带的标准。工具输出的是原始检测结果,风险等级还需要结合业务形态来判断。
5. 避坑指南:那些让检测结果失真、让你白忙一场的典型坑
5.1 检测目标被 WAF 拦截,拿到的是拦截页响应头
现象:工具跑完,报告显示Content-Security-Policy和X-Frame-Options全都没有,但浏览器打开目标页面明明有这些头。
原因:目标站点挂了 WAF,脚本请求因为 User-Agent 或者请求频率被识别成扫描行为,WAF 直接返回了一个简化版的拦截响应页。这个拦截页只有最基本的响应头,自然检测不出安全配置。
解决:先用浏览器开发者工具看成产环境的真实响应头,再手动把浏览器的User-Agent和Accept-Language注入到工具的请求里重跑一遍。如果结果仍然不一致,检查目标 IP 是否有访问频率限制,拉长扫描间隔。
5.2 CORS 检测报出null源,但业务本身没这个配置
现象:报告里显示Access-Control-Allow-Origin: null,团队检查服务端配置发现根本没写过这个值。
原因:检测请求没有带Origin头,服务端拿到空来源后把默认值回填成了null。这是服务端框架自动赋值的逻辑,不是业务主动配置。用sandbox属性嵌入 iframe 的请求也会把Origin变成null。
解决:在请求里显式加上Origin: https://your-domain.com,重跑 CORS 检测。如果加上之后Allow-Origin正常回显业务域名,说明服务端源校验是通的,之前报出来的null只是空来源兜底逻辑。
5.3http error 400. a request header field is too long导致检测中断
现象:对某些登录接口跑检测时,脚本直接报 400,而且错误信息提示请求头字段太长。
原因:检测脚本注入的自定义头里带了过长的测试值,部分服务器对单行请求头长度做了限制,超过阈值直接拒绝。常见触发点是Cookie头或Authorization头里放了超大 payload。
解决:缩短注入的自定义头值,控制在 1024 字节以内。如果目标是真实业务接口,建议先确认接口自身的请求头长度限制,再用合适的测试值去检测。这个错误本身也值得记录在报告里,因为请求头长度限制缺失同样属于后期需要评估的防护缺口。
5.4 HTTPS 站点证书校验失败导致检测无结果
现象:目标站点用 IP 直连或者内部测试证书,工具直接抛 SSL 错误退出,什么都检测不到。
原因:脚本默认走requests的证书校验逻辑,自签名证书不在可信 CA 列表里,连接被掐断。
解决:工具提供了可选的证书跳过开关,仅限测试环境使用。生产环境检测建议直接修复证书问题,而不是在脚本里关校验。
python HTTP_Header_Check.py -u https://192.168.1.88:8443 --skip-verify--skip-verify让底层 HTTP 库不再校验服务器证书链。这个参数必须谨慎用,一旦开启就等于放弃了传输层加密的信任验证。
5.5 同一 URL 跑两次结果不同,头集合变化大
现象:同一个命令连续跑两次,第一次报缺少Strict-Transport-Security,第二次这个头又出现了。
原因:服务器做了根据来源负载均衡,不同节点上的 Nginx 配置不一致,有的节点补了 HSTS,有的没补。这类配置漂移在生产环境非常常见。
解决:对目标域名多跑几次,间隔拉长到 30 秒以上,对比每次返回的节点特征。如果多轮结果不一致,优先排查负载均衡器上的头配置统一性。工具在这里的作用就是把配置漂移暴露出来,它本身没有能力修复。
6. 进阶:把请求头检测接进 CI/CD,在合并前自动拦截风险配置
把工具从手动命令行推进到自动化流水线,才算真正发挥它的价值。常见做法是在 GitLab CI 或者 GitHub Actions 里加一个检测 job,每次有代码合并到主干前,对这个环境的新域名或者变更接口自动跑一遍HTTP_Header_Check.py,检测到高危项直接阻断合并。
header-security-check: stage: test script: - pip install -r requirements.txt - python HTTP_Header_Check.py -u ${STAGING_URL} --fail-on-high only: - main--fail-on-high这个参数让脚本检测到高危项时以非零退出码结束,CI 任务随即失败,阻断后续构建流程。${STAGING_URL}是流水线预置的测试环境地址,不同分支可以注入不同的值。体系搭建初期可以把风险等级判定放宽,先只阻断反射型 Origin 和 CSP 缺失这两类条目,等团队消化了再逐步收紧策略。
我还有一个个人的处理习惯:检测脚本更新之后,强制跑三个验证目标——一个全新未配置的裸站点、一个故意写坏 CORS 的模拟站点、一个线上稳定运行的正式站点。三个结果分别对照预期,确认工具既不会漏报也不会误报,再把它接进团队共享的流水线。这套口子我踩过太多次,不验证直接上生产,最终只会换来一堆虚假警报。希望帮到你。
本文还有配套的精品资源,点击获取