jQuery 的 $.get() 调用不受信任的 URL 是否安全?
Is jQuery's $.get() safe to call on an untrusted URL?
最近得知jQuery的$.getJSON()
是not safe to call on an untrusted URL。 $.get()
呢?当 URL 参数来自不受信任的来源时,调用 jQuery 的 $.get()
是否安全,或者这是不安全的?
这是在我进行的安全代码审查中出现的,目的是检查 XSS 漏洞。示例代码模式:
$.get(url, function (...) { ... })
如果攻击者选择 url
恶意,此 Code Pattern 是否会产生 XSS 漏洞?
请假设该函数将安全地处理来自 AJAX 请求的响应,并且 url
来自不受信任的来源(例如,其他用户)并且可以完全由对手.
我担心的是:如果攻击者选择了 url
,攻击者是否可以选择恶意的 URL(例如,包含 callback=?
并指向他们自己的站点,或者一些聪明的东西像那样)导致jQuery猜测数据类型应该是JSONP,启用JSONP,在文档中插入脚本标签,并引入XSS漏洞in the same way that getJSON() does? (Since I'm not passing an explicit dataType
argument to $.get()
, jQuery will guess the data type, as described in the docs。我不确定这对安全有何影响。)
我 运行 在代码审查中检查了这个 Code Pattern,我试图了解它是否是一个潜在的漏洞。我不是在寻找可以编写此代码的替代方法;相反,我想知道这种代码模式是否安全。
由于威胁模型有点棘手,让我举个例子来帮助更好地理解这一点。假设 Bob 是该服务的用户,他可以提供与他的个人资料相关联的 URL。假设当 Alice 在她的浏览器中访问 Bob 的个人资料页面时,页面上的 Javascript 代码采用 Bob 提供的 URL 并将其作为参数传递给 $.get()
。问题是,这样安全吗?鲍勃可以用它来攻击爱丽丝吗? Bob 能否触发 Alice 的浏览器执行任意 Javascript 代码,并使用 Alice 的所有功能?正如链接问题所解释的那样,$.getJSON()
在这种情况下是不安全的——但是 $.get()
呢?是不安全,还是安全?
由于我收到了一些要求澄清的请求,让我尝试 explaining/asking 以不同的方式提出问题。假设我正在进行代码审查以检查某些 Javascript 代码是否包含任何 XSS 漏洞,并且我看到以下代码行:
$.get(url, function(resp) { /* do nothing */ });
假设我知道url
可以完全被攻击者控制。这会自动成为 XSS 漏洞吗?或者这总是安全的吗?或者如果答案是"it depends",它取决于什么?
或者,另一种思考方式。假设我正在进行代码审查,并且看到以下代码行:
$.get(url, f);
假设我知道url
可以完全被攻击者控制。我需要检查什么来验证这是否安全(没有 XSS 错误)?我知道我需要检查 f
的代码以查看它是否安全地处理响应,因为如果 f
粗心,它可能会引入 XSS 错误。我的问题是:这是我唯一需要检查的东西吗?或者无论 f
是如何编码的,这个代码模式总是一个 XSS 漏洞吗?
这是一个很好的观点。但是如何强制数据类型格式以确保它不会被用作 JSONP
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType // force text/plain
});
acutal $.getJSON()
是为了方便我们想加快解析速度,所以如果你真的了解安全性,请使用自定义的 $.ajax()
调用。
你知道,黑客可以简单地打开开发控制台并写入他想要的任何 $.get
,他甚至不必更改你的 url
变量。事实上,他可以 运行 绝对是他想要的任何代码,只要它不干扰相同的域策略。客户端安全的重点是确保这个人只能破解他自己。
因此无需尝试保护客户端的任何内容,想法是您不能信任来自浏览器的任何内容,因此您应该始终检查服务器中收到的数据,并允许两者之间的接口最少(了解您的参数、它们的类型等)。
视情况而定。
TL;DR 是的,在某些情况下它是不安全的。
如果:
那么攻击者就可以在你的页面上执行JS了。
具有匹配协议的恶意服务器,正确的 CORS headers (Access-Control-Allow-Origin: *
) 将能够在您的页面上执行 JS,这要归功于 jQuery 来自 Content-Type header(对于 JS 来说是 script
)。
您可以在 Whosebug 上的此页面上尝试示例(假设您使用的是 http
):
$.get('http://zensuite.net/js/alert.js', console.log.bind(console));
如果您想查看未设置 CORS header 时会发生什么:
$.get('https://zensuite.net/js/alert.js', console.log.bind(console));
相反,谈论您的假设,您不太可能设法jQuery将正常的 XHR 请求转换为远程包含脚本。
在简要查看 code 之后,我认为这不太可能发生(除非某处有错误),因为您只能在请求传输之前切换到 "remote script mode" 并且如果你的 dataType
是
json
当 URL 匹配 rjsonp
正则表达式时 /(=)\?(?=&|$)|\?\?/
;
jsonp
script
这些也容易受到攻击:
$.get('https://zensuite.net/js/alert.js?callback=?', console.log.bind(console), 'json');
$.get('https://zensuite.net/js/alert.js', console.log.bind(console), 'jsonp');
$.get('https://zensuite.net/js/alert.js', console.log.bind(console), 'script');
这当然与问题无关,因为您可以使用 $.get
来执行远程代码。
jQuery.get
是否存在 XSS 安全风险。
如果您查看 jQuery 的源代码(或 jQuery.get
的文档),您会发现 jQuery.get
和 jQuery.post
只是 [= 的包装器16=].
这里有两个问题:
- 如果
dataType
是jsonp
,或者URL以=?
结尾并且dataType
是json
,jQuery将尝试发出 JSONP 请求,然后 eval
脚本。
- 如果响应是脚本,jQuery 将执行该脚本 除非
dataType
是 json
并且 jsonp
选项设置为 false
.
因此,如果您将 dataType
设置为 json
,并将 jsonp
设置为 false
,则 可以安全地 调用 jQuery.get
表示未知 URL.
易受攻击的脚本
$.get(url, function(...) { ... });
安全脚本
$.ajax(url, { jsonp: false, dataType: 'json' }).done(function(...) { ... });
Does this code pattern create a XSS vulnerability, if an attacker chooses url maliciously?
编辑:是的,但不是你问题中的原因。
怪异的 auto-JSONP 功能在内部应用到 AJAX 使用 ajaxPrefilter("json jsonp")
的请求。所以它适用于 json
前置过滤器列表,但不适用于其他类型或默认的 *
。但是,预过滤器在响应发生之前应用,所以这不会仅仅因为服务器以 [=47=] 类型回复。
(目前——从 1.11.2 开始——getJSON
的文档没有描述这种 potentially-dangerous 行为准确触发的情况。get
和ajax
根本没有提到 auto-JSONP。所以也许它应该被认为是一个错误。当然考虑到 poorly-specified 这是如何,我不会依赖它在未来的版本中保持不变jQuery.)
它易受攻击的实际原因(如 framp 和 toothbrush 所证明的)是没有 dataType
参数 jQuery 会从响应中猜测一个。如果攻击者的 URL 命中了一个作为 JS-like Content-Type
的资源,jQuery 会猜测它是 JavaScript 和 eval
它。注意:为了使 AJAX 请求足够远以使其工作,对于 third-party 服务器上的资源,它必须包含 CORS headers.
$.get(url, function (...) { ... }, 'json');
此版本不易受到响应类型猜测的攻击。但是,它 容易受到 auto-JSONP 过滤器的攻击。
为了安全起见,您必须同时设置 dataType
选项 和 ,如果那个选项是 json
,还有 jsonp: false
选项。遗憾的是,您无法在 get()
方法中设置 jsonp
选项。您应该可以通过传入一个选项字典而不是参数来做到这一点,但是您不能这样做,因为 API 目前完全是 non-functional 因为 jQuery 是一团糟的破碎Do-What-I-Mean API 其行为(越来越)难以预测。
因此,从不受信任的 URL 获取 JSON 的唯一安全方法是通过基本 ajax
:
$.ajax(url, {dataType: 'json', jsonp: false});
根据 https://nvd.nist.gov/vuln/detail/CVE-2015-9251
,这是 jQuery < 3.0.0 的 XSS 漏洞
jQuery before 3.0.0 is vulnerable to Cross-site Scripting (XSS) attacks when a cross-domain Ajax request is performed without the dataType option, causing text/javascript responses to be executed.
最近得知jQuery的$.getJSON()
是not safe to call on an untrusted URL。 $.get()
呢?当 URL 参数来自不受信任的来源时,调用 jQuery 的 $.get()
是否安全,或者这是不安全的?
这是在我进行的安全代码审查中出现的,目的是检查 XSS 漏洞。示例代码模式:
$.get(url, function (...) { ... })
如果攻击者选择 url
恶意,此 Code Pattern 是否会产生 XSS 漏洞?
请假设该函数将安全地处理来自 AJAX 请求的响应,并且 url
来自不受信任的来源(例如,其他用户)并且可以完全由对手.
我担心的是:如果攻击者选择了 url
,攻击者是否可以选择恶意的 URL(例如,包含 callback=?
并指向他们自己的站点,或者一些聪明的东西像那样)导致jQuery猜测数据类型应该是JSONP,启用JSONP,在文档中插入脚本标签,并引入XSS漏洞in the same way that getJSON() does? (Since I'm not passing an explicit dataType
argument to $.get()
, jQuery will guess the data type, as described in the docs。我不确定这对安全有何影响。)
我 运行 在代码审查中检查了这个 Code Pattern,我试图了解它是否是一个潜在的漏洞。我不是在寻找可以编写此代码的替代方法;相反,我想知道这种代码模式是否安全。
由于威胁模型有点棘手,让我举个例子来帮助更好地理解这一点。假设 Bob 是该服务的用户,他可以提供与他的个人资料相关联的 URL。假设当 Alice 在她的浏览器中访问 Bob 的个人资料页面时,页面上的 Javascript 代码采用 Bob 提供的 URL 并将其作为参数传递给 $.get()
。问题是,这样安全吗?鲍勃可以用它来攻击爱丽丝吗? Bob 能否触发 Alice 的浏览器执行任意 Javascript 代码,并使用 Alice 的所有功能?正如链接问题所解释的那样,$.getJSON()
在这种情况下是不安全的——但是 $.get()
呢?是不安全,还是安全?
由于我收到了一些要求澄清的请求,让我尝试 explaining/asking 以不同的方式提出问题。假设我正在进行代码审查以检查某些 Javascript 代码是否包含任何 XSS 漏洞,并且我看到以下代码行:
$.get(url, function(resp) { /* do nothing */ });
假设我知道url
可以完全被攻击者控制。这会自动成为 XSS 漏洞吗?或者这总是安全的吗?或者如果答案是"it depends",它取决于什么?
或者,另一种思考方式。假设我正在进行代码审查,并且看到以下代码行:
$.get(url, f);
假设我知道url
可以完全被攻击者控制。我需要检查什么来验证这是否安全(没有 XSS 错误)?我知道我需要检查 f
的代码以查看它是否安全地处理响应,因为如果 f
粗心,它可能会引入 XSS 错误。我的问题是:这是我唯一需要检查的东西吗?或者无论 f
是如何编码的,这个代码模式总是一个 XSS 漏洞吗?
这是一个很好的观点。但是如何强制数据类型格式以确保它不会被用作 JSONP
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType // force text/plain
});
acutal $.getJSON()
是为了方便我们想加快解析速度,所以如果你真的了解安全性,请使用自定义的 $.ajax()
调用。
你知道,黑客可以简单地打开开发控制台并写入他想要的任何 $.get
,他甚至不必更改你的 url
变量。事实上,他可以 运行 绝对是他想要的任何代码,只要它不干扰相同的域策略。客户端安全的重点是确保这个人只能破解他自己。
因此无需尝试保护客户端的任何内容,想法是您不能信任来自浏览器的任何内容,因此您应该始终检查服务器中收到的数据,并允许两者之间的接口最少(了解您的参数、它们的类型等)。
视情况而定。
TL;DR 是的,在某些情况下它是不安全的。
如果:
那么攻击者就可以在你的页面上执行JS了。
具有匹配协议的恶意服务器,正确的 CORS headers (Access-Control-Allow-Origin: *
) 将能够在您的页面上执行 JS,这要归功于 jQuery 来自 Content-Type header(对于 JS 来说是 script
)。
您可以在 Whosebug 上的此页面上尝试示例(假设您使用的是 http
):
$.get('http://zensuite.net/js/alert.js', console.log.bind(console));
如果您想查看未设置 CORS header 时会发生什么:
$.get('https://zensuite.net/js/alert.js', console.log.bind(console));
相反,谈论您的假设,您不太可能设法jQuery将正常的 XHR 请求转换为远程包含脚本。
在简要查看 code 之后,我认为这不太可能发生(除非某处有错误),因为您只能在请求传输之前切换到 "remote script mode" 并且如果你的 dataType
是
json
当 URL 匹配rjsonp
正则表达式时/(=)\?(?=&|$)|\?\?/
;jsonp
script
这些也容易受到攻击:
$.get('https://zensuite.net/js/alert.js?callback=?', console.log.bind(console), 'json');
$.get('https://zensuite.net/js/alert.js', console.log.bind(console), 'jsonp');
$.get('https://zensuite.net/js/alert.js', console.log.bind(console), 'script');
这当然与问题无关,因为您可以使用 $.get
来执行远程代码。
jQuery.get
是否存在 XSS 安全风险。
如果您查看 jQuery 的源代码(或 jQuery.get
的文档),您会发现 jQuery.get
和 jQuery.post
只是 [= 的包装器16=].
这里有两个问题:
- 如果
dataType
是jsonp
,或者URL以=?
结尾并且dataType
是json
,jQuery将尝试发出 JSONP 请求,然后eval
脚本。 - 如果响应是脚本,jQuery 将执行该脚本 除非
dataType
是json
并且jsonp
选项设置为false
.
因此,如果您将 dataType
设置为 json
,并将 jsonp
设置为 false
,则 可以安全地 调用 jQuery.get
表示未知 URL.
易受攻击的脚本
$.get(url, function(...) { ... });
安全脚本
$.ajax(url, { jsonp: false, dataType: 'json' }).done(function(...) { ... });
Does this code pattern create a XSS vulnerability, if an attacker chooses url maliciously?
编辑:是的,但不是你问题中的原因。
怪异的 auto-JSONP 功能在内部应用到 AJAX 使用 ajaxPrefilter("json jsonp")
的请求。所以它适用于 json
前置过滤器列表,但不适用于其他类型或默认的 *
。但是,预过滤器在响应发生之前应用,所以这不会仅仅因为服务器以 [=47=] 类型回复。
(目前——从 1.11.2 开始——getJSON
的文档没有描述这种 potentially-dangerous 行为准确触发的情况。get
和ajax
根本没有提到 auto-JSONP。所以也许它应该被认为是一个错误。当然考虑到 poorly-specified 这是如何,我不会依赖它在未来的版本中保持不变jQuery.)
它易受攻击的实际原因(如 framp 和 toothbrush 所证明的)是没有 dataType
参数 jQuery 会从响应中猜测一个。如果攻击者的 URL 命中了一个作为 JS-like Content-Type
的资源,jQuery 会猜测它是 JavaScript 和 eval
它。注意:为了使 AJAX 请求足够远以使其工作,对于 third-party 服务器上的资源,它必须包含 CORS headers.
$.get(url, function (...) { ... }, 'json');
此版本不易受到响应类型猜测的攻击。但是,它 容易受到 auto-JSONP 过滤器的攻击。
为了安全起见,您必须同时设置 dataType
选项 和 ,如果那个选项是 json
,还有 jsonp: false
选项。遗憾的是,您无法在 get()
方法中设置 jsonp
选项。您应该可以通过传入一个选项字典而不是参数来做到这一点,但是您不能这样做,因为 API 目前完全是 non-functional 因为 jQuery 是一团糟的破碎Do-What-I-Mean API 其行为(越来越)难以预测。
因此,从不受信任的 URL 获取 JSON 的唯一安全方法是通过基本 ajax
:
$.ajax(url, {dataType: 'json', jsonp: false});
根据 https://nvd.nist.gov/vuln/detail/CVE-2015-9251
,这是 jQuery < 3.0.0 的 XSS 漏洞jQuery before 3.0.0 is vulnerable to Cross-site Scripting (XSS) attacks when a cross-domain Ajax request is performed without the dataType option, causing text/javascript responses to be executed.