Preventing cross-site scripting attacks-in your web applications

Source: Internet
Author: User
Tags taint tainted
Document directory
  • Introduction
  • What is "cross-site scripting "?
  • Solutions
  • Solutions for mod_perl
  • Tainting + Apache: Request... Apache: taintrequest
  • Conclusions
  • Resources
By Paul Lindner
February 20,200 2

Introduction

The cross-site scripting attack is one of the most common, yet overlooked, security problems facing Web Developers today. A web site is vulnerable if it displays user-submitted content without checking for malicious script tags.

Luckily, Perl and mod_perl provide us with easy solutions to this problem. We highlight these built-in solutions and also a introduce a new mod_perl module:Apache: taintrequest. This module helps you secure mod_perl applications by applying Perl's powerful "tainting" rules to HTML output.

What is "cross-site scripting "?

Lately the news has been full of reports on web site security lapses. some recent headlines include the following grim items: security problems open Microsoft's wallet, Schwab financial site vulnerable to attack, or new hack poses threat to popular Web Services. in all these cases the root problem was caused byCross-Site ScriptingAttack. instead of targeting holes in your server's operating system or web server software, the attack works directly against the users of your site. it does this by tricking a user into submitting web scripting code (JavaScript, JScript, etc .) to a dynamic form on the targeted Web site. if the web site does not check for this scripting code it may pass it verbatim back to the user's browser where it can cause all kinds of damage.

Consider the following URL:

http://www.example.com/search.pl?text=<script>alert(document.cookie)</script>

If an attacker can get us to select a link like this, and the Web application does not validate input, then our browser will pop up an alert showing our current set of cookies. this particle example is harmless; an attacker can do much more damage, including stealing passwords, resetting your home page, or redirecting you to another Web site.

Even worse, you might not even need to select the link for this to happen. If the attacker can make your application display a chunk of HTML, you're in trouble. BothIMGAndIFRAMETags allow for a new URL to load when HTML is displayed. for example the following HTML Chunk is sent by the badtrans worm. this worm uses the load-on-view feature provided by the IFRAME tag to infect systems running Outlook and Outlook Express.


--====_ABC1234567890DEF_====
Content-Type: multipart/alternative;
boundary="====_ABC0987654321DEF_===="

--====_ABC0987654321DEF_====
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable


<HTML><HEAD></HEAD><BODY bgColor=3D#ffffff>
<iframe src=3Dcid:EA4DMGBP9p height=3D0 width=3D0>
</iframe></BODY></HTML>
--====_ABC0987654321DEF_====--

--====_ABC1234567890DEF_====
Content-Type: audio/x-wav;
name="filename.ext.ext"
Content-Transfer-Encoding: base64
Content-ID: <EA4DMGBP9p>

This participant ular example results in executable code running on the target computer. The attacker cocould just as easily insert HTML using the URL format described earlier, like this:

<iframe src="http://www.example.com/search.pl?text=<script>alert(document.cookie)</script>">

The "Cross-Site" part of "cross-site scripting" comes into play when dealing with the web browser's internal restrictions on cookies. the javascript interpreter built into modern Web browsers only allows the originating site to access it's own private cookies. by taking advantage of poorly coded scripts the attacker can bypass this restriction.

Any poorly coded script, written in Perl or otherwise, is a potential target. the key to solving cross-site scripting attacks is to never, ever trust data that comes from the web browser. any input data shoshould be considered guilty unless proven innocent.

Solutions

There are a number of ways of solving this problem for Perl and mod_perl systems. all are quite simple, and shocould be used everywhere there might be the potential for user submitted data to appear on the resulting web page.

Consider the following scriptSearch. pl. It is a simple CGI script that takes a given parameter named 'text' and prints it on the screen.


#!/usr/bin/perl
use CGI;

my $cgi = CGI->new();
my $text = $cgi->param('text');

print $cgi->header();
print "You entered $text";

This script is vulnerable to cross-site scripting attacks because it blindly prints out submitted form data. to rid ourselves of this vulnerability we can either perform input validation, or insure that user-submitted data is always HTML escaped before displaying it.

We can add input validation to our script by inserting the following line of code before any output. This Code eliminates everything but letters, numbers, and spaces from the submitted input.


$text =~ s/[^A-Za-z0-9 ]*/ /g;

This type of input validation can be quite a chore. another solution involves escaping any HTML in the submitted data. we can do this by using the HTML: Entities module bundled in the libwww-perl CPAN distribution. the HTML: Entities module provides the function HTML: entities: encode (). it encodes HTML characters as HTML Entity references. for example, the character<Is converted& Lt;,"Is converted& Quot;, And so on. Here is a versionSearch. plThat uses this new feature.


#!/usr/bin/perl
use CGI;
use HTML::Entities;

