Last week I wrote a post noting security vulnerabilities on Backloggery. I've left it until now to give more specific details, as the cross-site scripting vulnerability has since been fixed, but the cross-site request forgery remains an issue.
I've recorded a companion audio blog to this if you'd prefer a verbal explanation rather than the verbose written version.
To start off, we'll define terms.
Cross-Site Scripting - When JavaScript from an untrusted source is placed on the page. For example, if a forum post is allowed to include JavaScript, that is vulnerable to a cross-site scripting attack. There are multiple dangers to this, but I'll detail the main 3
None of these are good, and even if you don't care about your user's safety, the cookie issue puts their accounts at risk. Cookies can only be read on the site they're from (a cookie that allows you to log into an account on google.com cannot be read from yahoo.com), and this is fundamental to the web. However, JavaScript on google.com can read the cookie from google.com (same domain), but JavaScript can also send that information to an external source, which is the problem.
Cross-Site Request Forgery - When data is accepted by the server without verification of the source. For example, if an external site can include a form that allows a user to submit a forum post, that is vulnerable to a cross-site request forgery. A web form is typically structured as follows:
-Action (e.g. goes to example.com/receiveForm.php)
-Content (e.g. forum post content)
The server receives this information and it doesn't matter where the content came from, whether it be example.com or evil.com. There is technically a value in the HTTP header that provides the source, but that's spoofable.
The Backloggery vulnerabilities
First there's the cross-site scripting issue. What happened was in writing a script to automatically submit games to Backloggery, it stored the case of the system (so on Backloggery Wii is stored as "Wii" and if you submit "WII" it's considered a different system). Curious, then, I suspected the console was not being filtered, and this turned out to be correct.
It's a very easy vulnerability to demonstrate, particularly if you have Opera installed. Log into Backloggery and go to the Add a Game page. On that page, choose View->Page Source, then find the drop down menu options, and change the value, then click Apply changes.
The Add a Game page will refresh with the updated entry.
Once submitted, it displays on the user's main page and runs the code.
The way to prevent this attack is quite simple, though, and that's to filter the input. In this case, there's absolutely no reason to allow any HTML tags, so just stripping them resolves the issue.
Second is the cross-site request forgery problem. This is another that comes about from the automatic submission script because there was no issue, and nothing I had to do to accomodate for any protections. What a cross-site request forgery means to the end-user is that as long as you're logged into a site with JavaScript enabled, any other site you go to could make arbitrary submissions on your account because you are in fact logged in already.
Now there is partial protection on Backloggery, as you need to know the username of the target in order for the submission to be accepted, as the submission URL is newgame.php?user=USERNAME_HERE. However, this still allows for targeted attacks, or brute force attacks using the CSS history hack, though somewhat impractical.
What this means in terms of Backloggery is that for example, if I were to have malicious intent, I could include code on The VG Press that would secretly add and delete games to your Backloggery catalogue. This, though, is a little trickier to demonstrate.
Imagine a file on your computer is another site (because, well, for our purposes it is). From there, you should not be able to add games to your account, let alone in the background silently. Here's how to submit a game to Backloggery in JavaScript code, assuming that you're already logged in. Also, I'll just have the whole page submit automatically, so it'll take you right to the completed form.
Save that to a .html file, then open it in your browser. It should immeditely redirect you to the Add a Game telling you of your successful submission.
Checking your catalogue confirms it
The way to fix this properly is to include a cryptographic pseudo-random token in the form that is stored in the user's session cookie. Because external sites wouldn't be able to read the user's cookie, that means it couldn't include the required security token to submit the game.
This on its own, because of the requirement of the username, is a narrow vector. However, combined with the aforementioned cross-site scripting vulnerability, this could have spread like a worm across the site. Since the JavaScript if it were directly on Backloggery could read the username, it could automatically add a game with the XSS script in it in order to spread.
Fortunately, as mentioned previously, the XSS problem has since been fixed.
It's a good warning to those of us involved in web development that something little and easy to overlook can have potentially drastic consequences.
I've recorded a companion audio blog to this if you'd prefer a verbal explanation rather than the verbose written version.
To start off, we'll define terms.
Cross-Site Scripting - When JavaScript from an untrusted source is placed on the page. For example, if a forum post is allowed to include JavaScript, that is vulnerable to a cross-site scripting attack. There are multiple dangers to this, but I'll detail the main 3
- Cookies can be read and disclosed
- The page can be redirected to a malicious site
- A malicious JavaScript exploit could be included
None of these are good, and even if you don't care about your user's safety, the cookie issue puts their accounts at risk. Cookies can only be read on the site they're from (a cookie that allows you to log into an account on google.com cannot be read from yahoo.com), and this is fundamental to the web. However, JavaScript on google.com can read the cookie from google.com (same domain), but JavaScript can also send that information to an external source, which is the problem.
Cross-Site Request Forgery - When data is accepted by the server without verification of the source. For example, if an external site can include a form that allows a user to submit a forum post, that is vulnerable to a cross-site request forgery. A web form is typically structured as follows:
-Action (e.g. goes to example.com/receiveForm.php)
-Content (e.g. forum post content)
The server receives this information and it doesn't matter where the content came from, whether it be example.com or evil.com. There is technically a value in the HTTP header that provides the source, but that's spoofable.
The Backloggery vulnerabilities
First there's the cross-site scripting issue. What happened was in writing a script to automatically submit games to Backloggery, it stored the case of the system (so on Backloggery Wii is stored as "Wii" and if you submit "WII" it's considered a different system). Curious, then, I suspected the console was not being filtered, and this turned out to be correct.
It's a very easy vulnerability to demonstrate, particularly if you have Opera installed. Log into Backloggery and go to the Add a Game page. On that page, choose View->Page Source, then find the drop down menu options, and change the value, then click Apply changes.
The Add a Game page will refresh with the updated entry.
Once submitted, it displays on the user's main page and runs the code.
The way to prevent this attack is quite simple, though, and that's to filter the input. In this case, there's absolutely no reason to allow any HTML tags, so just stripping them resolves the issue.
Second is the cross-site request forgery problem. This is another that comes about from the automatic submission script because there was no issue, and nothing I had to do to accomodate for any protections. What a cross-site request forgery means to the end-user is that as long as you're logged into a site with JavaScript enabled, any other site you go to could make arbitrary submissions on your account because you are in fact logged in already.
Now there is partial protection on Backloggery, as you need to know the username of the target in order for the submission to be accepted, as the submission URL is newgame.php?user=USERNAME_HERE. However, this still allows for targeted attacks, or brute force attacks using the CSS history hack, though somewhat impractical.
What this means in terms of Backloggery is that for example, if I were to have malicious intent, I could include code on The VG Press that would secretly add and delete games to your Backloggery catalogue. This, though, is a little trickier to demonstrate.
Imagine a file on your computer is another site (because, well, for our purposes it is). From there, you should not be able to add games to your account, let alone in the background silently. Here's how to submit a game to Backloggery in JavaScript code, assuming that you're already logged in. Also, I'll just have the whole page submit automatically, so it'll take you right to the completed form.
<script type="text/javascript">
/*
We'll assume this is a targeted attack.
Change the username value to whatever your Backloggery username is in order to test this.
*/
var username = "xsstest";
var name = "CSRF: The Game!";
var console = "HAX";
var region = 0; //0=NA, 1=PAL, 2=JP
var rating = 8; //0=No rating
var complete = 1;
var own = 1; //1=Currently own
var submit1 = "Add Game";
function init() {
var output = '<form id="hiddenForm" action="http://backloggery.com/newgame.php?user='+username+'" method="post">';
output += '<input type="hidden" name="name" value="'+name+'" />';
output += '<input type="hidden" name="console" value="'+console+'" />';
output += '<input type="hidden" name="region" value="'+region+'" />';
output += '<input type="hidden" name="rating" value="'+rating+'" />';
output += '<input type="hidden" name="own" value="'+own+'" />';
output += '<input type="hidden" name="complete" value="'+complete+'" />';
output += '<input type="submit" name="submit1" value="'+submit1+'" />';
output += '</form>';
document.getElementById('hiddenDiv').innerHTML = output;
document.getElementById('hiddenForm').submit();
}
window.onload=init;
</script>
<div id="hiddenDiv" style="display: none"></div>
Save that to a .html file, then open it in your browser. It should immeditely redirect you to the Add a Game telling you of your successful submission.
Checking your catalogue confirms it
The way to fix this properly is to include a cryptographic pseudo-random token in the form that is stored in the user's session cookie. Because external sites wouldn't be able to read the user's cookie, that means it couldn't include the required security token to submit the game.
This on its own, because of the requirement of the username, is a narrow vector. However, combined with the aforementioned cross-site scripting vulnerability, this could have spread like a worm across the site. Since the JavaScript if it were directly on Backloggery could read the username, it could automatically add a game with the XSS script in it in order to spread.
Fortunately, as mentioned previously, the XSS problem has since been fixed.
It's a good warning to those of us involved in web development that something little and easy to overlook can have potentially drastic consequences.
Recently Spotted:
Foolz (8m)
/blog.
So did bl.com give you any response? Or did they just fix it? (I've been wondering).
DLing your aural blog now.