建议在Web服务器上禁用OPTIONS方法

我上周给一个客户做安全审计,建议发现他们的服方法Nginx服务器对OPTIONS请求的响应头里赫然写着`Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS`。这不是上禁什么大漏洞,但就像你家大门没锁侧窗——真正的建议小偷不一定会走,但所有路过的服方法人都能看见你家里有什么。

OPTIONS方法本身是上禁无害的。它就是建议个询问机制,客户端问服务器“你支持哪些方法”,服方法服务器回答一下。上禁问题在于,建议这个回答等于把你的服方法攻击面画了张地图送给对方。攻击者拿到的上禁信息越多,构造恶意请求就越精准。建议比如看到有PUT,服方法就知道可以试试上传恶意文件;看到有DELETE,上禁就知道可能尝试越权删除资源。

更麻烦的是,某些Web应用防火墙(WAF)对OPTIONS请求的处理比较宽松。攻击者可以先用OPTIONS探测出服务器支持的HTTP方法,再针对性地绕过WAF规则。我见过一个真实案例,某电商平台因为开放了OPTIONS,攻击者发现后端支持DEBUG方法,直接调出调试接口拿到了数据库配置信息。虽然这是应用层的问题,但OPTIONS在其中扮演了引路人的角色。

有人会反驳说,禁用OPTIONS会影响CORS(跨域资源共享)预检请求。确实,浏览器在发起跨域非简单请求前会先发一个OPTIONS。但注意,CORS预检请求会带`Access-Control-Request-Method`头,服务器完全可以只响应带这个头的OPTIONS,而不是对所有OPTIONS都返回Allow列表。Nginx里加个判断条件就行:

if ($request_method = OPTIONS) {  if ($http_access_control_request_method = "") {  return 403; } } 

这段配置的意思是:如果收到OPTIONS请求但没有CORS预检头,直接拒绝。这样既不影响正常跨域请求,又堵住了信息泄露的口子。当然,如果你的应用根本不涉及跨域,那就更简单了——直接在location块里`return 405`。

我的建议是,无论什么场景,都别让OPTIONS请求返回完整的Allow列表。即使你不想完全禁用,至少把响应头里的Allow字段改成`Allow: GET, HEAD`这种最小化声明。别让服务器当话痨,该沉默时就沉默。

实际操作起来,Apache用户可以用`<LimitExcept>`指令,IIS用户可以在请求筛选器里隐藏方法。但最省事的办法还是从应用层入手——如果你的框架支持路由白名单,就只放行GET和POST,其他方法一律404。毕竟,一个正常的Web应用,99%的情况只需要GET和POST就够了。

最后说个让我印象深刻的细节。那次审计结束后,客户问我:“禁了OPTIONS,会不会影响搜索引擎抓取?”我反问他:“你见过Googlebot发OPTIONS请求吗?”他愣了两秒,笑了。搜索引擎用的是GET,用户浏览器用的是GET或POST,只有工具和攻击者才会对OPTIONS感兴趣。你不需要讨好工具,更不需要给攻击者递刀子。