Disable XSS and HTML Sanitization in Rails 3 - ruby-on-rails

I'm having an issue where when I have the contents of my rich text editor saved into the database using activerecord the html content is stripped of the html contents (I think it fires html_safe on it). I tried overriding the html_safe method on the content string, but nothing works.
content = "<p>hello</p>"
#article.content = content
puts #article.content # "<p>hello</p>"
#article.save
puts #article.content # "<>hello</>"
How can you override the html stripping capabilities in activerecord for a particular column?

As frank blizzard already said in his answer, you make your self vulnerable two XSS-Attacks.
But if you trust your authors, that this columns are safe two display, you can do something like this in your Article model
class Article < ActiveRecord::Base
def content
attributes[:content].html_safe
end
end

You can use the raw(string) method, but it would make you vunlerable against XSS attacks.
Another option would be taking a deeper look into markdown.

Turns out the issue to this problem was nothing todo with Rails or the XSS stripping. The code that I had was modifying a string and then saving the results elsewhere which was causing the original input to be changed. I solved the problem by using string.dup to copy over the original string so that I wasn't affected.

There should be an option for this.
I encourage you to take a look at the docs of the rich text editor that you are using.

Related

rails 5.x: add nofollow to all links in 'sanitize'

I am working on a Rails application whose HAML templates frequently make use of a routine called sanitize. I have deduced from context that this routine sanitizes user-controlled HTML. Example:
# views/feed_items/_about.html.haml
%h3 Summary:
.description
= sanitize #feed_item.description
I want to make this routine add 'rel=nofollow' to all outbound links, in addition to what it's already doing. What is the most straightforward way to do that?
N.B. I am not having any luck finding the definition of this method, or the official configuration knobs for it. The vendor directory has two different HTML sanitizer gems in it and I can't even figure out which one is being used. This is a large, complicated web application that I did not write, and I barely understand Ruby, let alone all of Rails' extensions to it. Please assume I do not know any of the things that you think are obvious.
The sanitizer will strip out the rel tags if they exist.
I ran into a similar issue and added an additional helper method - clean_links to the ApplicationHelper module, and called it after sanitizing the content.
# application_helper.rb
def clean_links html
html.gsub!(/\\2')
html.html_safe
end
This method looks for all <a> tags, and adds rel="nofollow". The html_safe method is necessary or else the HTML will be displayed as a string (it's already been sanitized).
This solution treats all links equally, so if you only want this for links pointing outside the domain, you'll have to update the REGEX accordingly.
In your view: <%= clean_links sanitize(#something) %>
So, first the content is sanitized, then you add the rel="nofollow" tag before displaying the link.
Actually there's a built-in way:
sanitize "your input", scrubber: Loofah::Scrubbers::NoFollow.new

Rails form text_field escaping html

Experimenting with my Rails form, I find that inserting <scrip>alert("hello")</script> into a text_field gives me two different results.
When I use the value, for example in a display page, it is automagicaly escaped.
When I use the value in a new form, for example to allow user editing, it is not escaped and I get the alert pop-up.
After a lot of research, I have found that text_area has an escape boolean that prevents this, but not text_field. Most of the stuff coming up on google is about escaping within erb templates, which does not appear to work when using a form. There are a couple of hints that data should be sanitized going into the db, but little guidance on the best way to do this --- aside from using old solutions for example xssterminate which appears to date back to Rails 2. Even the RoR security guide focuses on sanitizing erb output rather than santizing the input.
Two questions.
What is the current best-practice approach to sanitizing text_field input before it is saved? (eg: in the form, the controller or the model. What gems are still considered current?)
Regardless, because I am paranoid, how do you sanitize the text_field when displaying db data?
The loofah-activerecord gem (https://github.com/flavorjones/loofah-activerecord) looks like your best bet for sanitizing data on its way into the database. Using xss_foliate on your models will strip tags for all columns by default.
e.g.
class User < ActiveRecord::Base
xss_foliate
...
end
I haven't found a solution to the 2nd point, but would be very keen to know about it if there is one!

Creating a link with link_to and gsub

I have a body of text being fed into a textarea and if any of the text matches URI.regexp, I need to make that link active with a target: '_blank' on the a tag in the textarea.
Here is my current code. I also tried this with .match which would correc
def comment_body(text)
text = auto_link(text)
text.gsub!(URI.regexp) do |match|
link_to(match, match, target: '_blank')
end
end
This outputs:
https://facebook.com">https://facebook.com in my view
and
https://facebook.com in the inspected HTML.
In the gsub docs it says that metacharacters will be interpreted literally, which is what I believe is messing me up here.
Any tips on how to properly construct this URL?
Thanks!
The auto_link gem does exactly what you need.
You can look at its code to see how its using gsub.
EDIT: this solution requires setting sanitize to false, which often is not a good idea!
I've found a solution without using auto_link (I'm using Rails 5 too). I know this is an oldish thread but I've spent some time trying to find a solution that would allow the insertion of target="_blank" and found this. Here I'm creating a helper to search text in a text box for links and then add essentially make them linkable in the view.
def formatted_comment(comment)
comment = comment.body
URI.extract(comment, ['http', 'https']).each do |uri|
comment = comment.gsub( uri, link_to(uri, uri, target: "_blank"))
end
simple_format(comment, {}, class: "comment-body", sanitize: false)
end
The key thing here was simple_format kept sanitizing, so it's important to add both {} and sanitize:false.
***Note that setting sanitize to false may bring up other issues like allowing javascript to run in a comment, but this solution will allow the insertion of target="_blank" into a link.
One solution using just a simple gsub with back references would be something like this: (You can certainly modify the regex to meet your needs.)
str = 'here is some text about https://facebook.com and you really http://www.google.com should check it out.'
linked_str = str.gsub( /((http|https):\/\/(www.|)(\w*).(com|net|org))/,
'\4' )
Example output:
print linked_str
#=> here is some text about facebook and you really google should check it out.

Rails 3.1 CKEditor gem raw text

I'm using the ckeditor gem and when I use the paste as plain text dialog it encapsulates the text in quotes as well as < p> tags and < br> tags. Is there any way I can tell ckeditor not to use any markup whatsoever when using that option.
What I am trying to accomplish is to have snippets of code within an article. Those snippets are processed using the markdown gem as well as pigments.rb. The following code is what I'm trying to accomplish
```ruby
puts "hello world"
class Hello
end
```
and this is what I'm getting
<p>
```ruby<br />
puts "hello world"
class hello<br />
end<br /></p>
This might be what you're looking for:
http://ckeditor.com/addon/codemirror
I really don't know if the ckeditor has that option.
If your problem is show the information like WYSIWYG in a web with RoR maybe you have to set in the view that the information is html safe (This is for security reasons and is set by default). If you don't do that you will see with the html tags.
You have many ways to do the html safe:
Here is a discussion about which one use:
raw vs. html_safe vs. h to unescape html
Hope that solve your problem.
Codemirror might be your best bet for this. Its like CKeditor but for code.
http://codemirror.net/
You could even write your own mode for it, which if I understand what your trying to do might end up being required.
Have not found anything better than going with Markdown. Just like it is done here on SO

Escaping HTML in Rails

What is the recommended way to escape HTML to prevent XSS vulnerabilities in Rails apps?
Should you allow the user to put any text into the database but escape it when displaying it? Should you add before_save filters to escape the input?
There are three basic approaches to this problem.
use h() in your views. The downside here is that if you forget, you get pwnd.
Use a plugin that escapes content when it is saved. My plugin xss_terminate does this. Then you don't have to use h() in your views (mostly). There are others that work on the controller level. The downsides here are (a) if there's a bug in the escaping code, you could get XSS in your database; and (b) There are corner cases where you'll still want to use h().
Use a plugin that escapes content when it is displayed. CrossSiteSniper is probably the best known of these. This aliases your attributes so that when you call foo.name it escapes the content. There's a way around it if you need the content unescaped. I like this plugin but I'm not wild about letting XSS into my database in the first place...
Then there are some hybrid approaches.
There's no reason why you can't use xss_terminate and CrossSiteSniper at the same time.
There's also a ERb implementation called Erubis that can be configured so that any call like <%= foo.name %> is escaped -- the equivalent of <%= h(foo.name) %>. Unfortunately, Erubis always seems to lag behind Rails and so using it can slow you down.
If you want to read more, I wrote a blog post (which Xavor kindly linked to) about using xss_terminate.
The h is an alias for html_escape, which is a utility method for escaping all HTML tag characters:
html_escape('<script src=http://ha.ckers.org/xss.js></script>')
# => <script src=http://ha.ckers.org/xss.js></script>
If you need more control, go with the sanitize method, which can be used as a white-list of tags and attributes to allow:
sanitize(#article.body, :tags => %w(table tr td), :attributes => %w(id class style))
I would allow the user to input anything, store it as-is in the database, and escape when displaying it. That way you don't lose any information entered. You can always tweak the escaping logic later...
Use the h method in your view template. Say you have a post object with a comment property:
<div class="comment">
<%= h post.comment %>
</div>
Or with this plugin - no need for h 8)
http://railspikes.com/2008/1/28/auto-escaping-html-with-rails
I've just released a plugin called ActsAsSanitiled using the Sanitize gem which can guarantee well-formedness as well being very configurable to what kind of HTML is allowed, all without munging user input or requiring anything to be remembered at the template level.

Resources