Detect Cross-Site Scripting Attacks with a bash Shell Script

by Mike on August 14, 2009

in Web Server

Cross-site scripting, often abbreviated as “XSS”, is used by malicious hackers to steal information. When an attacker finds a web site that’s vulnerable to this type of attack, he can craft a customized URL that contains the attack code, and then try to trick people into using it.  This will cause information that a user enters into the web browser to be sent to the attacker.

Let’s say that an attacker wants to steal account information from on-line banking customers.  He’d first need to search for on-line bank sites that are vulnerable.  He finally finds one, with the URL of:

https://www.mybigbank.com

Then, he’ll pick out an appropriate bit of XSS attack code, and append it to the end of the URL.  It would then look something like:

https://www.mybigbank.com/<BR SIZE=”&{alert(‘XSS’)}”>

He could then put this into a “phishing” email message, with the custom URL disguised as the real thing, and send it out to unsuspecting users.

For the most part, banking and commerce web sites are more secure than they used to be.  Unfortunately, the topic of safe coding still isn’t well emphasized in most programming or web design courses.  So, it’s still possible that an attacker could find an XSS-vulnerable site.  Also, theoretically, even a “safe” site could be made vulnerable, if an attacker could find a way to upload Java script code to the web server.

If you’re running Apache on your web servers, the best defense against XSS—and other attacks, as well—is to install “mod_security”.  This can not only prevent attacks from being successful, but it can also give you a nice, easy-to-read log that will tell you when these attack attempts occur.

xss_article_21

But, what if you’ve just gone to work for someone who doesn’t have mod_security installed?  What if the boss comes to you, and tells you to look for signs of XSS attacks on the web server?  Recently, this happened to a colleague of mine, who is a security worker at a local credit union.  His boss handed him a USB “thumb” drive that contained four Gigabytes worth of compressed Apache log files, and told him to look through them for signs of cross-site scripting attacks.  Since this guy is only a beginner with things Linux, he gave me a call and asked me if I knew of a way to make this somewhat painless.  I was able to write a simple script that finished the job in only a few hours time.

On the “XSS (Cross Site Scripting) Cheat Sheet” page of the “ha.ckers” web site, you’ll see plenty of examples of code for cross-site scripting attacks.

xss_article_11

If you have an extra Linux machine handy, you can set it up as an Apache server, and launch XSS attacks against it from another machine.  Just open the web browser on the attack machine, and enter the URL of the victim machine, with a chosen piece of XSS code appended to the end.

xss_article_3

xss_article_4

(Of course, with a vulnerable server, you would have seen the actual web site, instead of the “404 Not Found” message.  But, for our purposes, this still works.)

Then, take a look at the Apache access log.  You should see entries for normal site access, such as the following:

192.168.0.252 – - [05/Aug/2009:15:10:16 -0400] “GET / HTTP/1.1″ 403 5043 “-” “Mo
zilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.12) Gecko/2009070812 Ubuntu/8.0
4 (hardy) Firefox/3.0.12″
192.168.0.252 – - [05/Aug/2009:15:10:16 -0400] “GET /icons/apache_pb.gif HTTP/1.
1″ 200 2326 “http://192.168.0.102/” “Mozilla/5.0 (X11; U; Linux x86_64; en-US; r
v:1.9.0.12) Gecko/2009070812 Ubuntu/8.04 (hardy) Firefox/3.0.12″
192.168.0.252 – - [05/Aug/2009:15:10:16 -0400] “GET /icons/powered_by_rh.png HTT
P/1.1″ 200 1213 “http://192.168.0.102/” “Mozilla/5.0 (X11; U; Linux x86_64; en-U
S; rv:1.9.0.12) Gecko/2009070812 Ubuntu/8.04 (hardy) Firefox/3.0.12″
192.168.0.252 – - [05/Aug/2009:15:10:16 -0400] “GET /favicon.ico HTTP/1.1″ 404 2
88 “-” “Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.12) Gecko/2009070812
Ubuntu/8.04 (hardy) Firefox/3.0.12″
192.168.0.252 – - [05/Aug/2009:15:10:19 -0400] “GET /favicon.ico HTTP/1.1″ 404 2
88 “-” “Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.12) Gecko/2009070812
Ubuntu/8.04 (hardy) Firefox/3.0.12″

