jQuery的$ .get()可以安全地调用不受信任的URL吗?

D.W*_*.W. 21 security xss ajax jquery json

我最近了解到,调用不受信任的URL$.getJSON()不安全的.怎么样$.get()$.get()当URL参数来自不受信任的来源时,jQuery是否可以安全地调用,或者这是不安全的?

这出现在我正在进行的安全代码审查中,以检查XSS漏洞.示例代码模式:

$.get(url, function (...) { ... })
Run Code Online (Sandbox Code Playgroud)

如果攻击者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 */ });
Run Code Online (Sandbox Code Playgroud)

假设我知道url攻击者可以完全控制它.这是否自动成为XSS漏洞?或者这总是安全吗?或者如果答案是"它取决于",它依赖于什么?

或者,另一种思考方式.假设我正在进行代码审查,我看到以下代码行:

$.get(url, f);
Run Code Online (Sandbox Code Playgroud)

假设我知道url攻击者可以完全控制它.我需要检查什么,以验证这是否安全(没有XSS错误)?我知道我需要检查代码f是否安全地处理响应,因为如果f不小心它可能会引入XSS错误.我的问题是:我唯一需要检查的是什么?或者这个代码模式总是一个XSS漏洞,无论f编码方式如何?

bob*_*nce 10

 如果攻击者恶意选择URL,此代码模式是否会创建XSS漏洞?

编辑:是的,但不是你问题中的原因.

奇怪的auto-JSONP功能在内部应用于AJAX请求ajaxPrefilter("json jsonp").因此它适用于json预过滤器列表,但不适用于其他类型或默认值*.但是,prefilters在响应发生之前应用,因此这不会因为服务器回复类似JSON的类型而发生.

(目前 - 从1.11.2开始 - 这些文档getJSON没有描述这种潜在危险行为正好引发的情况.而且文档中getajax没有提到auto-JSONP.所以也许它应该被认为是bug.当然,鉴于这是多么糟糕的指定,我不会依赖它在jQuery的未来版本中保持不变.)

它易受攻击的实际原因(如framp和牙刷所示)是没有dataType参数jQuery会从响应中猜出一个.如果攻击者的URL命中一个像JS一样的资源Content-Type,jQuery会猜测它是JavaScript和eval它.注意:为了使AJAX请求足以使其工作,对于第三方服务器上的资源,它必须包含CORS头.

$.get(url, function (...) { ... }, 'json');
Run Code Online (Sandbox Code Playgroud)

此版本不容易受到响应类型的猜测.但是,它容易受到auto-JSONP过滤器的攻击.

为了安全起见,你必须既设置dataType选项,如果该选项json,也是jsonp: false选项.不幸的是,您无法jsonpget()方法中设置选项.你应该可以通过传入一个选项字典而不是参数来做到这一点,但你不能,因为这个API目前完全不起作用,因为jQuery是一个令人遗憾的混乱的破坏的Do-What-I-Mean API其行为它(越来越)难以预测.

因此,从不受信任的URL获取JSON的唯一安全方法是通过基本方式ajax:

$.ajax(url, {dataType: 'json', jsonp: false});
Run Code Online (Sandbox Code Playgroud)


Too*_*ush 8

jQuery.get 确实会造成XSS安全风险.

如果你查看jQuery的源代码(或者文档jQuery.get),你会看到它jQuery.get并且jQuery.post只是包装器jQuery.ajax({ url: url, data: data, success: success, dataType: dataType });.

这里有两个问题:

  1. 如果dataTypejsonp,或者URL在结束=?dataTypejson,jQuery将设法使JSONP请求,然后eval脚本.
  2. 如果响应是脚本,jQuery将执行该脚本,除非 dataTypejson并且jsonp选项设置为false.

所以,如果你设置dataTypejson,并jsonpfalse,它是安全的调用jQuery.get一个未知的URL.

易受攻击的脚本

$.get(url, function(...) { ... });
Run Code Online (Sandbox Code Playgroud)

请参阅JSFiddle上的示例.

安全的脚本

$.ajax(url, { jsonp: false, dataType: 'json' }).done(function(...) { ... });
Run Code Online (Sandbox Code Playgroud)

请参阅JSFiddle上的示例.


fra*_*amp 5

这取决于.

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));
Run Code Online (Sandbox Code Playgroud)

如果您想查看未设置CORS标头会发生什么:

$.get('https://zensuite.net/js/alert.js', console.log.bind(console));
Run Code Online (Sandbox Code Playgroud)

相反,在谈论您的假设时,您可能无法使jQuery将正常的XHR请求转换为远程包含脚本.

在简要查看代码后,我认为这不可能发生(除非某处有错误),因为只有在要求传输之前才能切换到"远程脚本模式",如果你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');
Run Code Online (Sandbox Code Playgroud)

这当然与问题无关,因为您可以使用它$.get来执行远程代码.

  • @Bergi:是的,当该资源与JavaScript Content-Type一起提供时.是的,这似乎是一个非常糟糕的主意. (3认同)