What's in a tag name? JavaScript, apparently
10 points by freddyb
10 points by freddyb
I feel like I need a bit more context for why any of this is useful. Is the idea that you could get XSS from a site that creates an element with untrusted input as the tag name?
No, I think this is mostly fun and experimental. Even if you could get someone to create that element, it’s unlikely you could get the required attributes in.
Obscure filters and bad block listing seems like the more realistic scenario.
It's always weird and unlikely... until someone chains it with another weird thing for a full exploit ;)
No mention of what browser(s) this applies to?
Practically all of this stuff (parsing and DOM behaviour) is exhaustively defined in the HTML Standard and DOM Standard. There are still occasional bits and pieces where differences are observable, but they’re not at all common.
For example: what happens after the < of a tag is defined in https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state, and localName and tagName are defined in https://dom.spec.whatwg.org/#interface-element; and in each case you can follow the links all through the document to chase up all the loose ends of what they actually are and do.
I was genuinely disappointed to see “wondering what characters are allowed in a tag” followed by experimentation and even fuzzing rather than reference to the spec—I would have expected anyone from PortSwigger to know that HTML has a dependable spec, and that especially around parsing, all implementations match it exactly (barring new features, like how they just resurrected processing instructions). I know I reach to the HTML Standard quite frequently over subtle details; it’s typically faster and more reliable than experimenting.
The tag open state shows that the tag name has to start with ASCII alpha, and then the tag name state shows that anything goes other than ␉, ␊, ␌, ␠, /, > and ␀, with ASCII uppercase immediately lowercased. So <alert(1)> is considered legal syntax, no parse error or such (though a validator will probably still complain that there’s no such element).
Related fun stuff: at unspecified times and browsers in history (but long ago, and not consistent across browsers), <br/> would create an element with local name br/ (which was why <br /> became the XHTML/HTML-polyglot way of writing a line break, found in many CMSes; whereas XML would customarily skip the space), and <br /> would create an element with local name br and one attribute named / with value empty string (and I honestly think they should have left it that way rather than ignoring a trailing slash—now we’ve somehow ended up with a whole lot of developers that think the / does something or is in any way worthwhile).
Fascinating how the end result looks so simple and clearly minimal. I like how Gareth describes how he started, which avenues he explored and how he arrived at this contrived but tiny XSS vector. Just neat.