HexBrain

Browse / CVEs / CVE-2021-27877

CVE-2021-27877· veritas / backup exec

Veritas Backup Exec - Broken Authentication

Exploited in the wild. Listed by CISA on 2023-04-07; known to be used by ransomware.

highseverity
8.2CVSS score
64.9%likelihood of exploitation, next 30 days
99%of all CVEs are less likely
Readycheck to confirm it

An issue was discovered in Veritas Backup Exec before 21.2. It supports multiple authentication schemes- SHA authentication is one of these. This authentication scheme is no longer used in current versions of the product, but hadn't yet been disabled. An attacker could remotely exploit this scheme to gain unauthorized access to an Agent and execute privileged commands.

Impact

Unauthenticated attackers can exploit the deprecated SHA authentication scheme to bypass authentication and gain unauthorized access to Backup Exec Agents, potentially executing privileged commands and compromising backup systems.

Fix

Upgrade to Veritas Backup Exec version 21.2 or later that disables the insecure SHA authentication scheme.

How to confirm it

Positive when: success == true and compare_versions(version, '< 9.3')

Run it with nuclei: nuclei -id CVE-2021-27877 -u <target>

The full check
id: CVE-2021-27877

info:
  name: Veritas Backup Exec - Broken Authentication
  author: pussycat0x,DhiyaneshDK
  severity: high
  description: |
    An issue was discovered in Veritas Backup Exec before 21.2. It supports multiple authentication schemes- SHA authentication is one of these. This authentication scheme is no longer used in current versions of the product, but hadn't yet been disabled. An attacker could remotely exploit this scheme to gain unauthorized access to an Agent and execute privileged commands.
  impact: |
    Unauthenticated attackers can exploit the deprecated SHA authentication scheme to bypass authentication and gain unauthorized access to Backup Exec Agents, potentially executing privileged commands and compromising backup systems.
  remediation: |
    Upgrade to Veritas Backup Exec version 21.2 or later that disables the insecure SHA authentication scheme.
  reference:
    - https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/multi/veritas/beagent_sha_auth_rce.rb
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N
    cvss-score: 8.2
    cve-id: CVE-2021-27877
    epss-score: 0.6491
    epss-percentile: 0.99253
    cpe: cpe:2.3:a:veritas:backup_exec:*:*:*:*:*:*:*:*
  metadata:
    verified: true
    vendor: veritas
    product: backup_exec
    shodan-query: product:"Veritas Backup Exec"
  tags: cve,cve2021,network,js,tcp,passive,kev,vkev,vuln

javascript:
  - pre-condition: |
      isPortOpen(Host,Port);

    code: |
      let packet = bytes.NewBuffer();
      const c = require("nuclei/net");
      const cmd = "80000018000000010000000000000000000001080000000000000000"
      packet.WriteString(cmd)
      let conn = c.Open('tcp', `${Host}:${Port}`);
      conn.SendHex(packet);
      const result = conn.RecvFullString();

      // Function to extract ASCII strings from various formats
      function extractAsciiStrings(data) {
        let asciiStrings = [];
        let currentString = '';

        if (data.includes('\\x')) {
          // Split by \x and process each part
          const parts = data.split('\\x');

          for (let i = 1; i < parts.length; i++) { // Skip first empty part
            const part = parts[i];

            if (part.length === 0) continue;

            // Handle single character
            if (part.length === 1) {
              const charCode = part.charCodeAt(0);
              if (charCode >= 32 && charCode <= 126) { // Printable ASCII
                currentString += part;
              } else {
                // End current string if we hit non-printable
                if (currentString.length > 0) {
                  asciiStrings.push(currentString);
                  currentString = '';
                }
              }
            } else if (part.length === 2) {
              // Try to parse as hex
              const hexValue = parseInt(part, 16);
              if (!isNaN(hexValue) && hexValue >= 32 && hexValue <= 126) {
                currentString += String.fromCharCode(hexValue);
              } else {
                // End current string if we hit non-printable
                if (currentString.length > 0) {
                  asciiStrings.push(currentString);
                  currentString = '';
                }
              }
            } else {
              // Multiple characters - process each
              for (let j = 0; j < part.length; j++) {
                const charCode = part.charCodeAt(j);
                if (charCode >= 32 && charCode <= 126) {
                  currentString += part[j];
                } else {
                  // End current string if we hit non-printable
                  if (currentString.length > 0) {
                    asciiStrings.push(currentString);
                    currentString = '';
                  }
                }
              }
            }
          }
        } else {
          // If not \x format, process as raw string
          for (let i = 0; i < data.length; i++) {
            const charCode = data.charCodeAt(i);
            if (charCode >= 32 && charCode <= 126) { // Printable ASCII
              currentString += data[i];
            } else {
              // End current string if we hit non-printable
              if (currentString.length > 0) {
                asciiStrings.push(currentString);
                currentString = '';
              }
            }
          }
        }

        // Add final string if exists
        if (currentString.length > 0) {
          asciiStrings.push(currentString);
        }

        // Filter out empty strings and return non-empty ones
        return asciiStrings.filter(s => s.length > 0);
      }

      const asciiStrings = extractAsciiStrings(result);
      const cleanResult = asciiStrings.join(' ');

      Export(ToString(cleanResult));

    args:
      Host: "{{Host}}"
      Port: 10000

    matchers:
      - type: dsl
        dsl:
          - "success == true"
          - "compare_versions(version, '< 9.3')"
        condition: and

    extractors:
      - type: regex
        part: response
        group: 1
        name: version
        regex:
          - 'Remote Agent for NT ([0-9.]+)'

References

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