In Rails 4.2.4, say I have a form with a text field that a user can input whatever they want. I don't sanitize the input at all. The user then submits the form and to a controller method that looks like this:
def datahandler
#data = params[:usersdata]
end
Then in the related view, "datahandler.html.erb", I have the following:
<%= #data %>
Should be a huge XSS vulnerability right? Well it looks like Rails now automatically converts certain characters in string objects into CDATA representations for their views. This appears to break at least the XSS attack examples I've found.
However, I'm hesitant to rely on this mechanism without some research as I'm not an expert in XSS vulnerabilities. Further, the Rails Guides don't seem talk about this feature, even in their security guide (they talk about defending against XSS but they don't mention this feature). I haven't been able to find any documentation on this.
Can anyone point me to some documentation regarding this feature? If not, does anyone know of any loopholes in this protection (please provide examples)?
Rails' stock XSS protection is extremely bulletproof.
The default behavior was changed in Rails 3, to "escape HTML output ... by default in all view templates". Although there have been cases where the escaping needed to be adjusted, most of the known XSS vulnerabilities in Rails have not been centered around this functionality.
At any rate, the code in your question should be quite secure. The main problem with the current XSS protection in Rails is caused by developers misunderstanding the mechanics of the process. Taking the time to fully understand the implementation will ensure that you do not inadvertently introduce XSS errors in spite of the built in protection.
As far as I'm concerned, it doesn't do that by default but it has a protection mechanism which does that for you in case you'd want to use it http://guides.rubyonrails.org/security.html#injection
Related
By default, rails 3.2 sets active_record.mass_assignment_sanitizer = :strict in config/environments/development.rb. (See railcasts episode http://railscasts.com/episodes/318-upgrading-to-rails-3-2). Here it is:
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
This makes the mass assignment error-prone in development and force to list every attributes for attr_accessible. What's the reasoning for doing this by default in rails 3.2(haven't checked if it is rails 4 as well)?
The link provided by Baldrick seems to be gone now. But I recently read a blog post that gives very useful context on the evolution of the mass assignment security issue in Rails: http://net.tutsplus.com/tutorials/ruby/mass-assignment-rails-and-you/
I'm not an expert on this issue but here's my understanding: Misconfiguring mass assignment in Rails could lead to really, really big security issues, all the more dangerous now that they've been popularized. Rails 4 attempts to patch over the biggest threats by requiring you to explicitly list the fields that can be mass-assigned right in the controller, where security concerns are easy for you to see and handle. But the handling of mass assignment in Rails 3 was more variable, and in many cases, if a parameter was submitted that wasn't on the attr_accessible whitelist (or was on the blacklist), Rails would simply skip over that parameter, without letting the developer know that anything had happened wrong.
This was a problem. If I'm writing an app that demands high security (or, these days, any level of security), if I've written a test to ensure that certain parameters are rejected, I want to know that they're being rejected. I'd much rather find out what Rails is doing sooner rather than later, so that I can adjust my code and plan future site sections accordingly. So, the mass_assignment_sanitizen = :strict setting makes this more vocal behavior the default.
You say that this setting makes mass assignment behavior more "error-prone" in development, as though this were a problem. I would think you would want your Rails app to be as error-prone and as vocal as it can be, during the development and testing phases, so that you learn about more of the potential problems in your code sooner on. So I appreciate the mass_assignment_sanitizer default.
Fortunately for both of us, Rails 4 has simplified this issue by taking a stronger stand in favor of strictness. Strict mass-assignment parameter sanitization, along with its vocal error-prone-ness, has become a default feature of the controller (since this issue never really belonged in the model in the first place) and provides you with a friendly private function where you can define any alternate behavior you need.
I am a Java programmer mostly, and it's actually amazing that we don't have to worry about a lot of security concerns that php or even rails developers have to worry about. We have to worry about them, but I think our job is actually a lot easier. You just use Java (already big bonus points there) and use Spring with Spring security... and you're basically done. Java and servlets are actually really good in this respect.
Now that I'm working in Rails, I think the biggest security concerns that I am the most scared of are parameters - both in the ones that are coming from the controllers (since they dynamic hashes, unlike in SpringMVC) and having to include more hidden values in forms.
But that got me thinking - you really have to be careful what you accept when you create new models or even update models. If you just blindly pass in parameters to your models, bad things can happen. In fact, things like the user role and stuff could be changed if you're not too careful.
It's almost like I want to write the setter code by hand to make sure it's not overwriting something that it shouldn't. And even if there's a framework mechanism to handle this... I would still want to test every risky model attribute just to be extra sure that it won't get overwritten on a create and on an update.
As much as Java gets a bad rep about productivity, it feels like it handles this stuff a lot better.
Anyway, my question is - what is the best resource/tips/advice for dealing with common security pitfalls/concerns/gotchas using rails - especially geared towards a Java/Spring developer who got used to working in a more stateful environment.
Even better, what would be a good checklist to go through every once in awhile?
And last, what tests would you recommend to make sure things are solid?
At least for your concern about assigning data to your model objects without proper checking, look into the attr_accessible declaration; it allows only specified attributes to be assigned via the bulk assignment:
user = User.new(params[:user])
user.approved = params[:user][:approved]
user.role = params[:user][:role]
You might find the entire 27th chapter of the Ruby on Rails 3rd edition book useful. (I haven't updated my 4th Edition book yet, not sure which chapter to recommend from the newer book. :)
I don't use ActiveRecord (I use DataMapper), but as a rule, I never do mass-assignment and I always expressly pass only the attributes I want to change. Rails 3 defaults to escaping all content in your views, unless you expressly output that data raw into into the .erb.
Also, it really bugs me that ActiveRecord doesn't help you out very much if you need to drop down to using SQL for something. You have to escape input yourself, which can expose you to the risk of human error allowing arbitrary SQL to be executed in your queries. DataMapper's underlying DataObjects connection supports prepared statements out of the box and in fact, it would actually require more work to avoid using them.
Rails 3 does have CSRF protection turn on by default too. It also makes session cookies HTTP-only by default, which makes them harder to steal via JavaScript.
I actually think, aside from Rails encouraging the use of mass-assignment, you're pretty well-covered for security.
I have just implemented CKEditor for rich text entry in my app and I am thinking that the ability of a user to enter anything could pose a security threat.
At the moment, I have the simplest implementation - CKEditor sits in a form, input is saved to the database as part of update_attributes, and other people can view the output as html_safe.
Somehow, the above doesn't sound good to me, even though it works. Am I correct in thinking there are risks to the above approach? Is there a safer way to do this to block an attack through the editor?
You should always take care of sanitizing a users input. In your case, by stripping all unwanted HTML tags (like , for example) regardless of where it came from.
html_safe is not meant to strip HTML or sanitize for you. See Yehuda Katz' article on ActiveSupport::SafeBuffer. It is meant to prevent "unsafe" markup by marking a String as safe, if it is (and encoding it to HTML entities otherwise, to make it safe).
There are sanitation helpers in ActionView::Helpers::SanitizeHelper that you can use to sanitize what is displayed, but you might want to sanitize it before it enters the database.
If you strip away the possibility of inserting CSS, Javascript or an iframe, you should be fine. If you're paranoid about what your users do, also take away <img> tags. And if you're really paranoid, you should consider using Markdown, Textile or others.
I'm currently in the process of writing my first Rails app. I'm writing a simple blog app that will allow users to comment on posts. I'm pretty new to Rails, so I'm looking for a bit of guidance on how to address security concerns with user input.
On the front end, I am using TinyMCE to accept user input. It is my understanding that TinyMCE will strip out any suspicious tags (e.g. <script>) from user input before posting to server. It seems that this could be bypassed by disabling javascript on the page, allowing a user to have free reign in the text area. TinyMCE recommends using javascript to create the TextArea. Therefore if the user disables javascript, there will be no text area. Is this the standard solution? It seems like a bit of a hack.
On the back end, what is the best way to strip out malicious code? Would I want to put some sort of validation in the create and update methods inside my comments controller? Is there some functionality built into Rails that can assist with this?
When displaying the information back out to the user, I'm assuming that I don't want to escape the HTML markup (with <%= h *text*%>), because that's how its stored in the back end. Is this bad practice?
I'm generally a big fan of cleaning out the data prior popping that stuff into the database. This is a debatable practice, but I usually lean toward this.
I use a modified version of the old white_list plugin to not strip out the html, but to convert anything I do want into a safer format.
<tag>
becomes
<tag>
This way I'm not really altering the content of the submission.
There are some plugins that specifically handle sanitization using a white/black list model.
http://github.com/rgrove/sanitize/ # Have not used, but looks very interesting
http://github.com/imanel/white_list_model # Used, not bad
There is also act_as_sanitized, but I have no real info on that.
And of course using the h().
Your suspicions are justified, but the creation of a text area in javascript won't make you any less vulnerable. A user could always use something like curl to force a form submission without ever visiting your site through a web browser.
You should assume that a user can post malicious scripts into the comments, and escape it on the frontend. Using <%= h(...) %> is one way to do it, or you can use the sanitize method in the same way. It will strip any scripts and escape all other html except for a few common tags that aren't harmful. Documentation for sanitize.
In addition to nowk's suggestions there is also the xss_terminate plugin. I have been using it in some of my applications. I found it to be easy to use, it needs almost no configuration, and has been working like a charm.
what do you recommend?
Authlogic or restful_authentication?
Is it hard, to build the email-activation-step into authlogic
(as far as I know, Authlogic hasn't this feature included).
Actually I'd disagree with fig-gnuton. There are a couple of things that you could do. If you want a basic solution try restful auth but be aware that the generator based approach has significant shortcomings. The main shortcoming is that you are squirting a large gob of code into your application. So when there's an issue you have to patch the code manually or blow away any customisations you've made. Recent versions of restful auth are much better than earlier versions which spewed code left, right and centre but my advice would be where possible leave the user and session code generated by restful auth well alone. For example if you want properties on your User make another object like Person and link the two.
I prefer authlogic because:
It feels like you're more in control.
I appreciate the extent to which authlogic is documented and their example app is pretty useful as a guide too.
Also I've had bother with testing restful_auth apps, not so with authlogic.
Extensions like forgotten password resets, API keys and the like are much less custom code than restful_auth.
And don't forget Clearance, the other kid in the block.
Restful Authentication is crap. It's the kind of thing that gives Rails generators a bad name.
What do I mean by that? The generators that come with Rails are (IMHO) good. They generate a very minimalistic skeletal structure. What they generate is small, easily understood, and easy added to/replaced by your own code as you go. All the complex gnarly pieces are in the Rails libraries, where they belong, not in the generated code.
Restful Authentication, on the other hand, comes with generators that spew out massive amounts of generated code that's hard to work with and hard to maintain. Functionality that should be in a nice library where it can be easily upgrade with each new version of the framework is instead spewed out in generated model and controller code where it'll end up intermixed with your code. It's not scaffolding, it's a mass one way dump of autogenerated code.
Stay away... stay far away....
You're better off with authlogic.
take a look at my reasoning here
http://blog.platform45.com/2009/09/30/user-authentication-with-authlogic
Restful_Auth is a drop-in solution.
Authlogic is great and can do anything restful_auth can do (and more, afaik), but Authlogic is geared to customization, it therefore lacks the generator aspect (by design rather than oversight).
Bottom line, if you're a newbie (sounds like you might be), I'd start with restful_auth.