Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Agile Web Development With Rails, 2nd Edition (2006).pdf
Скачиваний:
30
Добавлен:
17.08.2013
Размер:
6.23 Mб
Скачать

AVOID SESSION FIXATION ATTACKS 607

Joe Asks. . .

Why Not Just Strip <script> Tags?

If the problem is that people can inject <script> tags into content we display, you might think that the simplest solution would be some code that just scanned for and removed these tags?

Unfortunately, that won’t work. Browsers will now execute JavaScript in a surprisingly large number of contexts (for example, when onclick= handlers are invoked or in the src= attribute of <img> tags). And the problem isn’t just limited to JavaScript—allowing people to include off-site links in content could allow them to use your site for nefarious purposes. You could try to detect all these cases, but the HTML-escaping approach is safer and is less likely to break as HTML evolves.

Rails provides the helper method h(string) (an alias for html_escape) that performs exactly this escaping in Rails views. The person coding the comment viewer in the vulnerable store application could have eliminated the issue by coding the form using

<div class="comment" > <%= h(order.comment) %>

</div>

Get accustomed to using h for any variable that is rendered in the view, even if you think you can trust it to be from a reliable source. And when you’re reading other people’s source, be vigilant about the use of the h method—folks tend not to use parentheses with h, and it’s often hard to spot.

Sometimes you need to substitute strings containing HTML into a template. In these circumstances the sanitize method removes many potentially dangerous constructs. However, you’d be advised to review whether sanitize gives you the full protection you need: new HTML threats seem to arise every week.

26.6Avoid Session Fixation Attacks

If you know someone’s session id, then you could create HTTP requests that use it. When Rails receives those requests, it thinks they’re associated with the original user and so will let you do whatever that user can do.

Rails goes a long way toward preventing people from guessing other people’s session ids, because it constructs these ids using a secure hash function. In effect they’re very large random numbers. However, there are ways of achieving almost the same effect.

Report erratum

FILE UPLOADS 608

In a session fixation attack, the bad guy gets a valid session id from our application and then passes this on to a third party in such a way that the third party will use this same session. If that person uses the session to log in to our application, the bad guy, who also has access to that session id, will also be logged in.4

A couple of techniques help eliminate session fixation attacks. First, you might find it helpful to keep the IP address of the request that created the session in the session data. If this changes, you can cancel the session. This will penalize users who move their laptops across networks and home users whose IP addresses change when PPPOE leases expire.

Second, you should consider creating a new session every time someone logs in. That way the legitimate user will continue with their use of the application while the bad guy will be left with an orphaned session id.

26.7File Uploads

Some community-oriented web sites allow their participants to upload files for other participants to download. Unless you’re careful, these uploaded files could be used to attack your site.

For example, imagine someone uploading a file whose name ended with .rhtml or .cgi (or any other extension associated with executable content on your site). If you link directly to these files on the download page, when the file is selected your web server might be tempted to execute its contents, rather than simply download it. This would allow an attacker to run arbitrary code on your server.

The solution is never to allow users to upload files that are subsequently made accessible directly to other users. Instead, upload files into a directory that is not accessible to your web server (outside the DocumentRoot in Apache terms). Then provide a Rails action that allows people to view these files. Within this action, be sure that you

Validate that the name in the request is a simple, valid filename matching an existing file in the directory or row in the table. Do not accept filenames such as ../../etc/passwd (see the sidebar Input Validation Is Difficult). You might even want to store uploaded files in a database table and use ids, rather than names, to refer to them.

When you download a file that will be displayed in a browser, be sure to escape any HTML sequences it contains to eliminate the potential for XSS attacks. If you allow the downloading of binary files, make sure you

4.Session fixation attacks are described in great detail in a document from ACROS Security, available at http://www.secinf.net/uplarticle/11/session_fixation.pdf.

Report erratum

DONT STORE SENSITIVE INFORMATION IN THE CLEAR 609

Input Validation Is Difficult

Johannes Brodwall wrote the following in a review of this chapter:

When you validate input, it is important to keep in mind the following.

Validate with a whitelist. There are many ways of encoding dots and slashes that may escape your validation but be interpreted by the underlying systems. For example, ../, ..\, %2e%2e%2f, %2e%2e%5c, and ..%c0%af

(Unicode) may bring you up a directory level. Accept a very small set of characters (try [a-zA-Z][a-zA-Z0-9_]* for a start).

Don’t try to recover from weird paths by replacing, stripping, and the like. For example, if you strip out the string ../, a malicious input such as

....// will still get through. If there is anything weird going on, someone is trying something clever. Just kick them out with a terse, noninformative message, such as “Intrusion attempt detected. Incident logged.”

I often check that dirname(full_file_name_from_user) is the same as the expected directory. That way I know that the filename is hygienic.

set the appropriate Content-Type HTTP header to ensure that the file will not be displayed in the browser accidentally.

The descriptions starting on page 431 describe how to download files from a Rails application, and the section on uploading files starting on page 501 shows an example that uploads image files into a database table and provides an action to display them.

26.8Don’t Store Sensitive Information in the Clear

You might be writing applications that are governed by external regulations (in the United States, the CISP rules might apply if you handle credit card data, and HIPAA might apply if you work with medical data). These regulations impose some serious constraints on how you handle information. Even if you don’t fall under these kinds of rules, you might want to read through them to get ideas on securing your data.

If you use any personal or identifying information on third parties, you probably want to consider encrypting that data when you store it. This can be as simple as using Active Record hooks to perform AES128 encryption on certain attributes before saving a record and using other hooks to decrypt when reading.5

5. Gems such as EzCrypto (http://ezcrypto.rubyforge.org/) and Sentry (http://sentry.rubyforge.org/) might simplify your life.

Report erratum

USE SSL TO TRANSMIT SENSITIVE INFORMATION 610

However, think of other ways that this sensitive information might leak out.

Is any of it stored in the session (or flash)? If so, you risk exposing it if anyone has access to the session store.

Is any of it held in memory for a long time? If so, it might get exposed in core files should your application crash. Consider clearing out strings once the data has been used.

Is any of the sensitive information leaking into your application log files? This can happen more than you think, because Rails is fairly promiscuous when it comes to logging. In production mode, you’ll find it dumps request parameters in the clear into production.log.

As of Rails 1.2, you can ask Rails to elide the values of certain parameters using the filter_parameter_logging declaration in a controller. For example, the following declaration prevents the values of the password attribute and any fields in a user record being displayed in the log.

class ApplicationController < ActionController::Base

filter_parameter_logging :password, :user

#...

See the Rails API documentation for details.

26.9Use SSL to Transmit Sensitive Information

The SSL protocol, used whenever a URL starts with the protocol identified https, encrypts traffic between a web browser and a server. You’ll want to use SSL whenever you have forms that capture sensitive information, and whenever you respond to your user with sensitive information.

It is possible to do this all by hand, setting the :protocol parameter when creating hyperlinks with link_to and friends. However, this is both tedious and error prone: forget to do it once, and you might open a security hole. The easier technique is to use the ssl_requirement plugin. Install using

depot> ruby script/plugin install ssl_requirement

Once installed, you add support to all your application’s controllers by adding an include to your application controller.

class ApplicationController < ActiveRecord::Base include SslRequirement

end

Now you can set policies for individual actions in each of your controllers. The following code comes straight from the plugin’s README file.

Report erratum