University of Minnesota
Development of Secure Software Systems
index.php

CSci 4271 Lab 14b

This week's lab returns to web-vulnerability attacking with examples of Cross-Site Request Forgery (CSRF) vulnerabilities. These arise when site accepts requests on behalf of a user by relying on authentication information like a cookie that it sent automatically, but missing that other aspects of the request came from an invalid source. As we did with SQL injection, we'll be exercising known vulnerabilties in the WebGoat server; this week we'll also be using the companion tool named WebWolf which is also a web application, but simulates an attacker's site.

Refer back to week 9 for basic background about running WebGoat. As before, you should start your own copy of the WebGoat server using a large .jar file we've already installed. This time you'll need to pick three different port numbers for WebGoat, WebWolf, and the SQL server they share. In the examples we'll use a pattern where you pick a number N between 8000 and 9000 to be the WebGoat web interface, and then use N-1000 for the WebWolf interface and N+1000 for the SQL server. In particular the examples use 8234, 7234, and 9234, but you'll need to pick different numbers especially if you're on the same machine as another student. The current version runs both WebGoat and WebWolf from a single JAR file, and produces lots of (mostly unimportant) messages on the terminal, so we recommend running in its own terminal window. For instance you can start WebGoat and WebWolf with this command:

env WEBGOAT_PORT=8234 WEBWOLF_PORT=7234 WEBGOAT_HSQLPORT=9234 \
  java -jar \
  /web/classes/Spring-2024/csci4271/labs/09/webgoat-2023.8.jar

The backslash at the end of the first two lines indicates that this is intended to be one long command line, but we've broken it up into pieces because it would be too long otherwise. The shell should interpret it correctly if you cut and paste it all together, as long as the backslash is the last characters on its line. Or you can cut and paste the two parts separately and skip the backslash.

When you want to stop the server, you can kill it by typing Control-C in the window where it is running. The program will also store some persistent data in your home directory in a directory named .webgoat-2023.8; you can remove this if you're done with it.