my $cgi = CGI->new();
my $text = $cgi->param('text');

print $cgi->header();
print "You entered ", HTML::Entities::encode($text);
Solutions for mod_perl

All of the previous solutions apply to the mod_perl programmer too. an Apache: Registry script or mod_perl handler can use the same techniques to eliminate cross-site scripting holes. for higher performance you may want to consider switching CILS from HTML: entities: encode () to mod_perl's much faster Apache: util: escape_html () function. here's an example of an Apache: Registry script equivilant to the precedingSearch. plScript.


use Apache::Util;
use Apache::Request;

my $apr = Apache::Request->new(Apache->request);

my $text = $apr->param('text');

$r->content_type("text/html");
$r->send_http_header;
$r->print("You entered ", Apache::Util::html_encode($text));

After a while you may find that typing Apache: util: html_encode () Over and over becomes quite tedious, especially if you use input validation in some places, but not others. to simplify this situation consider using the Apache: taintrequest module. this module is available from CPAN or from the mod_perl developer's cookbook web site.

Apache: taintrequest automates the tedious process of HTML escaping data. It overrides the print mechanic in the mod_perl Apache module. The newPrintMethod tests each chunk of text for taintedness. If it is tainted the module assumes the worst and HTML-escapes it before printing.

Perl contains a set of built-in security checks knowTaint Mode. These checks protect you by insuring thatTaintedData that comes from somewhere outside your program is not used directly or indirectly to alter files, processes, or directories. Apache: taintrequest extends this listDangerousOperations to include printing HTML to a Web client.UntaintYour data just process it with a regular expression. tainting is the Perl Web Developer's most powerful defense against security problems. ConsultPerlsecMan page and use it for every web application you write.

To activate Apache: taintrequest simply add the following Directive to your httpd. conf.

       PerlTaintCheck on    

This activates taint mode for the entire mod_perl server.

The next thing we need to do modify our script or handler to use Apache: taintrequest instead of Apache: request. The preceding script might look like this:


use Apache::TaintRequest;

my $apr = Apache::TaintRequest->new(Apache->request);

my $text = $apr->param('text');

$r->content_type("text/html");
$r->send_http_header;

$r->print("You entered ", $text);

$text =~ s/[^A-Za-z0-9 ]//;
$r->print("You entered ", $text);

This script starts by storing the tainted form data 'text' in $ text. if we print this data we will find that it is automatically HTML escaped. next we do some input validation on the data. the following print statement does not result in any HTML escaping of data.

Tainting + Apache: Request... Apache: taintrequest

The implementation code for Apache: taintrequest is quite simple. It's a subclass of the Apache: request module, which provides the form field and output handling. we overridePrintMethod, because that is where we HTML Escape the data. We also overrideNewMethod -- this is where we use Apache's tiehandle interface to insure that output to stdout is processed by our print () routine.

Once we have output data we need to determine if it is tainted. This is whereTaintModule (also available from CPAN) becomes useful. We use it inPrintMethod to determine if a printable string is tainted and needs to be HTML escaped. If it is tainted we use the mod_perl function Apache: util: html_escape () to escape the HTML.


package Apache::TaintRequest;

use strict;
use warnings;

use Apache;
use Apache::Util qw(escape_html);
use Taint qw(tainted);

$Apache::TaintRequest::VERSION = '0.10';
@Apache::TaintRequest::ISA = qw(Apache);

sub new {
my ($class, $r) = @_;

$r ||= Apache->request;

tie *STDOUT, $class, $r;

return tied *STDOUT;
}


sub print {
my ($self, @data) = @_;

foreach my $value (@data) {
# Dereference scalar references.
$value = $value if ref $value eq 'SCALAR';

# Escape any HTML content if the data is tainted.
$value = escape_html($value) if tainted($value);
}

$self->SUPER::print(@data);
}

To finish off this module we just need the tiehandle interface we specified in ourNew ()Method. The following code implementsTiehandleAndPrintMethod.


sub TIEHANDLE {
my ($class, $r) = @_;

return bless { r => $r }, $class;
}

sub PRINT {
shift->print(@_);
}

The end result is that tainted data is escaped, and untainted data is passed unaltererd to the Web Client.

Conclusions

Cross-site Scripting is a serious problem. the solutions, input validation and HTML escaping are simple but must be applied every single time. an application with a single overlooked form field is just as insecure as one that does no checking whatsoever.

To insure that we always check our data Apache: taintrequest was developed. It builds upon Perl's powerful data tainting feature by automatically HTML escaping data that is not input validated when it is printed.

Resources
  • CERT Advisory CA-2000-02 malicious HTML tags embedded in client Web requests
  • The mod_perl developer's cookbook
  • Download Apache: taintrequest

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.