The Spanner logo
    • Home
    • Blog
      • Blog home
      • RSS
    • Login
    • Home
    • Blog
      • Blog home
      • RSS
    • Login
    The Spanner logo

    The Spanner
    Web security blog

    Made by Gareth Heyes
    Follow me on Twitter: @garethheyes

    Javascript for hackers!

    Hackvertor logo
    Shazzer logo
    My Github account
    Recent posts
    Introducing Feedworm: A Privacy-First RSS Reader That Lives in DevToolsSpeedy RSVP extensionAutoVaderHackvertor history and tag finderShadow Repeater v1.2.3 releaseBurp Hackvertor v2.1.24 releaseHacking roomsXSSing TypeErrors in SafarivalueOf: Another way to get thisMaking the Unexploitable Exploitable with X-Mixed-Replace on FirefoxThe curious case of the evt parameterCSS-Only Tic Tac Toe ChallengeRewriting relative urls with the base tag in SafariBypassing DOMPurify with mXSSNew IE mutation vectorHow I smashed MentalJSMentalJS DOM bypassAnother XSS auditor bypassXSS Auditor bypassBypassing the IE XSS filterUnbreakable filterMentalJS bypassesmXSSJava SerializationBypassing the XSS filter using function reassignmentRPOSandboxed jQueryX-Domain scroll detection on IE using focusEpic fail IEnew operatorDecoding complex non-alphanumeric JavaScriptHacking FirefoxDOM ClobberingBypassing XSS AuditorThe evolution of codeNon-Alpha PHP in 6-7 charsetTweetable PHP-Non AlphaMentalJS for PHPOpera x domain with video tutorialSandboxing and parsing jQuery in 100ms

    XSS is art

    By Gareth Heyes (@hackvertor)

    Published 17 years 7 months ago • Last updated March 22, 2025 • ⏱️ 3 min read

    ← Back to articles

    I had a bet with a friend of mine David Lindsey aka Thornmaker. Basically we said the first one to get a XSS vector on phpids buys a beer at Bluehat :) I haven't had much time to do this because I've been pretty busy but over the last few days in my spare time I've been slowly constructing a vector. David you owe me a beer :D

    What is interesting about phpids is that it includes a centrifuge detection system which compares past vectors and known good inputs which enables them to detect future attacks that slip past their regular expressions. The system has greatly improved since the early days and I actually had a ton of XSS vectors which got past their expressions but not centrifuge.

    So in my crazy world of XSS how can you bypass a protection like this? Well in Firefox there's a E4X statement which I posted previously that doesn't look like javascript syntax. e.g. :-

    <pre lang="javascript"> default xml namespace = statement </pre>

    Using this method I managed to construct my vector which used this to bypass centrifuge but I had a problem, how to first get a payload and how to call that payload. Why is that a problem? Because phpids checks common injections like eval, alert etc.

    I decided to try various different tricks using "this" which refers to the current window in javascript when executing from a script tag in Firefox. The methods I used worked well but the centrifuge detection was triggered when using "+" to concatenate strings.

    Simple calls to 'abc'.concat('def') were blocked quite easily so I needed another method. Using a && trick to bypass some of their regular expressions it was possible to call a global function by assigning it to a variable:-

    <pre lang="javascript"> default xml namespace=toolbar,b=1&&this.atob </pre>

    So the default xml namespace bypasses centrifuge and the variable b is assigned to the atob function in Firefox. This is because in javascript the right side of the statement is returned not 1 when using && in this context. I could get the string eval by converting base64 and convert the string to a function using the techniques described.

    All I needed now was the payload and that was obtained using the 1&& method but this time using window.name:-

    <pre lang="javascript"> default xml namespace=toolbar,y=1&&name </pre>

    I had all the raw ingredients now to finish my vector which produced the final vector that looks like a work of art to me :)

    <pre lang="javascript"> default xml namespace=toolbar,b=1&&this.atob default xml namespace=toolbar,e2=b('ZXZhbA') default xml namespace=toolbar,e=this[toolbar,e2] default xml namespace=toolbar,y=1&&name default xml namespace=toolbar default xml namespace=e(y) </pre>

    ← Back to articles