White Label CMS <= 1.5.2 - Stored XSS

ID WPEX-ID:59BB5CF2-67A0-494C-A202-4B1A9DB28F3B
Type wpexploit
Reporter James Hooker
Modified 2021-01-19T20:30:29


Due to a lack of CSRF protection, and lack of sanitation of user input, it is possible to trigger a Persistent XSS attack via a CSRF attack. This attack targets in particular the Import functionality, which is located in the 'wlcmsImport' function, within the file '/white-label-cms/wlcms-plugin.php'. The path to execution is in the addition of the hook to the 'admin_menu' action, to the 'wlcms_add_admin' function. The 'wlcms_add_admin' function allows triggering of the 'wlcmsImport' function simply by providing an action parameter, with the value of ‘import’. Due to the lack of CSRF, it is possible – if an administrative user can be tempted to visit a malicious site – to inject HTML which will be displayed to all users, depending on the template in use, in the form of a custom IMG element. Providing an invalid URL to this element, and utilizing the 'onerror' event, custom JS can be triggered, which can result in Privilege Escalation. The default WordPress template will trigger the XSS on all pages of the site, as will the default WordPress Administrative theme. This is made possible thanks to the ability to import wlcms options via the import functionality, overwriting current options.

                                            The below snippet of Javascript, when executed by an administrative user of the target site (in this case, http://localhost) who is logged in will result in a Persistent XSS attack being triggered, via the import functionality of the White Label CMS plugin. The result, is an alert with the value of ‘1’ being displayed to all users of the site, depending on the template in use (default WordPress template will result in XSS being triggered on all pages). Note, that the ‘wlcms_o_adminbar_custom_logo’ is not the only option susceptible to a Persistent XSS attack, but is the only one used in this PoC.

Note: This PoC only appears to work in Firefox, however it should be possible to apply the same logic to a PoC in Chrome, and other browsers that support navigator

navigator.sendBeacon(q='http://localhost/wp-admin/options-general.php?page=wlcms-plugin.php&action=import',_=new FormData,_.append('wlcms_import',new Blob(['a:1:{s:28:"wlcms_o_adminbar_custom_logo";s:21:"\\" onerror=\\"alert(1)";}'])));