Wednesday, October 3, 2007

Password Stealing For Dummies

Password stealing for dummies

... or why Cross Site Scripting really matters

Ever wondered why Cross Site Scripting (XSS) is said to be such a bad thing? Who on Earth clicks on links that are 8 inches long, contain funny characters en masse and still enters valid log-in data? Our little demo shows that XSS can be hidden everywhere and it makes your password an easy prey.

The whole security model of JavaScript depends on the origin of code. Code that comes from the same server as a web page that has just been loaded is automatically trusted; it can therefore read and modify most aspects of such a web page whilst it is displayed in the browser. Cross Site Scripting is a method to grab those rights by pushing malicious code into your browser in a way that makes it appear as if it is coming from the same server as, say, a log-in page.

A little demo

Imagine that this Demo log-in is the regular log-in page of our server. Click on that link to open it, use it, and take a look at the code. It is nothing special, just a plain form submitting the access data back to itself, when you press "log-in". After you click on log-in, your data is sent back to the form in clear text and displayed as "username=" and "password=" in the address bar of the browser window. So, when trying this out, don't use real passwords.

Now imagine that this article that you are reading was a page containing evil code, that had somehow been injected by an attacker. Now we can adjust our demo accordingly. If you press the Demo button below, the Demo log-in page will again open. Note that this is not a fake such as used to be used in old phishing attacks. It is the real log-in page, as you can see by checking the address bar of the new window. You can even check the source code – it's still the same simple log-in form.

However, things are different with this second stage of the demo because our evil code is in control in the background. It plants an invisible bug into the Demo log-in page, that watches what you do. When you click on "log-in", an alert message appears and displays your password. This alert was triggered by that evil code. It grabs the password from the Demo log-in page and instead of displaying your password to you as in the demo, it could easily have sent it to any location on the internet. The log-in page sees nothing of this sniffing done by the evil page and otherwise works as intended.


Almost all of this could have been done automatically, triggered just by opening this "evil" page. The code could sit in the background and wait for the next time you use the log-in form. Or it could activate a "log-out" link, present some reasonable message about inactivity timeouts and open the log-in window requiring you to log-in again. The only thing you have to do is enter your password – and not even that, if a password manager fills it in automatically. Then theft of your password could be completely hidden in the background. All of this is currently being packaged in exploit modules, so that attackers can generate suitable payloads for their XSS attacks on the fly.

The trick

Clicking on "Demo" activates some JavaScript code. This code opens the Demo log-in page in a new window. Because the Demo log-in page originates from the same server as the JavaScript code – they share the same origin – the latter has all the rights to read and modify attributes of the log-in page as it is displayed in the browser. It uses these rights to attach an additional onsubmit-function that is executed when you click on "log-in", then reads the password from the form properties and presents it in an alert box. This works with almost every browser capable of JavaScript, i.e. Internet Explorer, Firefox, Opera, Safari, you name it.

This type of evil JavaScript code is by no means rocket science. In fact it is very simple and is well known by the bad guys. There is therefore no harm in showing it here:

function open_steal_login() {
mylogin ="demo-login.html");
mylogin.onload = function() {
mylogin.document.forms[0].onsubmit = stealit;

function stealit() {
alert('Your password is: ' +
mylogin.document.forms[0].password.value + ' !');

A click on the Demo link activates open_steal_login(). This opens a new window with "demo-login.html" and the onload function attaches stealit() to the form, after the login page has been loaded. That's about it.


All that is required is that an attacker is able to place JavaScript code onto a server – or at least to make it look to your browser as if the code originates from that server. That means that he can manipulate all content from that server at will. In general, this can happen on pages with user generated content, that is not filtered carefully enough. Examples are user home pages, forums or classical Cross Site Scripting scenarios with web applications, that reflect parameters like "> back to the user. For such an attack and our demo to work the user needs to have JavaScript enabled.


This is a hard one! Don't trust sites that allow others to create pages containing JavaScript. On the other hand, the code could have been inserted via Cross Site Scripting (XSS). So don't trust sites that are vulnerable to XSS. But hey – how would you know which they are? Even the best get hit by that plague – penetration testers claim very high success rates beyond 90 per cent on that one.

Disabling JavaScript completely takes you to the safe zone. But this is not really an option for most of us; too many sites depend on it nowadays. With Internet Explorer you can work with zones and allow Active Scripting only for trusted sites (by the way: the heisec Browsercheck helps you to configure your browser for greater security). If you are using Firefox, you can install the extension NoScript. This allows you to disable JavaScript and carefully build a whitelist of selected servers, that are allowed to execute JavaScript. Additionally it features some XSS protection mechanisms that we have not examined yet. Apart from that, all that can be said is: be careful, stay alert to possible dangers, keep your eyes open and hope for good karma

No comments: