messageevent listener. The following check is used to reject invalid event origins:
this.iframeSrc.indexOf(event.origin) < 0
this.iframeSrcbeing something like
https://foo.myshopify.com/preview_bar, this mostly does the job correctly. However,
event.origindoesn't end with a slash, meaning that for example
https://foo.myis a possible origin and would be accepted here. Sending an
exit_previewmessage allows the attacker to specify a URL to redirect to, supplying a
Recommendation: Changing the check into
this.iframeSrc.indexOf(event.origin + "/") != 0should reliably reject all invalid origins.
I demonstrate this attack against a random shop that is not under my control (roolee.com) to prove that no special knowledge is required. Steps to reproduce are:
- Download the attached
exploit_preview.htmlpage to the same directory on your computer.
%Windir%\Sysnative\drivers\etc\hostson Windows) and add the following entry:
127.0.0.1 roolee.co(note that this is
.com). The real attackers would register
roolee.codomain instead, it is for sale.
ssl_server.pyscript (requires Python 3) to run a local SSL-protected web server. On Linux and macOS this script needs to be run with administrator privileges.
https://roolee.co/exploit_preview.htmlin your browser and accept the invalid certificate (real attacker would actually own roolee.co, so they would be able to get a valid certificate for it).
Recommendation: The second attack scenario is avoidable, XSS issues in the store front shouldn't compromise the admin interface. The admin interface should be located under a different subdomain, e.g.
admin.foo.myshopify.com. This will make sure that code running in the shop front is forbidden from accessing it by the same-origin policy.
For the community, by the community