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.
Related
I'm trying to submit input to the form, and parse the results in a RoR app. I've tried using mechanize, but it has some trouble with the way the page dynamically updates the results. It doesn't help that most fields are hidden.
Is there anyway to get mechanize to do what I'm looking for, or are there any alternatives to mechanize which I can use?
So whenever I want to do something like this, I go with the gem selenium-webdriver. It spawns a real browser (supports all major brands) and lets you control it with ruby code. You can do almost everything a real user could do. In addition, you have access to the (rendered) dom, so javascript generated content is not a problem.
Performance is much slower than with pure library clients, so its not a good fit for use in a web request cycle.
http://rubygems.org/gems/selenium-webdriver
I need to submit forms from a couple of remote sites to the central rails application that processes and stores data. You can think about it as of widget form (something similar to what Wufoo service provides).
These outside sites are going to be pure HTML (what means no server-side scripting - only JS/jQuery at browser side). I am aware that straight way to get it would be to put the form inside of an iframe element but I'd be glad to avoid this.
What would be a good and safe pattern to build such interaction?
I wrote simply HTML form sending data to create action in proper controller and submit form with AJAX/jQuery. It almost works, however I got
WARNING: Can't verify CSRF token authenticity
warning so, I'm sure, this approach would not be useful in production.
May someone who is experienced provide me some advice? Thank You.
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 building a web app (atop Ruby on Rails), which will let users style their own areas (personal blog pages), and was wondering what are the best ways of accomplishing this?
I think Liquid for templating would be good, but how would you handle styling? My aim was to have a DB field associated with each blog dubbed "style" which will store a custom stylesheet, is this the best approach?
I've tried it so far with the "sanitize_css" helper method, but it just strips the "#stylebox" tags out, meaning nothing is displayed.
Any ideas?
Thanks.
Currently I'm also working on almost a similar requirement as you do. I'm also trying to create a CMS for users to add pages, style them etc..
My Approach as follows
each user will have his/her subdomain. (I use a before_filter to get the current users subdomain and load his/her website)
About styling, I prefer to have the style sheet as a physical file. Given that your method will have the more flexibility of editing the style sheet, I dont like the idea of having the stlesheet code on top of my page. Insted, I allow users to load their styleshets (Using paper clip)
So when the site loads I will get the css paths from the DB and load the stylesheet from the path.
Later I'm planning to read the file and load it to a textarea so that users can edit their stylesheets and when saving override the existing file;
For layouts i use liquid as well
cheers
sameera
I would honestly allow themable elements on your page, and then store each of those style rules as a field (or conglomerate them into one giant field) in the database. Enforce some validation to ensure that they don't use any funny business (if they're only coding for specific div's, they shouldn't need to use any curly braces.)
Then generate the CSS on the fly.
The reason? If you ever want to serve up ad's on your site, and you allow them to just upload the entirety of their CSS, they can easily turn off visibility on the ad div.
I think it's "safer" to control what they're allowed to theme; sure more advanced users will get ticked. But do you really want to be the next MySpace? ;-)
if there is too much of code then serialize the data and store it as text in db.
That would be much better i think
If your going to allow areas for users to have complete control over their CSS, then I would probably avoid the database altogether and use a structured file system approach. You could create a sub-domain or folder for each user that contains a main.css. This also allows you to scale well as features grow for your user (pictures, etc.)
With that said, as Robbie mentioned, you might want to consider limiting what styles a user can and can not control. Otherwise, you would probably find things getting out of hand quickly. For this approach, you would probably want to use the database for storing property values of the elements that can be modified.
This is probably a stupid question but I'll go ahead and humble myself.
The Ruby code in my controllers and models are interpreted so that a HTML result is sent to the browser. Ok, I get that part.
But is there any way for a mailicious user to somehow take a peek at the Ruby code in the controllers and models by bypassing the process that converts or interprets that code before it is sent to the browser?
The reason I'm concerned is I am planning on doing some order processing in my app and if a malicious user was able to do that, they might be able to figure out how to do all kinds of unpleasant things.
Side tip: make sure you use html_escape or h to escape user data and prevent someone from injecting code into your site. For example, use
<%= h(person.name) %> so that someone can't put javascript in the name field and have it run when people view that page.
Nope. Try and navigate to the file yourself in the browser, you won't be able to see it. Your biggest worry should be someone trying to fake out GETs and POSTs because they know how REST works.
Assuming you have things set up correctly, then the web server in front of Rails is pointed to the /public directory. So anything in that directory may be open to direct attack. However, the web server intercepts the HTTP call based on certain criteria and redirects it to Rails for processing.
The architecture of Rails makes it impossible for model and controller code to be exposed to the public. There is a possibility that view code is viewable, but ONLY if you seriously mess up the code (I think). I have never managed to expose code to the client by accident, and I have never deliberately attempted to do so.