Malicious Toolbars

We recently received a bug report for a web application. The user was unable to use the application due to JavaScript errors that showed up when loading the main page and the screenshot we received showed JavaScript code in a place where the application usually displays a list of informational messages:

Our first attempt was to google for the code snippet to see if it was mentioned elsewhere. It showed up on a few sites, in some forums but nothing really interesting.

The screenshot included an additional detail that caught our attention. A few toolbars were installed in Internet Explorer including the Pdfforge Toolbar:

This toolbar comes with PDFCreater and Wikipedia has some details on it:

The installation package includes a closed-source browser toolbar that is considered by many users to be malicious software (see below). Although technically an optional component, the opt-out procedure is a multi-step process which is considered by many to be intentionally confusing.

The toolbar injects additional JavaScript code into the browser to track its users, report visited sites and show ads.

It turned out that the toolbar had added an indexOf() function to Array.prototype:

Array.prototype.indexOf=function(a){if(this===void 0||this===null)
throw new TypeError;var b=Object(this),c=b.length>>>0;
if(c===0)return-1;var d=0,e=d;arguments.length>0&&(
d=Number(arguments[1]),d!==d?d=0:d!==0&&d!==1/e&&d!==-(1/e)&&
(d=(d>0||-1)*Math.floor(Math.abs(d))));if(d>=c)return-1;
var f=d>=0?d:Math.max(c-Math.abs(d),0);for(;f<c;f++)
if(f in b&&b[f]===a)return f;return-1}

This seems to be a workaround for older versions of Internet Explorer that don’t support the indexOf() function natively. To understand how the code ended up in the info messages field here is how the application iterated over the array of messages to display:

for (var i in messages) {
  // adds an element for each key in the messages object
  // including messages["indexOf"]
}

The correct way to iterate over an array is however

for (var i = 0; i < messages.length; i++) {
  // adds elements only for the values in the array
}

Yet another case where the two loops show different results is the following:

var a = [];
a[5] = 5;

for (var i=0; i<a.length; i++) {
    // iterates over numeric indexes from 0 to 5
}

compared to

for (var key in a) {
    // shows only the index of "5" and ignores 0 to 4
}

What can we learn from this?

  • Do not use for..in with arrays
  • Do not modify built-in datatypes as others may depend on them
  • Be careful what you install on your computer

Real World Browser Performance

We are currently building a web application for the financial services sector that is highly depending on client side JavaScript and DOM manipulation. Each time the user changes an input parameter the following steps are executed:

  • the data is collected from the user interface,
  • sent to the server,
  • processed there,
  • sent back to the browser
  • where the user interface is finally updated with the results.

The application is based on DWR for Ajax communication, Drools as a rule engine running on the server and some custom Java code. Server side execution is rather fast, in the range of 100-200ms. On the client side things are different. Collecting the data is quite fast, too, below 100ms in every browser. Updating the UI is where most of the time is spent.

The user interface contains a bunch of tables to show the results. Rows are created and removed dynamically depending on the returned data and populated with the corresponding properties. This is done using jQuery for heavy DOM manipulation.

The current version of the tool has been tested with different browsers showing some significant differences:

Browser Time (ms)
MSIE 6.0 3281
Firefox 3.0.4 (Linux) 1492
Firefox 3.0.4 (Windows) 1357
Safari 535.20 (Mac) 632
Google Chrome Beta 2 515

These are just the numbers from our current development version (IE 6 matches the production environment, that’s why we didn’t test with IE 7 or IE 8 beta).

What is interesting is that Google Chrome with the WebKit HTML and V8 JavaScript engine outperforms Firefox by a factor of three and IE 6 by a factor of six. As Safari is also quite fast this seems to result mostly from the WebKit rendering engine.

Adding Presence to Your Website

You might have noticed the small green, yellow or gray icon next to my name in the about section on the right. It shows my XMPP status and my status message. This is done by including a small JavaScript snippet in the template of my blog:

<script type="text/javascript" 
  src="/js/presence.js?uid=stefan.reuter&nick=Stefan%20Reuter">
</script>

The presence.js script is in fact a PHP script that retrieves the XMPP presence from the presence plugin of my Openfire server:

<?php
ini_set('display_errors', false);

$uid = $_GET['uid'];
if (! preg_match('/^[A-Za-z0-9_\.-]+$/', $uid))
{
        echo "document.write('Invalid uid parameter.');";
        die;
}
if (isset($_GET['nick']))
{
        $nick = $_GET['nick'];
}
else
{
        $nick = $uid;
}
if (! preg_match('/^[A-Za-z0-9_\. -]+$/', $nick))
{
        echo "document.write('Invalid nick parameter.');";
        die;
}
$imgtag = "<img src=\"/status/".$uid."\"/>";
$url = "http://openfire:9090/plugins/presence/status?jid="
        .$uid."@reucon.com&type=text";
$text = rtrim(implode(file($url, FILE_SKIP_EMPTY_LINES)));
$text = str_replace("\n","",nl2br(htmlspecialchars($text)));
?>
document.write('<table class="xmpp-status"><tbody>');
document.write('<tr valign="center">');
document.write('<td><?php print $imgtag; ?></td>');
document.write('<td><?php print $nick; ?></td>');
document.write('</tr>');
<?php if ($text != 'null') { ?>
document.write('<tr>');
document.write('<td> </td>');
document.write('<td><?php print $text; ?></td>');
document.write('</tr>');
<?php } ?>
document.write('</tbody></table>');

References