
Don’t trust the locals: investigating prevalence of persistent client-side XSS - godelmachine
https://blog.acolyer.org/2019/04/10/dont-trust-the-locals-investigating-the-prevalence-of-persistent-client-side-cross-site-scripting-in-the-wild/
======
strictnein
Discovered a cookie-persisted version of this at a large multi-national
(Global Fortune 100). It affected almost all of their SSO pages. They all had
multiple XSS issues, and then they read from a cookie and then wrote that
value to the page inside some Javascript(!), so I was able to persist the XSS
on the user's machine indefinitely (until they cleared their cookies).

The result was the ability to capture user credentials at any of their login
portals, and the "infection" mechanism would have just been the victim
clicking on a link to one of their login portals.

The company has a bug bounty that awards "schwag", which I knew going in. So
now I have two of the same really dumb t-shirts.

~~~
digitaltrees
You have two tee shirts and some random dude on hacker news eternal gratitude
— me.

~~~
strictnein
Thanks! :)

------
FiddlyPack
Highlights, to me:

\- do not trust localStorage

\- quote: The most challenging pattern in our dataset consists of scenarios in
which applications use the persistence mechanisms to deliberately store HTML
or JavaScript code, e.g., for client-side caching purposes. In this setting,
the attacker is able to completely overwrite the contents of the corresponding
storage entry with their own code. We could identify in several cases these
flaws are actually introduced by third-party libraries, among them CloudFlare
and Criteo.

~~~
joeyrideout
Isn't "do not trust localStorage" another variant of "do not trust the
client"?

Taking client-controlled storage and inserting it unsafely into the DOM sounds
like a bad idea, although it's not something that is popularly discussed as a
trust boundary so awareness is key (this article is a great example).

~~~
FiddlyPack
Exactly so. The use case of Local Storage is usually “application cache.” When
you’re building out features, it may not even be obvious that you’re injecting
application state _that originated in localStorage_ into the DOM. That’s why
this is such an easy problem to fall into.

------
megous
Use one XSS, like reflected URL parameter, to store the code to localStorage
for locally persisted XSS. Looks like fun.

------
brasetvik
XSS coupled with a vulnerable JSONP endpoint can also be chained to a
persistent client-side XSS via service workers.
[https://c0nradsc0rner.com/2016/06/17/xss-persistence-
using-j...](https://c0nradsc0rner.com/2016/06/17/xss-persistence-using-jsonp-
and-serviceworkers/)

------
pornel
The proposed solution, to use the ServiceWorker as a trusted cache, is OK when
you own the entire origin. Unfortunately, for 3rd parties this is not an
option. There can be only one global ServiceWorker per document/scope.
Clobbering the global one by a third party would be unwelcome by page owners,
and there's no standard for graceful cooperation here.

