Когда вы создаёте элемент с id, браузер автоматически создаёт глобальную переменную с таким именем:
<a id="foo"></a>
Теперь
window.foo указывает на этот элемент.Но если вы создаёте несколько элементов с одинаковым id:
<a id="foo"></a>
<a id="foo"></a>
Теперь
window.foo становится HTMLCollection, а не отдельным элементом.Если вы добавите атрибут name:
<a id="foo" name="bar" href="..."></a>
Тогда
window.foo.bar будет указывать на этот элемент(работает в браузерах Chromium/WebKit, но не в Firefox).
Теперь представьте распространённый JS-паттерн:
var someObject = window.someObject || {};Он должен подставить объект по умолчанию, если
window.someObject не существует.Но если
window.someObject был подменён через HTML, то вместо объекта будет DOM-элемент и скрипт это молча примет.Теперь рассмотрим JS-логику:
let imgSrc = someObject.avatar;
Если атакующий подменит
someObject.avatar таким образом:<a id="someObject"></a>
<a id="someObject" name="avatar" href='cid:"onerror=alert(1)//'></a>
И если этот HTML вставлен, например, через innerHTML, то может получиться:
<img src="cid:" onerror="alert(1)//">
И это вызовет XSS 🏆
Вот краткий разбор этой уязвимости и лабораторной работы от WebSecAcademy
@WebDev_Plus