ASPX站点BREACH隐私违规修复求助:IIS压缩禁用失效及方案咨询
咱们先梳理下当前的情况:站点被检测出存在BREACH隐私违规,官方给出的修复方案有三个:
- 禁用HTTP压缩
- 确保用户输入与机密信息不在同一响应内容中
- 随机化机密信息
IIS压缩禁用的异常情况
我们已经在IIS的「压缩」设置里取消了静态和动态压缩的勾选,这个操作在DEV环境没问题,但到了PRODUCTION服务器就失效了——明明关了压缩,响应头里还是显示content-encoding: gzip。这里要明确:判断HTTP压缩是否真的禁用的标准是响应头中没有content-encoding字段。
给你贴一下PROD服务器的示例响应头(请求头也附在后面):
Cache-Control: private Connection: Keep-Alive Content-Encoding: gzip Content-Length: 71447 Content-Type: text/plain; charset=utf-8 Date: Thu, 24 May 2018 16:57:04 GMT Server: Microsoft-IIS/7.5 Strict-Transport-Security: max-age=31536000; includeSubDomains Vary: Accept-Encoding X-AspNet-Version: 4.0.30319 X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-XSS-Protection: 1; mode=block --- Request Header --- Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.5 Cache-Control: no-cache Connection: keep-alive Content-Length: 92398 Content-Type: application/x-www-form-urlencoded; charset=utf-8 Cookie: .ASPXANONYMOUS=fMbt3RErereq1AEkAAA…nId=00y51efaerreuc3pw0erereyehwc2wzxk Host: example.org Pragma: no-cache Referer: https://example.org/dsearch.aspx User-Agent: Mozilla/5.0 (Windows NT 6.1; W… Gecko/20100101 Firefox/60.0 X-MicrosoftAjax: Delta=true X-Requested-With: XMLHttpRequest
先插一句关于PROD压缩关不掉的可能原因:大概率是上层有代理(比如CDN、负载均衡器)偷偷开启了压缩,或者IIS的服务器级压缩设置覆盖了站点级的设置,也有可能web.config里还保留着启用压缩的配置。可以检查下web.config里的<httpCompression>和<urlCompression>节点,确保dynamicCompressionEnabled和staticCompressionEnabled都设为false。
针对指定参数应用修复方案2和3的实操建议
接下来咱们重点说怎么把修复方案2和3用到你提到的这两个参数上:
第一个参数:TSM_HiddenField_=ctl00_ContentPlaceHolder1_ToolkitScriptManager1_HiddenField&_TSM_CombinedScripts_=%3b%3bAjaxControlToolkit%2c+Version%3d3.5.7.123%2c+Culture%3dneutral%2c+PublicKeyToken
第二个参数:ctl00_ContentPlaceHolder1_ToolkitScriptManager1_HiddenField=&__EVENTTARGET=&__EVENTARGUMENT=&__LASTFOCUS=PRexdxaxbhgeccgjdchdfcgcdefRP(响应体中被修改)
落实修复方案2:分离用户输入与机密信息
首先得明确:这里的「用户输入」指的是用户提交的内容(比如__EVENTTARGET、__EVENTARGUMENT里可能带的用户操作数据),「机密信息」则是ToolkitScriptManager1_HiddenField里的内容(通常是视图状态、脚本管理的令牌这类敏感数据)。
- 把用户输入对应的响应内容和含机密的部分拆分开:比如用AJAX发起两个请求,一个专门提交用户输入并返回非敏感的响应,另一个单独获取包含机密信息的HiddenField内容;或者把机密信息放到HTTP-only的Cookie里,而非响应体中,避免和用户输入的内容混在同一个响应里。
- 检查
_TSM_CombinedScripts_参数:如果这个参数里包含的是脚本的哈希或固定标识符,尽量不要让它和用户输入的参数出现在同一个请求/响应中,或者把它的内容移到单独的静态资源请求里,因为静态资源可以单独处理,不和用户输入的动态响应混在一起。
落实修复方案3:随机化机密信息
对于这类ASP.NET AJAX Toolkit生成的HiddenField和相关参数,核心是让敏感内容每次请求都不一样:
- ToolkitScriptManager的HiddenField:这个字段通常存储的是脚本的加载状态或加密的视图状态片段。可以在后台代码中每次请求都重新生成这个字段的值,比如加入随机的盐值,或者使用ASP.NET的
Session来关联动态生成的令牌,而不是用固定的内容。另外,检查是否开启了视图状态的随机化——在web.config里设置<pages viewStateEncryptionMode="Always" viewStateUserKey="YourRandomKey" />,viewStateUserKey可以用用户的Session ID或其他唯一标识,让视图状态每次请求都有不同的加密上下文。 _TSM_CombinedScripts_参数:如果这个参数是固定的脚本组合标识符,可以改成动态生成的临时标识符,每次请求都生成一个新的ID来映射对应的脚本组合,这样即使攻击者捕获了多个响应,也没法通过重复的模式来还原机密信息。__LASTFOCUS参数:这个参数记录的是用户最后聚焦的控件ID,如果它属于敏感内容(比如关联了用户的操作轨迹),可以每次请求都对它进行随机化处理,比如加密时加入随机因子,或者直接在响应中不返回真实的聚焦ID,而是用一个临时的映射ID,后台再转换回来。
最后再提醒下:BREACH攻击利用的是压缩后响应的重复模式,所以只要打破“用户输入+固定机密”的重复组合,攻击就很难奏效。如果禁用压缩实在搞不定,把修复方案2和3落实到位也能有效防御。
内容的提问来源于stack exchange,提问作者user3068724

