发布于8小时前8小时 在网站建设和服务器维护中,接入 CDN、WAF 或反向代理加速器后,常见问题并不是单一漏洞,而是代理信任链配置不当:源站管理端口被直接暴露、应用错误信任客户端请求头、内网服务通过代理路径被访问,最终导致权限边界失效。本文以一次授权渗透测试为背景,说明如何在不破坏业务的前提下定位这类问题,并给出可落地的修复配置。一、测试场景与边界目标网站结构如下:公网域名经过加速器后访问 Nginx,Nginx 再转发到 PHP 或 Java 应用;同一台服务器上还运行着仅供内网调用的管理 API。测试范围包括域名、加速器回源地址和授权的业务账号,不包括压力测试、批量扫描和真实数据修改。公网入口: IP 访问 443 端口管理路径:/admin/,应只允许办公网访问内网接口: CDN。部分加速器会改写响应头,测试时应同时核对 DNS、TLS 证书、源站访问日志和加速器回源日志。授权范围内可以先执行被动查询和低频请求:dig +short curl -skI curl -sk --resolve -o /dev/null -D -如果通过域名访问时命中加速器,而使用历史 DNS、证书透明度记录、资产台账中发现的源站地址可以直接返回业务内容,就说明源站绕过风险存在。这里不要对未知地址进行端口爆破,应先通过资产清单、云安全组和服务商控制台确认归属。三、反向代理配置中的三个高风险点1. 源站未限制回源来源加速器的作用是隐藏源站并统一接入,但如果云安全组允许全网访问 80/443,攻击者可能直接绕过 WAF、限速和访问控制。修复时应将安全组和主机防火墙同时收敛到加速器公布的出口网段,并保留运维跳板机的独立管理入口。2. 错误信任 X-Forwarded-For应用经常根据 X-Forwarded-For 判断客户端 IP。如果 Nginx 对任意来源都直接使用该请求头,公网请求者可以伪造办公网地址,绕过管理端路径限制。正确做法是先定义可信代理网段,再由 Nginx 重建客户端地址,应用只读取经过代理清洗后的变量。3. 管理接口与业务接口共用代理规则将整个站点统一转发到后端,容易把本应只监听回环地址的调试端点、健康检查端点和管理 API 暴露出来。管理路径应采用独立 location,明确允许来源、认证方式和日志级别,不能仅依靠前端页面隐藏入口。四、Nginx 配置示例下面示例假设加速器出口网段为文档中的保留地址,实际部署时应替换为服务商公布并经过核验的地址。示例同时禁止用户伪造原始客户端地址,并将管理路径限制在办公网。http { set_real_ip_from 198.51.100.0/24; real_ip_header X-Forwarded-For; real_ip_recursive on; log_format main_ext '$remote_addr|$realip_remote_addr|$request_id|$host|$request|$status|$body_bytes_sent|$http_x_forwarded_for'; access_log /var/log/nginx/access.log main_ext; server { listen 443 ssl; server_name location = /admin { return 301 /admin/; } location /admin/ { allow 192.0.2.0/24; deny all; proxy_set_header Host $host; proxy_set_header X-Request-ID $request_id; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass } location / { proxy_set_header Host $host; proxy_set_header X-Request-ID $request_id; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass } } }配置变更前使用 nginx -t 检查语法,确认无误后再平滑加载:sudo nginx -t sudo systemctl reload nginx sudo ss -lntp sudo journalctl -u nginx --since '10 minutes ago' --no-pager需要注意,set_real_ip_from 只允许可信代理网段。如果把它配置成 0.0.0.0/0,任何客户端都可以影响 remote_addr,等于主动放弃来源校验。五、内网接口的安全验证方法对疑似代理转发或 SSRF 问题,应使用低风险验证,不读取云实例密钥、环境变量或业务数据。优先验证一个无敏感信息的健康检查接口,并在服务端日志中确认请求是否真的到达。curl -sk -X POST \ -H 'Content-Type: application/json' \ --data '{"url":" \ -D /tmp/response.headers \ -o /tmp/response.body sed -n '1,20p' /tmp/response.headers head -c 500 /tmp/response.body如果业务功能确实需要服务端抓取外部 URL,应在应用层实施协议、域名和地址解析限制,禁止回环地址、链路本地地址、RFC1918 私网地址以及 IPv4/IPv6 的等价表示。不能只用字符串匹配判断,因为域名解析可能在校验后发生变化。更稳妥的方式是解析域名、对每个解析结果做地址分类,并在独立网络命名空间或出站代理中再次执行策略。六、日志留痕与时间线还原这类问题排查的关键是把加速器、Nginx、应用和系统日志串起来。建议所有层都传递同一个请求 ID,并统一使用 UTC 或明确记录时区。可以先按请求 ID 查询:sudo grep '8f3c2a' /var/log/nginx/access.log sudo journalctl --since '2025-01-01 10:00:00' --until '2025-01-01 10:10:00' | grep -E 'nginx|php|java' sudo grep -R 'X-Forwarded-For\|/admin/\|/api/fetch' /var/log/ 2>/dev/null | tail -n 100重点关注以下字段:真实客户端地址、代理链地址、Host、请求路径、响应状态、响应大小、用户标识、请求 ID 和后端处理耗时。若只记录了最终的 remote_addr,且没有保留代理来源,后续很难判断请求是否来自加速器、办公网还是伪造头部。七、权限边界与修复检查清单源站安全组仅允许加速器出口和受控运维网段,禁止公网直连。管理后台使用独立域名或独立入口,并叠加 VPN、办公网 ACL 和多因素认证。应用不直接信任客户端提交的 X-Forwarded-For、X-Real-IP 或自定义权限头。后端管理 API 仅监听回环地址或专用内网网卡,避免监听 0.0.0.0。代理转发功能实施 URL 规范化、DNS 重绑定防护、出站 ACL 和响应大小限制。修复后分别从加速器入口、源站地址和办公网进行验证,确认访问结果符合设计。检查修复前后日志,确认拒绝请求有记录但不泄露内部地址、堆栈和凭据。八、回归验证修复不应只验证页面能否打开,还要验证权限边界是否真正生效:公网访问管理路径应返回 403 或统一认证页面;直接访问源站应无法建立连接;伪造 X-Forwarded-For 不应改变应用看到的客户端地址;代理抓取功能访问回环和私网地址应被拒绝;正常业务请求仍应保留可追踪的请求 ID。实际项目中,最容易被忽略的是“源站已限制,但应用仍信任请求头”这一组合问题。网络层和应用层必须同时建立信任边界,单独依赖 CDN、Nginx 或前端隐藏入口都不足以形成权限控制。总结网站接入加速器后,安全重点从单纯的 Web 漏洞转向代理链、源站暴露、身份来源和内网访问边界。授权测试时应采用低频、可回滚的验证方式,以日志为依据还原请求路径,再分别从网络、代理、应用和系统权限四层修复。这样既能定位真实风险,也不会把排查过程变成对生产环境的破坏性操作。 服务器、云资产与权限边界梳理示意 网络请求、日志与边界流量分析示意
7小时前7小时 如果这里的“加速器”是 CDN 或边缘代理,最容易出问题的其实是代理信任链。源站不能一边接受任意公网回源,一边又相信客户端传来的 X-Forwarded-For,否则内网 IP 白名单和审计日志都可能被伪造。 建议先把链路固定成“公网 → 加速节点 → 源站 Nginx → 应用”,源站 443 在安全组或主机防火墙上只允许平台公布的回源网段,同时处理 IPv4、IPv6。不要把“源站域名不公开”当成访问控制。 Nginx 可以这样处理真实地址和链路日志,网段、真实 IP 头名称按平台文档替换: # 只信任加速平台的回源地址,不能写 0.0.0.0/0 set_real_ip_from 203.0.113.0/24; real_ip_header X-Forwarded-For; real_ip_recursive on; log_format trace escape=json '{"time":"$time_iso8601","rid":"$request_id",' '"client":"$remote_addr","peer":"$realip_remote_addr",' '"host":"$host","uri":"$request_uri","status":$status,' '"upstream":"$upstream_addr","ustatus":"$upstream_status",' '"rt":$request_time,"urt":"$upstream_response_time"}'; access_log /var/log/nginx/access_trace.log trace; upstream app_backend { server 127.0.0.1:8080; keepalive 32; } location / { proxy_pass proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 覆盖外部传入值,不把未经验证的地址链继续传给应用 proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Request-ID $request_id; add_header X-Request-ID $request_id always; proxy_connect_timeout 3s; proxy_read_timeout 30s; } 如果访客协议可能同时有 HTTP/HTTPS,不要无条件固定 https;应使用加速平台提供且经过源地址校验的协议头做映射。另一个常见坑是 proxy_pass 末尾的斜杠:proxy_pass 会保留原 URI,而 proxy_pass 在特定 location 下会重写前缀。 内网管理接口建议单独监听内网地址或单独虚拟主机,不要只靠某个可伪造的请求头判断: # 公网站点明确不暴露管理路径 location = /admin { return 404; } location ^~ /admin/ { return 404; } # 独立的内网管理入口 server { listen 10.10.0.5:8443 ssl; server_name admin.internal; allow 10.20.0.0/16; deny all; ssl_client_certificate /etc/nginx/ca/internal-ca.pem; ssl_verify_client on; location / { proxy_pass proxy_set_header X-Request-ID $request_id; } } 需要注意,启用 realip 模块后,Nginx 的 allow/deny 通常看到的是改写后的 $remote_addr,不是加速节点地址。回源节点白名单更适合放在安全组或防火墙;原始对端地址可从 $realip_remote_addr 记录和核对。 排障时可以按日志是否出现来快速定位: 加速平台有请求,源站 access log 没有:检查回源 DNS、端口、安全组、源站证书及 SNI。 源站有日志但 upstream/ustatus 为空:多半命中了错误的 server/location,或被 Nginx 本地规则拦截。 ustatus=502:检查应用监听地址、HTTP/HTTPS 协议是否一致;504 重点看应用阻塞和超时;499 表示加速节点在源站返回前断开。 应用日志是 2xx、边缘却返回 4xx/5xx:再查 CDN 缓存、WAF、响应体大小和边缘超时。 nginx -t && nginx -T ss -lntp journalctl -u nginx --since "10 min ago" # 保留 Host 和 SNI,直接验证指定源站 curl -vk --resolve example.com:443:198.51.100.20 \ # 从应用所在机器验证后端 curl -sv # 按响应中的请求 ID 串联源站与应用日志 grep '请求ID' /var/log/nginx/access_trace.log 最后,访问日志里建议保留请求 ID、两段 IP、上游状态和耗时,但不要直接记录 Authorization、Cookie 或含令牌的完整查询参数。这样既能定位是哪一层失败,也不会让排障日志本身变成新的权限泄漏点。
创建帐户或登录后发表意见