diff --git a/Changelog.md b/Changelog.md index ff4b828e1..aa83e297f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -92,6 +92,9 @@ * ffi 1.1.5 -> 1.3.1 * configurate 0.0.1 -> 0.0.2 +# 0.0.2.4 + +* Fix XSS vulnerabilities caused by not escaping a users name fields when loading it from JSON. [#3948](https://github.com/diaspora/diaspora/issues/3948) # 0.0.2.3 diff --git a/app/assets/javascripts/widgets/search.js b/app/assets/javascripts/widgets/search.js index 4648cdf45..675b6f8b8 100644 --- a/app/assets/javascripts/widgets/search.js +++ b/app/assets/javascripts/widgets/search.js @@ -36,11 +36,12 @@ }; this.formatResult = function(row) { - return row.name; + return Handlebars.Utils.escapeExpression(row.name); }; this.parse = function(data) { var results = data.map(function(person){ + person['name'] = Handlebars.Utils.escapeExpression(person['name']); return {data : person, value : person['name']} }); diff --git a/app/helpers/layout_helper.rb b/app/helpers/layout_helper.rb index c226aff74..d29b1243e 100644 --- a/app/helpers/layout_helper.rb +++ b/app/helpers/layout_helper.rb @@ -43,7 +43,7 @@ module LayoutHelper user = UserPresenter.new(current_user, a_ids).to_json content_tag(:script) do <<-JS.html_safe - window.current_user_attributes = #{user} + window.current_user_attributes = #{j user} JS end end diff --git a/app/views/people/show.html.haml b/app/views/people/show.html.haml index 9dd05ad6a..a2b18ca21 100644 --- a/app/views/people/show.html.haml +++ b/app/views/people/show.html.haml @@ -7,7 +7,7 @@ = javascript_include_tag :people - if user_signed_in? && @person != current_user.person :javascript - Mentions.options.prefillMention = Mentions._contactToMention(#{@person.to_json}); + Mentions.options.prefillMention = Mentions._contactToMention(#{j @person.to_json}); - content_for :page_title do = @person.name diff --git a/config/initializers/json_escape.rb b/config/initializers/json_escape.rb new file mode 100644 index 000000000..a27bf2dd5 --- /dev/null +++ b/config/initializers/json_escape.rb @@ -0,0 +1,11 @@ +# From http://jfire.io/blog/2012/04/30/how-to-securely-bootstrap-json-in-a-rails-view/ +# Review on Rails 4 update, might be built in by then! + +class ActionView::Base + def json_escape(s) + result = s.to_s.gsub('/', '\/') + s.html_safe? ? result.html_safe : result + end + + alias j json_escape +end diff --git a/spec/controllers/people_controller_spec.rb b/spec/controllers/people_controller_spec.rb index 222509082..c38ed5148 100644 --- a/spec/controllers/people_controller_spec.rb +++ b/spec/controllers/people_controller_spec.rb @@ -201,11 +201,10 @@ describe PeopleController do it 'does not allow xss attacks' do user2 = bob profile = user2.profile - profile.first_name = "" - profile.save + profile.update_attribute(:first_name, "") get :show, :id => user2.person.to_param response.should be_success - response.body.match(profile.first_name).should be_false + response.body.should_not include(profile.first_name) end diff --git a/spec/helpers/layout_helper_spec.rb b/spec/helpers/layout_helper_spec.rb index f63da634a..dd11e3666 100644 --- a/spec/helpers/layout_helper_spec.rb +++ b/spec/helpers/layout_helper_spec.rb @@ -5,6 +5,18 @@ require 'spec_helper' describe LayoutHelper do + describe "#set_current_user_in_javascript" do + it "doesn't allow xss" do + user = FactoryGirl.create :user + profile = user.profile + profile.update_attribute(:first_name, ""); + stub!(:user_signed_in?).and_return true + stub!(:current_user).and_return user + set_current_user_in_javascript.should_not be_empty + set_current_user_in_javascript.should_not include(profile.first_name) + end + end + describe "#page_title" do context "passed blank text" do it "returns Diaspora*" do diff --git a/spec/javascripts/widgets/search-spec.js b/spec/javascripts/widgets/search-spec.js new file mode 100644 index 000000000..0e06516c2 --- /dev/null +++ b/spec/javascripts/widgets/search-spec.js @@ -0,0 +1,12 @@ +describe("Diaspora.Widgets.Search", function() { + describe("parse", function() { + it("escapes a persons name", function() { + $("#jasmine_content").html('
'); + + var search = Diaspora.BaseWidget.instantiate("Search", $("#jasmine_content > #searchForm")); + var person = {"name": "