Last Friday, Adblock Plus developer Wladimir Palant refuted five typical excuses for calling the
eval(), and the string gets executed as though it were ordinary code. When I took Stanford’s hacking class last spring, we developed an exploit that targeted a fictitious website’s generous use of the function.
Were you to conduct a comprehensive survey of computer programmers, I’d suspect that nearly all of us would rate ourselves “above average” programmers who keep particularly good best practices in mind at all times. Like, to avoid
eval() at all costs. But I called that function – once – and Wladimir caught me.
The gory technical details go something like this: Mozilla-based applications like Firefox have user interfaces built in an XML-based language called XUL. Textboxes in XUL look kind of like textboxes in HTML:
<textbox value="foobar" />.
<textbox value="foobar" oninput="this.value = 'barbaz';" />
This textbox changes its text to say “barbaz” every time you try to type or paste something in.
Since AVIM is an IME, it similarly changes the textbox’s contents when you type in it. But for various reasons, the
oninput attribute has no effect when AVIM interferes with the text. That prevents the interface from responding properly to input in places like the Find Bar and the Library (formerly the Bookmarks Organizer).
So what’s my solution? After searching for low-level, implementation-detail functions to do what I want, I settle on calling – naturally –
eval() with the contents of the
oninput attribute. After some quick testing to verify that it works, I ship a new version of AVIM. To make myself feel better about knowingly using such a dangerous function, I added this comment above the call to
// Truly awful kludge
Indeed. The problem is that, like all extensions, AVIM is given more privileges than an ordinary webpage script. It can access APIs for everything from opening dialog boxes to saving files. With enough effort, you might even be able to get files to execute. Such privileges aren’t usually a problem, since malicious and malware-laden extensions rarely go public on the official Firefox Add-ons website.
eval() function doesn’t know where the string you’re giving it came from. That string may come from a webpage that contains a textbox with the
eval() just assumes you wanted it to execute exactly what you, the extension, told it to. So the string gets executed within the extension’s scope, with all the extension’t privileges, and with access to plenty of Mozilla’s low-level interfaces.
As a concrete example, what do you think would happen if a webpage contained this HTML textbox:
<input oninput="delete avim;" />
Never mind that
oninput isn’t a standard HTML attribute: my extension never checked, and
eval() certainly couldn’t be bothered to. If you have AVIM enabled and start typing in this textbox, AVIM winds up disabling itself.
Cool, huh? One could imagine doing a bit more with that line of attack.
After Wladimir wrote about
eval(), I spent several hours searching for more low-level functions that would execute the
oninput code in a safer way, but nothing seemed clean or sane enough to actually use. As usual the solution turned out simpler than I ever imagined: generate a fake
So, yeah: upgrade now, pretend I never made this mistake, and hope you never do either.
This post was embargoed for eight days to give AVIM’s users adequate time to upgrade.