Open aszx87410 opened 3 years ago
Hi could you explain how u arrived to the conclusion that 'reference' is the attribute to be overwritten for this prototype pollution to work?
@TheMythologist
From this line: https://github.com/popperjs/popper-core/blob/4800b37c5b4cabb711ac1d904664a70271487c4b/src/createPopper.js#L63
return function createPopper<TModifier: $Shape<Modifier<any, any>>>(
reference: Element | VirtualElement,
popper: HTMLElement,
options: $Shape<OptionsGeneric<TModifier>> = defaultOptions
): Instance {
let state: $Shape<State> = {
placement: 'bottom',
orderedModifiers: [],
options: { ...DEFAULT_OPTIONS, ...defaultOptions },
modifiersData: {},
elements: {
reference, // this line
popper,
},
attributes: {},
styles: {},
};
The first parameter we send in(which is button
) will be state.elements.referecne
, and in applyStyles:
function applyStyles({ state }: ModifierArguments<{||}>) {
Object.keys(state.elements).forEach((name) => {
const style = state.styles[name] || {};
const attributes = state.attributes[name] || {};
const element = state.elements[name];
Object.keys(state.elements).forEach((name) => {
, name will be "reference"
And for this line: const attributes = state.attributes[name] || {};
, because we polluted Object.prototype.reference
, so state.attributes["reference"]
will be the object we gave, which is { onfocus: "..." }
Small Talk
Description
Take a little break in your journey, read some of our extravagant knowledgement to become your best version... ...and, of course, share your sentences with us.
Source code:
quote.html
Writeup
First, shvl is so suspicious so I went to it's GitHub page and found that there is a prototype pollution we can leverage: https://github.com/robinvdvleuten/shvl/pull/35
There is no
X-Frame-Options
header so we can embed index page and postMessage to it, but we need to be faster than quote.html because index page only accept first message event.So I think the goal is to win the race and pollute some attributes to abuse Popper. But how do we do this? Let's check the source code!
When creating new Popper instance, it merges default modifiers and the modifiers user set:
https://github.com/popperjs/popper-core/blob/4800b37c5b4cabb711ac1d904664a70271487c4b/src/createPopper.js#L97
And in
mergeByName
, it checks if property exists first:https://github.com/popperjs/popper-core/blob/4800b37c5b4cabb711ac1d904664a70271487c4b/src/utils/mergeByName.js#L4
So we can pollute here to override the default modifier if we need. Fortunately, we don't. Because there is a default modifier called
applyStyles
which adds styles and attributes to the element: https://github.com/popperjs/popper-core/blob/4800b37c5b4cabb711ac1d904664a70271487c4b/src/modifiers/applyStyles.js#L31So we can set
onfocus
to the element and use hashtag to trigger the focus event.The last thing is, how to be faster than quote.html to send message before it? The answer is, just keep sending it! I use
requestAnimationFrame
to send the message recursively until it reaches a limit(40 times in this case).Final exploit, not perfect but works: