修改响应包的2026年真相:服务器在“拒绝你”的那一刻,已经把钥匙递到了你手里
原创
klsec
klsec
昆仑AI安全实验室
2026年11月12日 11:38
广东
去阅读
2026年7月,HCL DFXAnalytics披露了一个账户接管漏洞,CVE-2026-56453。VulDB的分析把根因写得很直接:应用没有实现响应完整性校验,攻击者可以在HTTP响应到达客户端之前拦截并修改它,操纵认证或授权逻辑,绕过控制,接管目标账户。同一份分析里还有一句话,精确地概括了2026年修改响应包漏洞的全部逻辑:“攻击者可以修改包含认证令牌、会话标识符或授权决策的HTTP响应,而客户端应用对此毫无察觉。”
客户端信任服务器返回的每一个字节。它信任状态码,信任JSON里的success字段,信任verified的布尔值,信任match的结果,信任amount的数字。而响应包,是攻击者通过一个代理就能改写的文本。 当客户端用“服务器的回答”来做安全决策时,服务器的回答就不再是一个事实,它是一个可以被任意编辑的建议。
一、认证层:服务器在“拒绝”里塞了一张有效的通行证
最经典的修改响应包漏洞,逻辑简单到荒谬,但2026年仍然在出现。
一个叫iPsalmy的安全研究员在一个模拟私人银行的靶场里复现了这个模式。登录端点在校验失败时返回401,响应体是:
{ \"success\": false, \"message\": \"Invalid email or password.\", \"token\": \"eyJhbGciOiJIUzI1NiJ9...\", \"envelope\": \"AUTH_FAILED\"}
后端已经创建了会话,签发了token,然后才决定“凭证错误”,把拒绝和token一起发给了客户端。 前端只检查状态码。401显示错误,200读取响应体、取出token、当作已认证处理。攻击者在Burp里把状态行从401改成200,放行。一个字节的翻转,一次失败的登录变成了完整登录,那个JWT在仪表盘、会话端点、所有期望会话的地方都有效。
这个模式的根源不在“前端只检查状态码”这一个选择。根源在于服务器在拒绝响应中包含了本不该出现在拒绝响应里的东西——一个有效的token。响应体的内容是“你失败了”,但响应体的载荷里躺着一把钥匙。客户端拿到了这把钥匙,但它选择了相信“你失败了”这个信封,而不是信封里的东西。当攻击者把信封换成一个“你成功了”的信封,客户端就打开了它,拿走了钥匙。
Cap-go的CVE-2026-56073是同一个逻辑在OTP验证上的版本。攻击者拦截OTP验证请求,修改HTTP响应,把验证标记为“成功”,而实际上没有任何验证发生,从而启用双因素认证并接管账户。VulDB的分析指出,系统“在没有适当验证机制的情况下信任服务器响应” ,攻击向量是“OTP验证工作流中缺少密码学验证或完整性检查,使得HTTP响应可以被中间人操纵”。
二、MFA层:你伪造的是“设备说它验证过了”,而服务器相信了设备
GitLab的CVE-2026-0723把修改响应包从“改HTTP响应”扩展到了“改认证协议的响应”。漏洞的描述是:拥有受害者凭证ID的攻击者,可以通过提交伪造的设备响应来绕过双因素认证,影响18.6.4、18.7.2、18.8.2之前的版本。
这里的“设备响应”不是浏览器和服务器之间的HTTP响应,是WebAuthn/FIDO2协议中认证器(设备)返回给服务器的签名断言。服务器验证这个断言,如果有效,就认为“用户完成了第二因素”。伪造的设备响应,意味着攻击者构造了一个服务器会接受的断言,而它并不是由受害者的真实认证器生成的。
这和改HTTP状态码是同一个结构:服务器相信了一个“来自认证链路中某个组件的声明”,而这个声明在到达服务器之前,可以被攻击者替换成一个看起来有效的声明。 HTTP响应的{\"verified\": true}是一个声明。WebAuthn的设备响应是一个声明。服务器验证的是声明的“形式”,而不是声明背后的“事实”。
三、支付层:你付了一块钱,然后告诉系统“我付了全款”
支付场景的修改响应包,在2026年有两个精确的标本。
mews/pos的CVE-2026-118377(CVSS 8.7)的根因是“数据真实性验证不足” 。GarantiPos、PayForPos和InterPos的3D Pay和3D Host处理器跳过了check3DHash(),攻击者可以提交被篡改的status、amount或order ID字段,在未支付的情况下完成订单,无需认证。check3DHash()是支付网关用来验证“这个支付结果确实来自网关,没有被篡改”的密码学校验。跳过它,等于让客户端把“我付了多少钱、付没付成功”这些事实自己声明。攻击者声明了一个虚假的事实,服务器接受了它。
Sylius的CVE-2026-100872(CVSS 8.7)走的是时间窗口路线。漏洞在于购物车重新计算时没有验证支付金额,攻击者可以在网关交易发起之后修改订单总额。攻击者先支付一个小额,在网关捕获之后把订单扩大,系统把膨胀后的订单标记为“已全额支付”,而网关实际只捕获了原始金额。
这两条缝的共同逻辑是:支付的“完成”是由一个可以被客户端影响的声明来决定的。在mews/pos里,声明是回调里的amount和status。在Sylius里,声明是重新计算之后的订单总额。服务器没有用一个独立的、客户端无法触及的真相源来验证这些声明——它没有去问支付网关“你实际收到了多少钱”,它相信了客户端告诉它的数字。
四、OAuth层:token在你“看不到”的片段里,但攻击者能看到
OAuth的响应包篡改,不是“改状态码”,是利用响应承载token的方式,让token到达一个它不该到达的地方。
CVE-2026-11102是OAuth2隐式授权的片段劫持。授权服务器没有对redirect_uri做白名单校验,攻击者提交一个恶意URI,用户认证之后,access token通过URL片段泄露到攻击者的页面,导致账户接管。这里的“响应”是重定向响应,token被放在#access_token=...的片段里。如果客户端或中间层把包含片段的完整URL当作一个“数据”来传递、记录或转发,token就脱离了它本应只存在于客户端内存中的约束。
guzzle的CVE-2026-67354把这条缝推到了HTTP客户端库的层面。当Guzzle启用allow_redirects => ['referer' => true]并跟随重定向时,RedirectMiddleware直接从原始请求URI构造Referer头,没有剥离URI片段。任何嵌入在请求URL里的片段——比如#token=abc123或#state=xyz——被原封不动地写进Referer头,发送到重定向目标服务器。目标服务器从Referer里读取它。RFC 3986明确规定片段是客户端侧的数据,永远不应该被发送到服务器,但Guzzle把它传了过去。
这是一个“响应包篡改”的镜像。 你不需要改响应,你只需要让一个本来只应该在客户端内部流转的秘密,被写进一个会发送给外部服务器的头里。token没有“泄露”,它是被主动运输到了一个错误的目的地。
五、测试修改响应包漏洞时,你在测什么:不是“能不能改”,是“客户端用响应里的哪个字段做安全决策”
2026年的这些CVE指向同一个测试方法论:找出所有“服务器返回一个声明,客户端根据这个声明决定是否放行”的地方。
第一,在认证/MFA流程里,找“拒绝响应中的有效载荷”。 用一个错误的凭证登录,在Burp里查看响应体。如果拒绝响应里包含token、session ID、或者任何形式的有效凭证,这个响应就是一个候选。把状态码改成200,或者把success: false改成true,看客户端是否接受。Cap-go的OTP验证、iPsalmy的银行靶场,都是这个模式。
第二,在支付流程里,找“回调/响应中的金额和状态字段”。 提交一个支付回调,查看请求体里有没有amount、status、orderId、sign这些字段。如果sign或hash校验可以被跳过(或者根本没有),直接修改amount和status,看订单是否被标记为已支付。mews/pos的check3DHash()跳过,是这个漏洞的精确标志。Sylius的“网关捕获后扩大订单”,测试的是金额校验和订单状态更新之间的时间窗口。
第三,在OAuth流程里,找“片段承载的token”。 检查授权响应是否使用response_mode=fragment。检查redirect_uri是否被严格白名单校验。检查任何记录、转发或构造Referer的中间件,是否会剥离片段。guzzle的漏洞说明,一个“便利选项”可以把一个客户端侧的秘密变成一个外发头里的明文。
写在最后
修改响应包漏洞在2026年仍然高频,不是因为开发者“不知道要校验”。是因为客户端和服务器之间的信任边界,被错误地画在了“响应的内容”上,而不是“响应的来源和完整性”上。
服务器说“你失败了”,但响应体里带着token。服务器说“验证成功”,但这个“成功”是一个可以被代理改写的布尔值。服务器说“支付完成”,但这个“完成”基于一个客户端声明的金额,而不是网关确认的金额。服务器说“token在片段里”,但一个中间件把片段写进了Referer。
每一次,客户端都做了它被要求做的事:读响应,按响应里的字段做决策。它没有做错。它只是相信了一个不该被相信的东西——一个没有经过完整性校验的、可以被任何中间人重写的声明。
下次你测一个登录、一个OTP、一个支付回调、一个OAuth流程,不要只问“这个请求能不能被篡改”。问:这个流程的“通过/失败”决策,依赖的是响应里的哪个字段?这个字段,有没有一个独立于响应本身的、客户端无法伪造的验证来源? 如果答案是没有,那条缝就在那里。
严正声明
本文所述所有漏洞分析、CVE案例及测试技术,仅用于已获得明确书面授权的安全测试、代码审计、红队演练和安全研究场景。CVE-2026-56453(HCL DFXAnalytics)已在对应版本中修复;CVE-2026-56073(Cap-go)已在12.128.2中修复;CVE-2026-0723(GitLab)已在18.6.4、18.7.2、18.8.2中修复;CVE-2026-118377(mews/pos)和CVE-2026-100872(Sylius)的修复版本分别为2.1.16/2.2.9和mews/pos 2.0.0之后;CVE-2026-11102(OAuth2隐式授权)和CVE-2026-67354(guzzle)的验证必须在授权范围内进行,并及时更新至修复版本(guzzle 7.15.1+)。所有测试必须在SRC平台或客户授权的资产范围内进行,靶场环境应部署在隔离网络中。未授权扫描、测试、攻击行为违反《中华人民共和国网络安全法》第27条及《刑法》第285条,将承担法律责任。技术无罪,边界是法律。
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论