1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
|
Description: Patch to address potential XSS vuln (CVE-2018-8048)
libxml2 >= 2.9.2 fails to escape comments within some attributes. It
wants to ensure these comments can be treated as "server-side
includes", but as a result fails to ensure that serialization is
well-formed, resulting in an opportunity for XSS injection of code
into a final re-parsed document (presumably in a browser).
Origin: upstream
Debian-Bug: #893596
Applied-Upstream: https://github.com/flavorjones/loofah/commit/4a08c25a603654f2fc505a7d2bf0c35a39870ad7
Last-Update: 2018-03-25
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- a/lib/loofah.rb
+++ b/lib/loofah.rb
@@ -6,6 +6,7 @@
require 'loofah/elements'
require 'loofah/html5/whitelist'
+require 'loofah/html5/libxml2_workarounds'
require 'loofah/html5/scrub'
require 'loofah/scrubber'
--- /dev/null
+++ b/lib/loofah/html5/libxml2_workarounds.rb
@@ -0,0 +1,12 @@
+require 'set'
+module Loofah
+ module LibxmlWorkarounds
+ BROKEN_ESCAPING_ATTRIBUTES = Set.new %w[
+ href
+ action
+ src
+ name
+ ]
+ BROKEN_ESCAPING_ATTRIBUTES_QUALIFYING_TAG = {"name" => "a"}
+ end
+end
--- a/lib/loofah/html5/scrub.rb
+++ b/lib/loofah/html5/scrub.rb
@@ -54,6 +54,7 @@
node.attribute_nodes.each do |attr_node|
node.remove_attribute(attr_node.name) if attr_node.value !~ /[^[:space:]]/
end
+ force_correct_attribute_escaping! node
end
def scrub_css_attribute node
@@ -89,6 +90,18 @@
style = clean.join(' ')
end
+ def force_correct_attribute_escaping! node
+ return unless Nokogiri::VersionInfo.instance.libxml2?
+ node.attribute_nodes.each do |attr_node|
+ next unless LibxmlWorkarounds::BROKEN_ESCAPING_ATTRIBUTES.include?(attr_node.name)
+ tag_name = LibxmlWorkarounds::BROKEN_ESCAPING_ATTRIBUTES_QUALIFYING_TAG[attr_node.name]
+ next unless tag_name.nil? || tag_name == node.name
+ encoding = attr_node.value.encoding
+ attr_node.value = attr_node.value.gsub(/[ "]/) do |m|
+ '%' + m.unpack('H2' * m.bytesize).join('%').upcase
+ end.force_encoding(encoding)
+ end
+ end
end
end
--- a/test/integration/test_ad_hoc.rb
+++ b/test/integration/test_ad_hoc.rb
@@ -173,4 +173,30 @@
html = "<p>Foo</p>\n<p>Bar</p>"
assert_equal "Foo\nBar", Loofah.scrub_document(html, :prune).text
end
+ [
+ {tag: "a", attr: "href"},
+ {tag: "div", attr: "href"},
+ {tag: "a", attr: "action"},
+ {tag: "div", attr: "action"},
+ {tag: "a", attr: "src"},
+ {tag: "div", attr: "src"},
+ {tag: "a", attr: "name"},
+ {tag: "div", attr: "name", unescaped: true},
+ ].each do |config|
+ define_method "test_uri_escaping_of_#{config[:attr]}_attr_in_#{config[:tag]}_tag" do
+ html = %{<#{config[:tag]} #{config[:attr]}='examp<!--" unsafeattr=foo()>-->le.com'>test</#{config[:tag]}>}
+ reparsed = Loofah.fragment(Loofah.fragment(html).scrub!(:prune).to_html)
+ attributes = reparsed.at_css(config[:tag]).attribute_nodes
+ assert_equal [config[:attr]], attributes.collect(&:name)
+ if Nokogiri::VersionInfo.new.libxml2?
+ if config[:unescaped]
+ assert_equal %{examp<!--" unsafeattr=foo()>-->le.com}, attributes.first.value
+ else
+ assert_equal %{examp<!--%22%20unsafeattr=foo()>-->le.com}, attributes.first.value
+ end
+ else
+ assert_equal %{examp<!--%22 unsafeattr=foo()>-->le.com}, attributes.first.value
+ end
+ end
+ end
end
|