Among CSE Labs workstations, you should be able to complete this assignment using old VOLE, new VOLE (VOLE-FX3), or an Ubuntu 22.04 workstation like the ones in 1-262 Keller. But we saw some intermittent problems with WebWolf on the new VOLE, so it wouldn't be our first recommendation. If the "Browse" button to select a file to upload in WebWolf doesn't work, try Chrome or Chromium instead. Another workaround we have sometimes seen to help is that if you get a 500 error code from the WebWolf upload, it can be fixed by deleting an empty file named /tmp/webwolf-fileserver/username, where "username" is your WebGoat/WebWolf username, and replacing it with an empty directory (c.f. this issue #1737).

Or if you are blocked by any other problems with WebWolf, you can also take the same files you would have uploaded to WebWolf and just view them directly in your browser. To do this, enter file:///home/goldy007 (note: three slashes), where goldy007 is your username, and you can browse to any HTML file stored in your home directory.

Once the WebGoat web server is running you can connect to it from your favorite web browser (on the same machine, or with SSH forwarding) at a URL like:

http://localhost:8234/WebGoat

Where of course you replace 8234 with the port number you chose in the previous step. You'll have to create an account when you log in for the first time, though if you didn't delete the data files from before, the same account will still be around. Analogously you can find WebWolf at:

http://localhost:7234/WebWolf

There's also a button with a wolf icon on the WebGoat page that will also take you to WebWolf. Because they share the same backend database, you can use your same WebGoat account for WebWolf.

It's important to keep in mind that there are three different entities involved in a CSRF attack: a benign site (e.g., bank.com), a user of the benign site (the customer whose account is going to be accessed), and a separate malicious web site (e.g., attacker.com). This is the reason for the separation between WebGoat and WebWolf: WebGoat is like bank.com, while WebWolf is like attacker.com. But of course unless you're doing the lab together with a friend, you'll need to play the roles of both the victim and the attacker. When you're logged into WebGoat, you're the victim. But the attacker can use WebWolf's capabilities to set up traps for the victim. In particular for this assignment you need to use WebWolf's "Files" feature to host web pages that the victim will click on. In a complete real world attack the attacker might need to do things like buy ads to attract victims to attacker.com and put enticing messages in links to tempt users to click on them, but for the lab we'll just assume that if the attacker makes a web site, the victim will come along and click on it.

The CSRF module of WebGoat can be reached from the main menu after you log in, first under "(A10) Sever-side Request Forgery", and then "Cross-Site Request Forgeries". (Note this is different from how they are categorized in the OWASP report.) The different pages of the module each have their own instructions, but we'll mention some extra suggestions for particular steps below:

Page 3: basic exercise

If you were creating a benign web site, you would generally create an HTML form and the server-side code that processes it in tandem so that they work together. To create a CSRF attack, you as the attacker need to create a new HTML page that the victim will be tempted to click on, but that will have your attacker-desired effect when processed by the bank.com server-side code. In order to see what information your attack page will need to send, you can compare with how the form on the benign site is written. However because the relevant parts of the WebGoat pages are loaded asynchronously, the traditional web browser "View Source" won't show you the information you're interested in. What we recommend instead is the web developer "Inspector" tool in recent versions of Firefox: you can get information about a piece of content on a page by right-clicking on it and choosing "Inspect Element", which pops up information at the bottom of your window, including a tree of HTML tags. If you haven't worked with HTML forms before, the basic structure is a <form> on the outside, whose attributes include where and how the form will be submitted, and then <input> tags inside that, each of which supplies one field's worth of information.

To set up the CSRF attack, you'll need to make your own little web site with a similar form, or something else like JavaScript that will have the right effect when the user clicks on it. You can create this in a text editor, cutting and pasting relevant information from the WebGoat web site. Then save this HTML in a file, upload the file in the Files section of WebWolf, and view the file after uploading it. (Each time you upload a file you'll need to give it a unique name.) Then you can switch to pretending to be the victim and clicking on something the attacker created in the page. Note that to confirm that you carried the attack out successfully, some of the pages will print a unique "flag" value when successfully attacked, which you can cut and paste back into WebGoat.

Page 4: reviews

This question is a fairly small generalization of the previous one, with one more defense that you'll need to subvert. You don't actually have to put in a full review for the attack to count as successful, but you might look into how to control the text of the review and the rating, since those are things a real attacker would want to control.

Page 5: headers as a defense

The first section of this page describes using a special HTTP header as part of a CSRF defense, but the second part describes how some forms of that defense are not effective if the victim has other software that can be tricked into sending a request with a custom header. An important distinction is that in the more secure approach described first, it isn't just the presence of the header that marks a request as legitimate. Instead the header has a value that is a value not known to an attacker, like a cookie.

Page 7: sending JSON

Like a lot of web attacks, the details here all have to do with quoting and text processing that's needed to squeeze attack data through an unexpected place: in this case specifically using a plain form to create a request that the benign web site sends in using JSON.

A previous time we used this WebGoat module in a lab, we had some problems with the link to pentestmonkey.net being flagged as malicious. We believe this was a false positive. In case the problem recurs, here's a archive.org copy of the page.

The key suggestion from the linked blog post is that setting the attribute enctype="text/plain" in the form tag will disable most of the extra escaping that the browser would normally do on form data. Since the JSON uses a lot of double quotes, it's good to know that HTML attributes can use single quotes to avoid having to escape the double quotes. Also, you can avoid line breaks in the attribute by using the fact that they aren't mandatory in JSON; they're equivalent to any whitespace.

Page 8: login CSRF

If you follow literally the steps described on this page, WebGoat should count the attack as successful. In a more realistic version of the attack, the process of logging in as the attacker should happen in a way that the victim doesn't intend or notice, such as an automatically posted form. But WebGoat doesn't check for that.