A startup named BUNGLE is about to launch its first product—a web search engine—but their investors are nervous about security problems. The site is written in Python using the Bottle web framework. Although Bottle has built-in mechanisms that help guard against some common vulnerabilities, the Bunglers have circumvented or ignored these mechanisms in several places. In addition to providing search results, the site accepts logins and tracks users’ search histories. Usernames, passwords, and search histories are stored in a MySQL database.
The website repies to five main URLs: /
, /search
, /login
, /logout
, and /create
.
/
)The main page accepts GET
requests and displays a search form. When submitted, this form issues a GET
request to /search
, sending the search string as parameter q
(i.e., /search?q=HelloWorld]
).
If no user is logged in, the main page also displays a form that gives the user the option of logging in or creating an account. The form issues POST
requests to /login
and /create
.
/search
)The search results page accepts GET
requests and prints the search string, supplied in the q
query parameter, along with the search results. If the user is logged in, the page also displays the user’s recent search history in a sidebar.
Note: Since actual search is not relevant to this project, you might not receive any results.
/login
)The login handler accepts POST
requests and takes plaintext username
and password
query parameters. It checks the user database to see if a user with those credentials exists. If so, it sets a login cookie and redirects the browser to the main page. The cookie tracks which user is logged in; manipulating or forging it is not part of this project.
/logout
)The logout handler accepts POST
requests. It deletes the login cookie (if one is set) and redirects the browser to the main page.
/create
)The create account handler accepts POST
requests and receives plaintext username
and password
query parameters. It inserts the username and password into the database of users, unless a user with that username already exists. It then logs the user in and redirects the browser to the main page.
Note: The password is neither sent nor stored securely; however, none of the attacks you implement should depend on this behavior. You should choose a password that other groups will not guess, but never use an important password (e.g., your UID password) to test an insecure site!
The following shows the source code for every CSRF and XSS defense level available in the site.
class CSRFNone(object):
@staticmethod
def init(request, response):
return None
@staticmethod
def formHTML(token):
return ""
@staticmethod
def validate(request, token):
pass
class CSRFToken(object):
@staticmethod
def init(request, response):
token = request.get_cookie("csrf_token")
if token is None:
token = os.urandom(16).encode('hex')
response.set_cookie("csrf_token", token)
return token
@staticmethod
def formHTML(token):
return ""
@staticmethod
def validate(request, token):
if request.forms.get('csrf_token') != token:
raise HTTPError(403, output="CSRF Attack Detected (bad or missing token)")
class XSSNone(object):
@staticmethod
def init(response):
response.set_header("X-XSS-Protection", "0");
@staticmethod
def filter(input):
return input
script
tags)class XSSRemoveScript(object):
@staticmethod
def init(response):
response.set_header("X-XSS-Protection", "0");
@staticmethod
def filter(input):
return re.sub(r"(?i)script", "", input)
class XSSRemoveSeveralTags(object):
@staticmethod
def init(response):
response.set_header("X-XSS-Protection", "0");
@staticmethod
def filter(input):
return re.sub(r"(?i)script|<img|<body|<style|<meta|<embed|<object", "", input)
"
, '
, and ;
)class XSSRemovePunctuation(object):
@staticmethod
def init(response):
response.set_header("X-XSS-Protection", "0");
@staticmethod
def filter(input):
return re.sub(r"[;'\"]", "", input)
< and >
)class XSSEncodeAngles(object):
@staticmethod
def init(response):
response.set_header("X-XSS-Protection", "0");
@staticmethod
def filter(input):
return input.replace("<", "<").replace(">", ">")