0

PowerShell Invoke-WebRequest 安全头批量检测:3个实战脚本让网站安全巡检自动化

2026.06.02 | youres | 25次围观

为什么要用PowerShell做安全头检测

在Linux服务器上,大家习惯用curl检查网站的Strict-Transport-SecurityContent-Security-PolicyX-Frame-Options等安全响应头。但到了Windows环境,情况就变了:

  • Windows自带的curl其实是Invoke-WebRequest的别名,行为跟Linux curl完全不同
  • PowerShell 5.x 的Invoke-WebRequest输出格式跟curl截然不同,解析响应头很麻烦
  • 批量检测多个域名时,curl脚本在Windows上经常遇到编码乱码问题

直接用PowerShell写检测脚本,不仅原生兼容Windows,还能把结果导出成Excel直接打开的CSV文件,运维效率提升一大截。

实战脚本一:基础版——单域名安全头检测

先上一个最基础的版本,适合手动排查单个域名:

# 检查单个域名的安全响应头
function Test-SecurityHeaders {
    param([string])
    try {
         = Invoke-WebRequest -Uri  -UseBasicParsing -TimeoutSec 10
         = .Headers
         = [PSCustomObject]@{
            Url = 
            StatusCode = .StatusCode
            HSTS = .'Strict-Transport-Security'
            CSP = .'Content-Security-Policy'
            XFrameOptions = .'X-Frame-Options'
            XXSSProtection = .'X-XSS-Protection'
            XContentTypeOptions = .'X-Content-Type-Options'
            ReferrerPolicy = .'Referrer-Policy'
            PermissionsPolicy = .'Permissions-Policy'
        }
        return 
    } catch {
        Write-Warning "请求失败:  - "
        return 
    }
}

# 用法
Test-SecurityHeaders -Url 'https://www.youres.cn'

关键点说明:

  • -UseBasicParsing参数必须加,否则PowerShell会启动IE引擎解析HTML,在服务器上会报错
  • .Headers是字典结构,直接用键名取值,不区分大小写
  • 超时设10秒,避免某个域名挂了把整个脚本卡死

实战脚本二:批量版——并行检测多个域名

单个域名不够用,实际运维中要一次性检查几十个域名。用ForEach-Object -Parallel(PowerShell 7+)可以大幅提升速度:

# 批量检测多个域名的安全头(PowerShell 7+ 并行版)
 = @(
    'https://www.youres.cn',
    'https://blog.youres.cn',
    'https://api.youres.cn'
)

 =  | ForEach-Object -Parallel {
     = 
    try {
         = Invoke-WebRequest -Uri  -UseBasicParsing -TimeoutSec 10
        [PSCustomObject]@{
            Url = 
            StatusCode = .StatusCode
            HSTS = .Headers.'Strict-Transport-Security'
            CSP = .Headers.'Content-Security-Policy'
            XFrameOptions = .Headers.'X-Frame-Options'
            XXSSProtection = .Headers.'X-XSS-Protection'
            XContentTypeOptions = .Headers.'X-Content-Type-Options'
            ReferrerPolicy = .Headers.'Referrer-Policy'
            PermissionsPolicy = .Headers.'Permissions-Policy'
            CheckTime = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss')
        }
    } catch {
        [PSCustomObject]@{
            Url = 
            StatusCode = 'ERROR'
            HSTS = ''
            CSP = ''
            XFrameOptions = ''
            XXSSProtection = ''
            XContentTypeOptions = ''
            ReferrerPolicy = ''
            PermissionsPolicy = ''
            CheckTime = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss')
        }
    }
} -ThrottleLimit 10

 | Format-Table -AutoSize

这个版本的核心优势:

  • -ThrottleLimit 10:最多同时跑10个请求,比串行快5-8倍
  • 异常捕获:某个域名挂了不影响其他域名的检测结果
  • PowerShell 5.x用户可以用Invoke-Parallel模块或Start-Job实现并行,只是代码更啰嗦

实战脚本三:CSV报告版——直接生成Excel可打开的巡检报告

巡检完要出报告,最实用的做法是将结果导出为CSV文件。这里有个坑:PowerShell 5.x的Export-Csv默认是UTF-8无BOM,Excel打开中文直接乱码。正确做法:

