Stylish

Description

A new card generator platform just went live. Apparently everything seems to be good but is it really like this? Find your way in with style!

Source

package.json

{
	"name": "web_stylish",
	"version": "1.0.0",
	"description": "",
	"main": "index.js",
	"scripts": { "start": "node index.js" },
	"keywords": [],
	"authors": [ "Nauten" ],
	"license": "ISC",
	"dependencies": {
		"express": "^4.17.1",
		"nunjucks": "^3.2.0",
		"puppeteer": "^10.4.0",
		"sqlite-async": "1.1.2"
	},
	"devDependencies": { "nodemon": "^2.0.15" }
}

database.js

routes/index.js

Solution

Stylish.png

When we create new CSS code and submit router.post('/api/submission/submit', ... endpoint is hit.

The submission creates the file and tells the bot to visit the card style. insertSubmission is a prepared query and is returning last inserted item ID, meaning no access to the filename of submission.

visitURL launches fresh incognito browser for each request, this rules out Cookie Stealer XSS possibility.

The bot only views the website and makes no additional requests.

getSubmissionComments is vulnerable to SQLi because of raw query.

isAdmin function check if request are made from localhost.

Looks like we need to abuse the bot to do actions on our behalf via CSRF. To make this work we need to inject Javascript and make bot trigger said Javascript which later with our code will trigger chain of endpoints to finally retrieve flag.

The chain seems to be XSS -> CSRF -> SQLi (???). The flag is located in flag_{random_4_hex} table...

First it seems we need to leak the tokens which are used for approval and rejection.

When bot visits the css we created it visits challenge/views/card_unapproved.html template.

Our CSS is included into the page, but what can we do with it?

CSS Injectionarrow-up-right 👀

CSP: https://csp-evaluator.withgoogle.comarrow-up-right

Stylish-1.png

challenge/helpers/TokenHelper.js creates the tokens and all it really does is shuffle ASCII table and return only 32 characters.

Just like HackTricks said the request is made to our server if character exists: https://book.hacktricks.xyz/pentesting-web/xs-search/css-injection#text-node-exfiltration-i-ligaturesarrow-up-right

Stylish-2.png

Note: For debug isAdmin just returns 1

This doesn't help much, because we need to know where each character is located at to have a proper approval token. Oh btw, tokens have display: none and font face won't make request if items are not actually visible.

Actually we don't care about order, because the token is being sorted 💀 If we exfiltrate the "good characters" then we can sort them and that's the token!

HackTricks > CSS Injection > Text node exfiltration (II): leaking the charset with a default font (not requiring external assets)arrow-up-right

After playing around with the PoC I ended up with this script, it's creating almost identical PoC but for this challenge.

Open the server to catch requests:

And now we have acquired Approval Token: 1356789ABCEGKLPQTWXbcfhklnpruvwz, but for local

For remote I used ngrok as server.

Now let's approve the card, but it's better to approve "clean" card. (Exfiltrated request was 8, dummy is 9 and 10 is next request)

Now that request has been approved we can view the card and add comments.

Stylish-3.png

Our real target was SQLi and now that we are here we can exploit it.

https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/SQLite%20Injection.md#integerstring-based---extract-table-namearrow-up-right ** Bruteforce the flag:

Last updated