| Title | Scada-LTS 2.8.0 Improper Authorization |
|---|
| Description | Insecure direct object reference (broken object-level authorization) in the AmCharts data API of Scada-LTS 2.8.0 (commit f2a519bf).
GET /Scada-LTS/api/amcharts/by-id (and /by-xid) is protected only by the Spring Security expression @guard.hasDataPointReadPermission(request, false, 'ids'). The guard resolves the ids parameter with HttpServletRequest.getParameter(), which returns only the FIRST value of a multi-valued parameter, while the controller binds @RequestParam Set<Integer> ids, that is, all of them. Any authenticated user, including a low-privileged ROLE_USER, can therefore place a data point they are allowed to read, or a non-existent id, first in the request, and the controller then returns the value history of every other data point id in the same request, bypassing the per-object read permission.
Affected code:
WebContent/WEB-INF/spring-security.xml:411
<intercept-url pattern="/api/amcharts/by-id" access="@guard.hasDataPointReadPermission(request,false,'ids')" method="GET" />
GetIdentifierFromHttpParameterGuard.java:213 hasDataPointReadPermission(request, isXid, "ids")
-> :290 return HttpParameterUtils.getValueOnlyRequest(idName, request, identifier -> doHasPermission(...)).orElse(false);
HttpParameterUtils.java:40 getValueOnlyRequest(...) <-- the sink
41 String parameter = request.getParameter(key); // only the FIRST value of ids is read
42 if (parameter != null)
43 return Optional.ofNullable(parse(parser, parameter));
HasPermissionOperations.java:48 hasDataPointReadPermission(user, <that first id>)
-> private hasPermission(...):
200 if (object == null) { ...; return true; } // fail-open when the id does not resolve
(193 an EmptyResultDataAccessException for an unknown id is likewise treated as "return true")
AmChartValuesAPI.java:113 @GetMapping("/by-id")
114 getValuesFromTimeRangeById(@RequestParam Set<Integer> ids, ...) // binds ALL ids
146 getPointValuesFromRangeById(...) ->
147 List<DataPointVO> dataPoints = dpService.getDataPoints(pointIds); // no per-object permission filter
The guard inspects only ids[0]; the controller returns values for every id in the set. A first value the user may legitimately read, or a non-existent one via the fail-open path above, passes the guard, and the response then includes any other point's data.
Impact: a low-privileged authenticated user can read the recorded value history of any data point in the system, that is, arbitrary process and sensor telemetry, regardless of the per-object read permissions an administrator has configured. The issue is read-only and affects confidentiality.
Reproduction. Authenticate as a low-privileged user with no read permission on the target data point (form login, POST /Scada-LTS/login.htm with username and password), then compare two requests that differ only in the ids parameter:
GET /Scada-LTS/api/amcharts/by-id?ids=1&startTs=0&endTs=9999999999999
-> HTTP 403 (denied, as expected)
GET /Scada-LTS/api/amcharts/by-id?ids=999999&ids=1&startTs=0&endTs=9999999999999
-> HTTP 200, response body contains the value history of data point 1
Same user, same target id. 999999 is simply an id that does not exist, which passes the guard through the fail-open branch; any data point the user is permitted to read works equally well as the first value.
A self-contained Docker lab (stock scadalts/scadalts:latest image plus MySQL) and a proof-of-concept script were supplied to the vendor and can be provided to the VulDB team on request. The proof-of-concept performs the two requests above and reports the 403 versus 200 result. It performs no privilege escalation and no code execution.
Affected versions: 2.8.0 verified. By code lineage the remainder of the 2.x line shipping the @guard layer and AmChartValuesAPI is expected to be affected. The code is unpatched on the current master and develop branches.
CWE-639 (authorization bypass through user-controlled key), also CWE-863 (incorrect authorization). Suggested CVSS v3.1 vector: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N (base 6.5). Confidentiality is rated high because the flaw bypasses the per-object read authorization model for every data point in the installation; integrity and availability are unaffected as the endpoint is read-only.
This is distinct from CVE-2023-33472 (Event Handlers code injection) and from the product's known XSS, CSRF and path traversal issues. No CVE is known to cover it.
Disclosure timeline: 2026-06-28 reported privately to the vendor at [email protected], with the Docker lab and proof-of-concept attached, per the project's security policy. No vendor response as at 2026-08-05. Researchers: Lian Aldrich and Jacob Simmons, Aphotic Security.
|
|---|
| User | LianAldrich (UID 43919) |
|---|
| Submission | 08/05/2026 12:46 (3 months ago) |
|---|
| Moderation | 10/23/2026 17:14 (3 months later) |
|---|
| Status | Accepted |
|---|
| VulDB entry | 425987 [Scada-LTS 2.8.0 AmCharts Data API AmChartValuesAPI.java HttpServletRequest.getParameter ids authorization] |
|---|
| Points | 17 |
|---|