依靠 Content-Type: text/plain 来缓解恶意 JavaScript 执行作为响应是否安全

Is it safe to rely on Content-Type: text/plain to mitigate malicious javascript execution in response?

本文关键字:执行 JavaScript 响应 安全 是否 恶意 text Content-Type plain 依靠      更新时间:2023-09-26

我们有一个返回的 Web 应用程序


HTTP/1.1 400 Bad Request
...
Content-Type: text/plain;charset=UTF-8
Content-Length: 57
Date: Tue, 14 Apr 2015 19:24:54 GMT
Connection: close
Invalid project area item id 
<script>alert(1086)</script>

我的理解是,依靠Content-Type:text/plain;charset=UTF-8作为防止javascript执行的防御是不够的。相反,输出应该被编码,并且输入应该经过输入验证并丢弃垃圾。

我正在寻找的是一些关于处理具有 javascript 的响应的正确方法的清晰和官方答案,其中内容类型已设置为文本/纯文本。

任何人都有指向此场景的官方示例的链接(或答案)以及处理它的正确方法? 还是只需要内容类型:text/plain;charset=UTF-8?

以下是两种情况。

顶级 XSS

如果攻击者可以操纵顶级 URL 以响应格式错误的请求,例如

HTTP/1.1 400 Bad Request
...
<script>alert(document.cookie)</script>

然后设置Content-Type: text/plain缓解 XSS 攻击(请参阅下面的详细答案)。

AJAX XSS

但是,如果攻击者可以操纵目标网页中的某些 AJAX 函数并诱骗它执行类似 $("#result").html(xss_request_result) 的操作,那么这将有效地将文本加载到 Web 上下文中,并且它将被浏览器(包括 JS)解析,并且所有赌注都被关闭

明智的做法是对此类错误消息的响应进行实体编码或标记剥离。


关于第一种情况,根据 w3.org,

文本

的主要子类型是"纯文本"。这表示纯文本(未格式化)。互联网邮件的默认内容类型,"文本/纯文本;charset=us-ascii",描述了现有的互联网实践,也就是说,它是 RFC 822 定义的主体类型。

这意味着不应解释和处理文本/纯文本。然而,谷歌(2011年3月30日更新)指出,

如果 Content-Type 匹配通用值之一,例如应用程序/八位字节流、应用程序/未知,甚至文本/纯文本,许多浏览器会将其视为根据上述信号对值进行二次猜测的权限,并尝试提出更具体的东西。此步骤的基本原理是,某些配置不当的 Web 服务器在所有返回的内容上回退到这些类型。

根据一项名为"HTML是否在文本/纯文档上嗅探(URL中带有或不带有文件扩展名)?"的浏览器嗅探调查,结果是:

  • IE浏览器9+:否
  • 火狐:否
  • 歌剧:否
  • 铬:否
  • 安卓:否
  • 野生动物园:

所以是的,将内容类型设置为带有显式字符集的文本/纯文本将缓解 XSS 攻击,但从上面的调查来看,Safari 可能是一个坚持。

测试您的浏览器是否存在此漏洞。转到一个更慷慨的在线PHP小提琴网站(例如 http://phptester.net/)并执行以下操作。您不应该看到弹出窗口。

<?php
header("Content-Type: text/plain");
echo "<script>alert(1)</script>";

有关内容嗅探 XSS 攻击的更多信息 (PDF)

https://www.rfc-editor.org/rfc/rfc2046"text/plain"不应该处理指令类型,而应该简单地看作是一个线性的字符序列。

>上面的Drakes答案让我感到困扰,所以我创建了一个简单的概念证明,看看我是否正确。 我是。 即使有Content-Type: text/plain;charset=UTF-8应用程序也可能受到简单的 XSS 攻击的影响。

正如我第一次尝试在下面解释的那样,原因是数据处理很重要,以及数据的最终目标和呈现上下文。 运输并不那么重要。我创建了一个简单的 servlet,它返回的响应就像 OP 一样,包括 Content-Type 标头。这是该响应:

HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Cache-Control: no-cache
Content-Type: text/plain;charset=UTF-8
Content-Length: 73
Date: Thu, 18 Jun 2015 22:49:01 GMT
Connection: close

Invalid project area item id <iframe src=javascript:alert(1)></iframe> 

这是结果的图像。请注意,攻击有效负载已执行:https://flic.kr/p/uRnSgo

同样,原因很简单。数据不是在 AJAX 请求中呈现,而是呈现在使用 Web 应用程序页(即 HTML 页)中。

无论如何,我希望这消除了在某些情况下脆弱的任何疑虑......特别是当响应是针对将在消费页面中呈现的 AJAX 请求时。

----- 以下是我最初的回应。 -----

带有错误消息的 400 响应对我来说闻起来像 REST API 响应。

如果这是一个 REST 请求(请求标头中X-Requested-With: XMLHttpRequestAccept: application/json),那么您将面临一个严重的问题。 尽管此响应不受影响,但使用页面可能会在最终用户的 UI 中选取并显示数据。 由于它没有正确编码,它将执行。 您需要担心的并不总是这种响应,而是攻击有效负载的最终处置。假设这是对XMLHttpRequest或REST调用的响应,这是一个严重的错误。

您可以使用 <iframe src=javascript:alert(1)></iframe> 的攻击有效负载进行测试,我敢打赌您会在消费应用程序中看到该弹出窗口。

我建议: Invalid project area item id省略无效值。最便宜的解决方案。

所以,不,你一般不能依靠Content-Type来拯救你。数据可能会显示在将执行的另一个上下文中。

始终验证输入并正确处理输出,其中可能包括某种格式或其他格式的编码,具体取决于呈现它的上下文。任何告诉你其他事情的人都是在试图摆脱一些必要的工作。:-)