Summary
The FacturaScripts ListCuenta restore-special action overwrites the special-accounts mapping (cuentasesp) that drives accounting-entry generation, with no authorization re-check inside the handler and no anti-CSRF token. It is exploitable two ways: (a) broken access control — any non-admin with ListCuenta page access can invoke it directly; and (b) CSRF against an admin via top-level GET navigation.
Root Cause
restoreSpecialAccountsAction (ListCuenta.php:149-157) is dispatched from execPreviousAction with $action read via inputOrQuery (GET-reachable). It has NO validateFormToken and NO admin/permission re-check — the if ($this->user->admin) gate (:90) only wraps the UI-button rendering, not the handler. The sink CSVImport::updateTableSQL(CuentaEspecial::tableName()) → dataBase->exec() overwrites the cuentasesp table with packaged CSV defaults.
Impact
Corruption of the special-accounts mapping used to generate accounting entries (financial-integrity, I:H on that table). The broken-access-control path (non-admin accountant with menu='accounting' access) is deterministic and needs no victim interaction (PR:L/UI:N), scored as the primary vector.
Attack Chain
- Entry:
GET /ListCuenta?action=restore-special (GET-reachable via inputOrQuery). Guard: admin-only restore button (:90) + expected token. Bypass proof: the if ($this->user->admin) gate only wraps UI-button rendering; the handler itself has no validateFormToken and no admin/permission re-check.
- Sink:
CSVImport::updateTableSQL(CuentaEspecial) → dataBase->exec() overwrites cuentasesp.
- Impact: special-accounts mapping overwritten → corrupted accounting-entry generation.
Bypass Evidence
- Handler verified on v2026.4 to lack token + admin re-check; the admin check is only around button rendering.
$action GET-reachability via inputOrQuery verified.
Affected Versions
<= v2026.4.
Suggested Fix
Add validateFormToken() and an admin/permission re-check inside restoreSpecialAccountsAction.
Dedup
No published advisory covers this. Not a duplicate.
Reported by zx (Jace) — GitHub: @manus-use
Summary
The FacturaScripts
ListCuentarestore-specialaction overwrites the special-accounts mapping (cuentasesp) that drives accounting-entry generation, with no authorization re-check inside the handler and no anti-CSRF token. It is exploitable two ways: (a) broken access control — any non-admin with ListCuenta page access can invoke it directly; and (b) CSRF against an admin via top-level GET navigation.Root Cause
restoreSpecialAccountsAction(ListCuenta.php:149-157) is dispatched fromexecPreviousActionwith$actionread viainputOrQuery(GET-reachable). It has NOvalidateFormTokenand NO admin/permission re-check — theif ($this->user->admin)gate (:90) only wraps the UI-button rendering, not the handler. The sinkCSVImport::updateTableSQL(CuentaEspecial::tableName())→dataBase->exec()overwrites thecuentasesptable with packaged CSV defaults.Impact
Corruption of the special-accounts mapping used to generate accounting entries (financial-integrity, I:H on that table). The broken-access-control path (non-admin accountant with
menu='accounting'access) is deterministic and needs no victim interaction (PR:L/UI:N), scored as the primary vector.Attack Chain
GET /ListCuenta?action=restore-special(GET-reachable viainputOrQuery). Guard: admin-only restore button (:90) + expected token. Bypass proof: theif ($this->user->admin)gate only wraps UI-button rendering; the handler itself has novalidateFormTokenand no admin/permission re-check.CSVImport::updateTableSQL(CuentaEspecial)→dataBase->exec()overwritescuentasesp.Bypass Evidence
$actionGET-reachability viainputOrQueryverified.Affected Versions
<= v2026.4.Suggested Fix
Add
validateFormToken()and an admin/permission re-check insiderestoreSpecialAccountsAction.Dedup
No published advisory covers this. Not a duplicate.
Reported by zx (Jace) — GitHub: @manus-use