But, if you see an entry like this . . .

192.168.0.252 – - [05/Aug/2009:15:16:42 -0400] “GET /%27%27;!–%22%3CXSS%3E=&{()
} HTTP/1.1″ 404 310 “-” “Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.12)
Gecko/2009070812 Ubuntu/8.04 (hardy) Firefox/3.0.12″

. . . that’s the sign of an XSS attack.  The part to look for is:

GET /%27%27

The percent sign pattern gets generated by the XSS attack.  There are a couple of variations on this pattern, which we can easily find with an appropriate script.

First we’ll need to create a set of “regular expressions” to find all variations of the attack signature.  The three that I’ve used are “GET /%”, “GET /.%”, and “GET /.=%”.  (The dot is a wildcard, which tells the script to search for any character in that position.)  Now, create the script, using the “find” utility to do the actual search.

#!/bin/bash

inputpath=$1

output_file=$2

if [ -f $output_file ]

then
echo “This file already exists.  Choose another filename.”
exit;
fi

find $inputpath -iname ‘*.gz’ -exec zcat {} \; | grep ‘GET /%’ > $output_file

find $inputpath -iname ‘*.gz’ -exec zcat {} \; | grep ‘GET /.%’ >> $output_file
find $inputpath -iname ‘*.gz’ -exec zcat {} \; | grep ‘GET /.=%’ >> $output_file
less $output_file
exit

To run this, enter the name of the script, followed by the path to your log files, and the name of an output file.  If a file with your chosen name already exists, you’ll receive an error message and the script will exit.  In the case of my colleague, the log files were on a USB “thumb” drive, so he would have entered something like:

./cross-site-search /media/PATRIOT/ ~/cross-site-search-results.txt

Fortunately, my colleague was able to verify that this works in real life.  The previous autumn, the credit union had hired a penetration testing outfit to test security, with XSS attacks being part of the test.  The script found all instances of the pen tester’s attack.

For some variations on the theme . . .

You could modify the script so that it will perform more than one type of search.  Add an “if . . then” structure, and you can choose the type of attack for which you’d like to search.  Here’s one that will search for either XSS attacks or Nikto scans.

#!/bin/bash
inputpath=$1
output_file=$2

if [ -f $output_file ]
then
echo “This file already exists.  Choose another filename.”
exit;
fi

echo “Hello, $USER.”
echo “For what would you like to search?”
echo “Press 1 to search for cross-site scritpting attacks.”
echo “Press 2 to search for Nikto attacks.”
read choice
echo

if [ $choice = 1 ]; then
find $inputpath -iname ‘*.gz’ -exec zcat {} \; | grep ‘GET /%’ > $output_file
find $inputpath -iname ‘*.gz’ -exec zcat {} \; | grep ‘GET /.%’ >> $output_file
find $inputpath -iname ‘*.gz’ -exec zcat {} \; | grep ‘GET /.=%’ >> $output_file
elif [ $choice = 2 ]; then
find $inputpath -iname ‘*.gz’ -exec zcat {} \; | grep ‘Nikto’ > $output_file
fi

less $output_file
exit

And finally, here’s one that will let you search through uncompressed log files.

#!/bin/bash
input_file=$1
output_file=$2

if [ -f $output_file ]
then
echo “This file already exists.  Choose another filename.”
exit;
fi

grep ‘GET /%’ $input_file > $output_file
grep ‘GET /.%’ $input_file >> $output_file
grep ‘GET /.=%’ $input_file >> $output_file

With a little imagination, I’m sure you could come up with other possibilities.

Article Written by  Donnie Tevault

Previous post:

Next post: