Paid Advertising
web application security lab

Diminutive Worm Contest Wrapup

While the fun is over, there is a lot to talk about in the wrap-up. So much so that I think it will take longer to deal with the output of the contest than the contest itself took. First of all, a huge congrats to both Giorgio Maone and Sirdarckcat for winning the contest with an incredibly small 161 byte worm. They tied because they both had nearly the same vector and it worked equally well. It was a tough battle and there were a lot of close calls, but various rules, cross browser compatibility and interoperability with Apache caused the pool of potential winners to be relatively small when the scoring was complete. However, that’s not to diminish everyone’s work - everyone did amazingly and I was very impressed when it all came together.

But now that leaves us to the aftermath. After looking at the contest for the first four days we may have figured out a way to potentially stop worm propagation. Unlike tracking this method actually may help companies devise plans on how to reduce the likelihood of worm propagation across their websites. This should put to rest the nay sayers who thought nothing good could come of this contest. The paper is not for everyone - it’s pretty complex (as worms tend to be), but I think the people who have the problem will understand how to use it in their own environments.

That said, there is at least two or three more potential outputs of this contest - including papers on propagation analytics, worm tracking technology, and potentially other things that I’m not privy to. Was it worth it? Absolutely. I couldn’t have been happier with the results. Thanks again to everyone who made it such a success. It was a lot of work, but it was the first step towards large scale worm defense. Again, a huge congrats to Giorgio Maone and Sirdarckcat!

