This project is Stanford CS 155 Project 2.
Is magic_quotes_gpc enabled on the web server?
Yes, it's enabled. The optional magic_quotes_gpc PHP feature escapes single quotes, double quotes, and backslashes in GET and POST data by prepending a backslash. This feature makes it slightly harder to write websites that are vulnerable to cross-site scripting and SQL injection attacks. However, as you will see in this assignment, sites with magic_quotes_gpc are not magically bug-free. There are many ways that sites can turn off magic_quotes_gpc, such as.htaccess
files,php.ini
files, and by callingstripslashes
on the escaped data. Note that magic_quotes_gpc doesn't do anything to angle brackets (<>). For that, you wanthtmlspecialchars
.
Is register_globals enabled on the web server?
No, it is off. The login page is vulnerable to an attack if register_globals is on, which you are welcome to fix if you want in the second part.
JavaScript, PHP, CSS : How do I learn these?
The definitive resource on PHP is php.net. You can find some introductory tutorials there. You can find a lot of references on Google. There's a decent one at W3Schools. Pay particular attention the DOM examples.
How do I figure out why my Javascript isn't working?
Two extremely useful tools for debugging in Mozilla Firefox are the JavaScript console and the DOM Inspector. Both can be accessed from the Tools menu. The JavaScript console lets you see which exceptions are being thrown and why. The DOM Inspector lets you peek at the structure of the page and the properties and methods of each node it contains. (If the DOM Inspector isn't installed, make sure it's selected when you install Mozilla Firefox.) You might also want to try Firebug.
What do I need to know about CSS?
You only need to know enough to make your attacks disappear. You should know what basic syntax like<style>.warning{display:none}</style>
means, and you should feel free to use stealthy attributes likestyle="display: none; visibility: hidden; height: 0; width: 0; position: absolute"
in the HTML of your attacks. Beware that frames and images may behave strangely withdisplay: none
, so you might want to usevisibility: hidden
instead.
How can I see cookies and form data that the browser sends?
Try the LiveHTTPHeaders browser extension.
Where can I find more information about PHP?
Am I allowed to load scripts or images from other domains?
No, your attacks should not load data from domains other than sphere.cs.berkeley.edu:8080
.
The example attack doesn't seem to do anything. What did I miss ?
You need to be logged in before
the attack will work. When you click the link, you
should get a browser alert with the contents of
document.cookie
.
How am I supposed to send email?
You have to convince the browser to send a GET request to the email script, which will cause an email to be sent by the server to the grader or your specified URL.
How do I get the browser to send a HTTP GET request to an URL of my choosing?
The email
script provides some example code. You allocate a JavaScript
Image
object, and set its src
attribute
to be the URL you want the browser to
retrieve. The browser immediately
tries to fetch the content of this image, even
though the image hasn't
been
inserted into the page anywhere.
How do I put code into a URL? And yes, I want to have wierd charactars like newlines in my code?
Try to URL-encode it.
Should I include the javascript:void
part in my
code?
If you do, your attack might still work, but it's not necessary if you're already within a<script>
tag. Just copy the part starting with(new Image()).src=...
What is this random
query
parameter?
It is to bypass your browser cache. If you try your attack more than once, the browser might think that it already has the image in its cache, and so it wouldn't send a second HTTP GET request. Adding a random number ensures that the browser will treat the new URL as different, and won't use the cache. As you must've noticed, the email script ignores this parameter.
Why are the characters reflected back different from the ones in the URL?
Your query parameter is URL decoded by the server before being reflected back at the user. You'll need to made sure that your attack code is URL encoded. For example, use+
instead of space and%2b
instead of+
. Here is a URL encoding reference and a handy conversion tool.
My attack is working. How should I make it invisible to the user?
The text box should its usual size and in the normal place.
No warning text or characters that are normally part
of the page should be visible. From the point of view of the visitor,
it should appear as if they just visited to users.php
and
didn't put in a username yet (with the possible exception of the
address bar). It's ok if the page
briefly looks weird before correcting itself.
My attack works. But, I had to switch the charactar-set encoding.
Can we assume the grader can be fooled into changing his setting?Why is this not a cross site scripting attack?
It is a cross site request forgery attack because you are exploiting the fact that StockBank uses only a cookie to authenticate requests, even ones with side effects.
Can I use the vulnerability in user.php
from Attack A?
No. Since this not a cross site scripting attack, you do not need to use the vulnerability inuser.php
. All you have to do convince the user's browser to post malicious form data totransfer.php
.
How do I force the browser to send a malicious
POST request to transfer.php
?
Put together a form in your HTML document, withhttp://sphere.cs.berkeley.edu:8080/transfer.php
as theaction
attribute.
How can I get the form to be submitted with no user interaction?
You can call the "Send" button'sclick
method. Or, you can use JavaScript to call the form'ssubmit
method.
How can I submit a form to StockBank
without
causing the browser's address bar to change to sphere.cs.berkeley.edu:8080
?
Create a hidden<iframe>
and make sure the form'starget
attribute matches the frame'sname
attribute.
Ouch, iframes. Will the grader have third-party cookie blocking enabled?
No, third party cookie blocking will not be enabled. It's probably off by default on your browser, but if your attack isn't working because the login cookie isn't sent, you might want to check to make sure.
How do I redirect the browser to my intended URL?
Change thedocument.location
property. Note that it is okay (and required, in fact) for the browser's address bar to change tohttp://sphere.cs.berkeley.edu:8080
once your attack is complete.
How do ensure that the redirect doesn't happen until after the form data has been posted?
You can trigger the redirect from the frame'sonload
handler. Depending on how your code is written, thisonload
handler may get called twice once when the page initially loads and once when the form is submitted. If this is the case, you'll have to make sure that you changedocument.location
on the second time only.
What will the grader do when logging in?
The grader will type a username, then click the password field, type a password, then move the mouse over the login button and click it. The grader will then wait for the login to complete.
Why is the site using JavaScript to focus the username field?
It's a convenience for the user, so they don't have to select the username field manually when they first come to the page. You may it useful as well.
How do I get my injected code in?
Defeat the sanitization. Because your code is sanitized withhtmlspecialchars
, you won't be able to inject a simple<script>
tag like you did in Attack A. Trick the browser into running your code another way.
Does it have something to do with charactar set selection bugs?
No, that's not it.
I think I figured it out, but when I call alert
to test my attack, nothing happens.
It turns out that callingalert
would lead to an infinite loop of dialog boxes, so Firefox is trying to be helpful by preventing it. Try using something likedocument.loginform.login_username.value=42
to test whether your attack is working.
How am I supposed to invoke the email script from my script without using any characters that will get escaped?
There are numerous static methods of String that you might find usable. Also, don't forget aboutescape
,unescape
, andeval
.
Encoding by hand is incredibly tedious. Help?
You can save yourself some headaches if you write out
your
attack as a string in your attack page and then encode it
programmatically, using those static String
methods.
What do I need to do to make my attack invisible to the user?
You'll have to get a handle on the relevant DOM nodes and make the extraneous text disappear, either by deleting the text or setting thestyle.display
property.
How can I get a handle on the warning message? It
doesn't have an
id
attribute.
It does have other distinguishing characteristics. You may find getElementsByTagName useful. Depending on how your attack works, you may not see a warning message anyway.
I'm sending the email when the form is submitted, but it isn't working. What's wrong?
There's a race condition here where the form may be getting submitted before the email image is downloaded. Once the form submit starts, the thread that's downloading the image is killed. So, to ensure that your attack always works, you should delay the form submission a little bit. You can useaddEventListener
with an event handler such asfunction(evt) { evt.preventDefault(); ... }
. In this way, you can prevent the form submission until you're ready to trigger it yourself.
Ok, I prevented the submission. How long should I wait?
If you're lazy, you can usesetTimeout
with a reasonable number of milliseconds. But the precise way of doing it is to useaddEventListener
to wait for the "error" event to fire on the Image object you created. That event indicates that the email script's server has started to respond with a non-image file, meaning that it successfully processed the email send request.
What should I do after the email is sent?
You can trigger the submission manually using the login button'sclick()
method. UseremoveEventListener()
to avoid infinite loops.
How does the site sanitize profiles?
It usesstrip_tags()
to restrict the tags that can be used, and it uses a regular expression to replace certain dangerous words like "onmouseover" with a space character. Note thatstrip_tags()
will remove all tags that are more than 1024 characters. If your solution occurs inside a tag, you will have to make sure it fits inside this limit, or it won't render to the user.
What tags does it allow or disallow in profiles?
Check the sources.
How do I transfer the money?
Many ways : (1) Create an<iframe>
pointing totransfer.php
, set the appropriate form fields inside it, and post the form.
(2) You can create a form on the current page withtransfer.php
as its target, and then post it with thetarget
pointing at an<iframe>
.
(3) Another option is to use XMLHttpRequest, since you're actually making a same-site request this time.
How do I create an <iframe>
?
You can use the DOM methodsdocument.createElement
anddocument.body.appendChild
.
How do I get a handle on form fields inside the
<iframe>
?
It differs by browser, and only works when the
frame's
domain matches the parent page (that's the Same Origin Principle).
Here's the Firefox way of doing it:
iframe.contentDocument.forms[0].dollars.value = 1;
Are there any alternatives to target
,
which is blacklisted?
You can use string concatenation to express "target" without actually saying it. The following are equivalent in JavaScript: x.target, x["target"], x["tar"+"get"].
How do I replace the profile?
Use the same technique you just used ontransfer.php
, but point atindex.php
instead.
Is there an easy way to get a copy of the current profile?
You can usedocument.getElementById('profile').innerHTML
, but it may mangle quotes in your profile, so be sure to check that the replicated profile is still functional. Also, note that onlydisplay:inline
tags can be nested inside a<p>
.
Do I need to look at the files in the includes/
directory?
You should skim these files to get a sense for how the site works, but you're not allowed to change them, so don't spend too much time on it.
How can I get the value of the user's cookie in PHP?
It can be found in$_COOKIE[$user->cookieName]
. The global variable$user
is initialized incommon.php
, and you can find out more about the User class inauth.php
. However, you'll find that the cookie can't be accessed in PHP immediately after being set. An alternative is to obtaindocument.cookie
in JavaScript. You may also findsession_start()
and$_COOKIE[session_name()]
, to be more useful, since you won't have to tiptoe around the site's existing authentication quirks.
Is checking the "HTTP Referer" a valid method of stopping cross-site request forgeries?
No. As discussed in lectures, users may have browsers configured not to send "Referer" information (in fact, "Referer" is never sent for links on HTTPS pages). Also many anonymizing proxies strip "Referer" information.
What should I do to stop Attack D?
You probably want to strengthen the profile sanitizing code and/or replace unsafe JavaScript operations with something simple and straightforward. If you want to guarantee full credit, don't stop sanitizing until you're sure it's secure!
How many more of these vulnerabilities are there for me to find?
More than zero.
What user behavior can I expect?
The attacker may entice the user to view a malicious page, either on StockBankor elsewhere, but the user will only provide their username and password if the address bar starts with
http://sphere.cs.berkeley.edu:8080/
and the login form looks convincing.
Is it a problem if an attacker's site I'm viewing is able to log me out of StockBank against my will?
That's an annoyance, and technically a cross-site request forgery, but by itself it's not a grave security problem, so you don't have to defend against it.
Is it a problem if an attacker can log me in as another user the attacker knows the password for?
Not unless this can be used to impact the security of the user's own account.
How can I find input validation vulnerabilities and fix them?
Look for other places that database data or form data are reflected back at the user. Determine whether magic_quotes_gpc is providing enough protection or whether some other sanitization function likehtmlspecialchars
,strip_tags
, oraddslashes
is required.
Should we worry about users tampering with their own cookies?
No, that's not really a cross-site scripting attack.
You can't change auth.php
anyway.
Should we worry about malicious data that's already in the database?
Your database will be empty when we start the attacks. Anything that we put in it during the attacks (e.g. profiles) will be using your web interface. So either sanitize it on the way in, or on the way out.
Can I make additional assumptions that legitimate users will not do stupid things?
If you want to make reasonable additional assumptions, that most likely
fine, but
please check first with the TA and clearly specify them in the README
file.
I think I've found an attack that isn't a cross-site scripting attack. Should I fix it?
Don't spend too much time hardening the site against other attacks, since they won't be part of the grading. However, if it's an interesting attack, you might want to email TA or mention it in yourREADME
file. Do not disrupt the working of the StockBank web site, so other students can continue working.