I'm working on a CTF where to obtain the flag I need to trigger the admin user of a Flask app to reveal it. The way this has to be done is through a CSRF + XSS chain attack, as the validation script first login on the app, then navigates to my evil server that triggers the CSRF.
The attack chain is required because of a session cookie set as httponly
I'm able to trigger that CSRF by performing a redirect to an unprotected endpoint of the app, the same where an unchecked GET parameter is vulnerable to a reflected XSS as the value is rendered inside HTML.
This is my XSS payload where I redirect the user after CSRF:
http://localhost:80/vulnerable?message=<script>fetch('http://localhost:80/flag',{method:'POST',credentials:'include'}).then(alert('succes'));</script>
I'm not able to interact with the vulnerable Flask app, I can only see its log.
My issue is that if login (unprivileged account) in the app, then I point my browser to http://my_evil_server:5000 (this is what the validation script visits) navigation is redirected to http://localhost:80/vulnerable, the XSS executed and I could see a POST request to http://localhost:80/flag returning HTTP 302.
On the other side when the same thing is done though the challenge script (automated navigation with Selenium) I see that the CSRF succeed but the fetch() call inside the XSS payload triggers an HTTP 400 Bad Request
What could be the problem in what I'm triyng to do?