11 Responses to “Diminutive Worm Contest Wrapup”

  1. Spyware Says:

    Once again, cheers to the winners and everyone else! Thank you RSnake for providing us with a place to spam to hell =]. I’m off reading your paper and watch the bickering in the forum.

  2. Vinicius K-Max Says:

    The best XSS contest ever :D

  3. BlahBlah Says:

    Very nice paper, and thank you for thanking me.

  4. Gregory Fleischer Says:

    @RSnake - Very good, thought-provoking paper. I have a few of questions with respect to the defenses sections of the paper.

    1) Could you explain what you mean by the statement:
    Nonces can be read if they are on the same domain, by
    XMLHttpRequest. So it would stand to reason that it is better to omit
    a nonce on another domain that sites know are completely free of XSS
    vulnerabilities. That is because XMLHttpRequest must obey the same
    origin policy.

    A nonce is only going to be effective on a domain that doesn’t have any XSS vulnerabilities to begin with. So, I fail to see why omitting the nonce on a separate domain (one that doesn’t have XSS holes) provides better defense against a worm. It would seem that one would find a nonce beneficial to protect against blind CSRF attacks.

    2) If I am understanding the invisible iframe approach, the vector has already been injected into the framed content on a separate domain and the user click is required to activate it (e.g., by posting it).

    If that other domain isn’t vulnerable to XSS, is there a common construct that allows this injection? And if the other domain is vulnerable to XSS, why not attack it directly?

    3) If a user doesn’t have JavaScript enabled, is XSS worm propagation even a valid concern? Although interesting as an edge case, does it make sense to create special handling for the situation?

    Once again, very nice work.

  5. RSnake Says:

    @Gregory - very good questions, let me see if I can answer them all for you:

    1) Because we know that XMLHttpRequest doesn’t work in another domain (barring any browser exploits outside of this paper) an attacker must use something else (like automatic form posting) which basically is blind CSRF. The nonce is there (in the other domain) to take blind CSRF off the table which effectively removes both vectors (given the other things I mentioned also being in place).

    2) That’s not what I was saying - Let’s assume the social networking site can secure one lousy page from XSS (I know, huge leap of faith, but go with me on this). The invisible iframe is injected not on that page, but on the vulnerable main part of the site. The iframe itself is actually probably an iframe of an iframe (for tactical positioning reasons, to put the button or link directly under the mouse). The final iframe does point to the link with the nonce in the separate domain where the submission confirmation page lives. Since the iframe does frame the submission confirmation page it doesn’t have any visibility into the page (or need any in most cases, actually) since it can place the bad link directly under the person’s mouse.

    3) No, XSS worm propagation is not an issue, but usability is. If you don’t have a use case for people who don’t have JS, they will be required to turn it on, and then worm propagation becomes an issue again. ;)

    Does all that make sense? This is pretty complicated, so please let me know if it doesn’t and I’ll try to explain further what I mean. Thanks for writing!

  6. Gregory Fleischer Says:

    @RSnake - thanks for the answers.

    1) I thought that was what you meant. I think the wording in the paper may be a bit awkward since it isn’t clear in which domain the nonce is being omitted.

    2) I see how you arrived at this point.

    3) Yes, so we assume that user either has JavaScript enabled or not. They shouldn’t need to switch back and forth.

    So, let me see if I am understanding how this all ties together:

    - The website is a social network site where users must log in to post content.

    - The site has potential XSS vulnerabilities on every page.

    - There are two types of users that utilize the site: those with JavaScript enabled and those with JavaScript disabled. The users don’t toggle JavaScript on and off as they use the site. Going from on to off, the site will not function; going from off to on, the user may be vulnerable to XSS attacks.

    - When a user first logs into, the JavaScript status is detected (e.g., onsubmit form handler sets hidden form variable). The JavaScript status is associated with the user session.

    - A separate domain is used to prompt users for confirmation of submitted content.

    - The website is guaranteed to be free of XSS holes.

    - Any content submitted on is posted directly to a confirmation page on

    - There is not a nonce used on, because an XMLHttpRequest could read it if it was present and replay it.

    - Confirmation of content on is only allowed via the POST method.

    - A nonce is used on POSTs from to prevent blind CSRF attacks.

    - If the confirmation page detects that it has been framed, it should attempt to unframe itself. If this fails, submission of the form should not be allowed. If JavaScript is either not enabled or if on IE the “security=restricted” was set on the frame, this check will never be applied so additional logic compensates for it.

    - If user did not have JavaScript enabled when the user session was established, the form is constructed so that no JavaScript is required to submit it. If JavaScript is enabled, the form should not be submitted; this protects against the situation where the user started with JavaScript off and then turned it on, thus making himself vulnerable to attacks.

    - If the user had JavaScript enabled when the session was established, the confirm page should be constructed so that it only allows for submission when JavaScript is enabled (e.g., set method and action in onsubmit handler). This protects against the IE situation where “security=restricted” has been set on an frame. If JavaScript is no longer enabled, submission will fail.

    The big caveat to all of this would be that the login process needs to be protected in a similar manner (e.g., use separate domain, etc.).

  7. RSnake Says:

    That’s almost exactly the way I’d do it. The only exception is that I’d probably not have some sort of cookie set, but rather just do all the detection on the secondary domain submission page. If they don’t have JS installed, no biggie - just send them through the login flow to get their stuff submitted. That way if they turn off or on their JS just before submission you don’t have to have any additional logic to deal with it.

  8. sirdarckcat Says:

    to be sincere.. I cant believe that payload won :-|
    Any way, awesome contest, there should be a lot of this type..

    But I really want to say, that all the stuff we presented, wouldn’t be possible without the help of everyone..

    I mean, without the improvements everyone gave, the payloads wouldn’t be so small.. just to name a few I remember..
    Ronald, ma1, .mario, gareth, shawn, ritz, spyware, bwblabs, babariansomething, and I’m sure there where more, but my memory fails.

    I mean the whole contest was..
    john doe posts code of 200 bytes
    jake doe improves it 1 byte
    mike doe improves it 2 bytes
    jane doe posts another approach of 195 bytes
    john doe improves it 5 bytes
    mike doe improves it another 2 bytes

    so.. I think everyone won this.. I’ll share the prize with all of you (oops theres no prize :() congrats :)

  9. dreamwind Says:

    I’ve missed the competition and a large part of discussion but… I have some ideas: the final code can be reduced (!) if we move out quotes around “content” in input and one whitespace between src and onerror. 3 bytes. It doesn’t change the code fundamentally but reduces it.

  10. DoctorDan Says:

    The paper on worm analytics you speak of can be found here:

    If anyone wants to host it, please let me know!

  11. Ronald van den Heetkamp Says:


    No, that doesn’t work with the rules in mind. The quotes are added by Firefox and so it does grow which was against the rules. Otherwise we probably did that already in the light of some fierce competition! I still got some bitemarks ;)