# 导出CSV报告(兼容Excel打开中文)
 = Get-Content 'C:\scripts\domains.txt'

 = foreach ( in ) {
    try {
         = Invoke-WebRequest -Uri  -UseBasicParsing -TimeoutSec 10
        [PSCustomObject]@{
            Url = 
            StatusCode = .StatusCode
            HSTS = .Headers.'Strict-Transport-Security'
            CSP = .Headers.'Content-Security-Policy'
            XFrameOptions = .Headers.'X-Frame-Options'
            XXSSProtection = .Headers.'X-XSS-Protection'
            XContentTypeOptions = .Headers.'X-Content-Type-Options'
            ReferrerPolicy = .Headers.'Referrer-Policy'
            PermissionsPolicy = .Headers.'Permissions-Policy'
            CheckTime = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
        }
    } catch {
        [PSCustomObject]@{
            Url = 
            StatusCode = 'ERROR'
            HSTS = ''; CSP = ''; XFrameOptions = ''
            XXSSProtection = ''; XContentTypeOptions = ''
            ReferrerPolicy = ''; PermissionsPolicy = ''
            CheckTime = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
        }
    }
}

# PowerShell 5.x 用UTF-8 BOM,Excel才能正常打开中文
 = 'C:\scripts\security-header-report.csv'
 | Export-Csv -Path  -Encoding UTF8 -NoTypeInformation

# PowerShell 7 用默认UTF-8无BOM即可,Excel 2016+能正确识别
#  | Export-Csv -Path  -NoTypeInformation

关于编码的说明(这个坑踩过好几次):

  • PowerShell 5.x:Export-Csv -Encoding UTF8 输出的是UTF-8 BOM,Excel能直接打开,中文正常
  • PowerShell 7:默认输出UTF-8无BOM,Excel 2016及以上版本也能识别,不需要BOM
  • 如果Excel打开还是乱码,用Notepad++转成ANSI(即GBK)是最快的解决办法

安全头评分规则(Security Headers标准)

检测出结果后,怎么判断是不是合格?参考Security Headers的评分标准:

安全头推荐值扣分项
Strict-Transport-Securitymax-age=31536000; includeSubDomains未配置或max-age<1年
Content-Security-Policy明确指定允许的域名,不用unsafe-inline未配置或用通配符*
X-Frame-OptionsDENY 或 SAMEORIGIN未配置
X-Content-Type-Optionsnosniff未配置
Referrer-Policystrict-origin-when-cross-origin未配置或unsafe-url
Permissions-Policy明确禁用不需要的API未配置

与curl方案对比:为什么选PowerShell

对比项curl(Linux)PowerShell(Windows)
安装依赖一般已预装Windows自带,无需安装
批量并行需要xargs -P一行-Parallel搞定
CSV导出需要手动格式化Export-Csv原生支持
中文编码需要注意locale设置Encoding参数直接控制
与Windows任务计划集成需要Cygwin或WSL原生支持,直接加计划任务

进阶:配合钉钉机器人做告警推送

脚本检测到安全头缺失时,可以自动推送到钉钉群。把下面的函数加进脚本即可:

function Send-DingTalkAlert {
    param([string])
     = 'https://oapi.dingtalk.com/robot/send?access_token=你的token'
     = @{ msgtype = 'text'; text = @{ content =  } } | ConvertTo-Json -Depth 3
    Invoke-RestMethod -Uri  -Method POST -Body  -ContentType 'application/json'
}

# 在检测结果里判断,缺失重要安全头就告警
foreach ( in ) {
    if (-not .HSTS) {
        Send-DingTalkAlert -Text "告警: 缺失 HSTS 安全头!"
    }
}

总结

用PowerShell做安全头批量检测,最大的优势是原生兼容Windows、并行简单、CSV报告开箱即用。三个脚本从单域名到批量并行再到CSV报告,覆盖了从手动排查到自动化巡检的完整路径。配合任务计划程序和钉钉告警,可以搭建一套完整的网站安全监控体系。

下一步可以扩展的方向:加入HSTS max-age的分阶段配置策略,以及用curl交叉验证PowerShell检测结果,确保监控数据的准确性。

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论