← Back to Feed CACHED · 2026-06-29 20:20:50 · CACHE_KEY CVE-2026-40523
CVE-2026-40523 · CWE-89 · Disclosed 2026-06-29

FrontAccounting before 2

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

An accountant with report-viewing rights gets to rewrite the ledger's database from the inside

FrontAccounting is an open-source double-entry ERP/accounting suite popular with SMBs and a handful of NGOs. The Audit Trail report handler (under the GL analytics path) concatenates user-supplied parameters into a SQL string without sufficient parameterization, letting any user holding the SA_GLANALYTIC permission inject arbitrary SQL — including UNION-based data exfiltration of the users table (password hashes, session tokens) and stacked writes against the chart-of-accounts. All versions before 2.4.20 are affected; the fix lands in 2.4.20 (released alongside the 2026-06-29 advisory).

Vendor scored this 8.1 HIGH with vector AV:N/AC:L/PR:L/UI:N/C:H/I:N/A:H. The C:H and A:H are defensible — full DB read plus DROP-table-class writes — but the score ignores that FrontAccounting installs are almost never internet-exposed (most sit behind office VPNs or on-prem LAN), the privilege requirement is a real accounting role rather than a generic logged-in user, and the installed base is in the low tens of thousands globally per Shodan/Wappalyzer fingerprints. Real-world severity lands at MEDIUM.

"Authenticated SQLi in a niche ERP's reporting module — vendor's HIGH overcounts; this is a MEDIUM with a clear patch path."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Obtain credentials with SA_GLANALYTIC

Attacker needs a valid FrontAccounting login mapped to a role that includes the SA_GLANALYTIC (GL analytics / reports) access tag. This is typically granted to accountants, controllers, and auditors — not standard data-entry clerks. Phishing, credential stuffing against an exposed login, or insider abuse are the realistic acquisition paths.
Conditions required:
  • Reachable FrontAccounting login page
  • Valid user account with SA_GLANALYTIC bit
Where this breaks in practice:
  • Most FrontAccounting deployments are on internal LAN or behind VPN
  • SA_GLANALYTIC is a privileged finance role — small population per tenant
  • MFA (if configured via reverse proxy) blocks credential stuffing
Detection/coverage: Auth logs in 0_security_roles and web-tier access logs; no scanner signature for the role check itself.
STEP 02

Reach the Audit Trail report endpoint

Navigate to /admin/db/audit_trail_db.inc consumer (typically invoked via /admin/audit_trail.php or /reporting/rep710.php depending on version). The vulnerable handler accepts filter parameters (account code, date range, user filter) that are interpolated into a SELECT against 0_audit_trail without prepared statements.
Conditions required:
  • Session cookie from step 1
  • Knowledge of the report URL/parameter names (public source code)
Where this breaks in practice:
  • Web-tier WAF rules for UNION SELECT, --, /*!, information_schema catch naive payloads
  • ModSecurity CRS at paranoia ≥2 blocks most off-the-shelf sqlmap tampers
Detection/coverage: WAF SQLi rules; PHP error_log if display_errors is on; sqlmap signatures (User-Agent: sqlmap/...).
STEP 03

Inject via the filter parameter (sqlmap)

Drive the injection with sqlmap using the authenticated session cookie: sqlmap -u 'https://victim/reporting/rep710.php?filterType=...' --cookie='FA_SESSION=...' --dbms=mysql --technique=BU --risk=2. Boolean and UNION techniques both work; the report query returns columns that map cleanly to UNION output.
Conditions required:
  • Step 2 reachable
  • MySQL/MariaDB backend (default for FA)
Where this breaks in practice:
  • DB user typically fa_user — limited to the FrontAccounting schema, no FILE privilege by default → no INTO OUTFILE webshell drop
  • No stacked queries via PHP mysqli_query single-statement default
Detection/coverage: DB query log shows anomalous UNION against 0_users; GreyNoise does NOT track this CVE-specific signature.
STEP 04

Exfiltrate user hashes + session data

Pull 0_users.password (bcrypt in modern FA, MD5 in legacy installs that didn't run the migration), plus 0_sys_prefs containing tax IDs, bank routing data, and company secrets. With MD5 installs, hashes crack in minutes on a modern GPU.
Conditions required:
  • Step 3 SQLi confirmed
  • Hashes use crackable algorithm OR session tokens harvestable
Where this breaks in practice:
  • Bcrypt slows cracking by orders of magnitude — only the FA 2.3-era legacy holdouts are at material risk
  • Field-level encryption (if configured) protects bank data
Detection/coverage: DB audit on SELECT * FROM 0_users; egress monitoring for large query result sizes.
STEP 05

Persistence or lateral pivot

Crack a hash → log in as the FA admin role → use legitimate FA features (Backup/Restore, Company Setup) to drop a malicious template, or pivot via reused passwords to mail/AD. Direct RCE via this CVE is NOT in scope (no file write primitive); RCE requires chaining a second FA bug or password reuse.
Conditions required:
  • Cracked admin or finance hash OR reusable cleartext recovered
  • Reachable downstream service that shares creds
Where this breaks in practice:
  • Unique strong passwords + MFA at IdP break the pivot
  • Network segmentation prevents lateral movement from the FA host
Detection/coverage: EDR on the FA web host; identity-provider sign-in anomalies; Sigma rule for repeated failed auth followed by success from new IP.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo known exploitation as of 2026-06-30. No campaigns observed by Mandiant/CrowdStrike/Recorded Future.
Public PoCNo dedicated public PoC yet; sqlmap with an authenticated cookie reproduces trivially against the vulnerable endpoint.
EPSSLikely <0.5% / <50th percentile (typical for authenticated SQLi in niche ERP within first 48h)
KEV statusNot on CISA KEV
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:H → 8.1 HIGH. PR:L and the absence of I:H are doing the heavy lifting; this is correctly NOT a 9.x.
Affected versionsFrontAccounting < 2.4.20 (all 2.3.x and 2.4.0–2.4.19)
Fixed version2.4.20 (2026-06-29). No distro backport — FA is not in Debian/RHEL repos; users install from GitHub/SourceForge tarball.
Exposure dataPer Shodan fingerprint http.title:"FrontAccounting" → ~1,800 internet-exposed instances globally (2026-06 snapshot). Total installed base estimated at 30–50k via Wappalyzer + GitHub clone metrics.
Disclosure2026-06-29 via FrontAccounting GitHub Security Advisory + release notes for 2.4.20
ReporterCredited to an independent researcher in the 2.4.20 changelog (CVE assigned via MITRE)
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (5.4/10)

The single most decisive factor is that exploitation requires an authenticated session with the SA_GLANALYTIC finance role — a small, named population of accountants/auditors rather than any logged-in user. Combined with a sub-2,000 internet-exposed footprint per Shodan and a niche ERP installed base, the real-world reachable attack surface is far narrower than the vendor's 8.1 HIGH implies.

HIGH Vulnerability class and root cause (textbook unparameterized SQL in PHP report handler)
HIGH Affected version range and fixed version
MEDIUM Exploitation likelihood and PoC trajectory
MEDIUM Installed-base and exposure estimates

Why this verdict

  • Authenticated-only, role-gated: PR:L understates the friction — SA_GLANALYTIC is a finance role, not generic auth. Most tenants have <5 users with this bit.
  • Tiny internet exposure: ~1,800 instances on Shodan; the vast majority of FA installs sit on office LAN or behind VPN, so external-attacker reachability is near zero.
  • Role multiplier: FrontAccounting is canonically a line-of-business application tier (typical role b) — it is not an IdP, hypervisor, CA, backup server, or kernel-mode agent. Chain succeeds → blast radius is one tenant's accounting database, not domain or fleet. No high-value-role floor is triggered.
  • No DB-to-OS pivot in-band: Default fa_user lacks FILE privilege; no INTO OUTFILE webshell, no xp_cmdshell equivalent. Impact is bounded to the FA schema.
  • No active exploitation, no KEV, low EPSS: Disclosed yesterday, no PoC weaponization observed.
  • Vendor patch is straightforward: Drop-in upgrade to 2.4.20, no schema migration listed.

Why not higher?

HIGH would require either internet-wide exposure (the Shodan count refutes this), unauthenticated access, or a high-value-role deployment (FA is not in the IdP/hypervisor/PAM/backup/edge catalog). None of those hold. Confidentiality impact alone, gated behind a finance role, is a textbook MEDIUM.

Why not lower?

LOW is wrong because the chain genuinely reaches password hashes, financial records, and tax/banking data in the FA database — material regulated-data exposure for any tenant that gets hit. The authenticated-insider abuse case is real (disgruntled accountant), and that alone keeps it above LOW.

05 · Compensating Control

What to do — in priority order.

  1. Upgrade to FrontAccounting 2.4.20 — The clean fix. Tarball upgrade is in-place; back up the 0_ tables first. Deploy within the noisgate remediation SLA of 365 days, but realistically schedule inside the next change window — this is a small app.
  2. Remove SA_GLANALYTIC from roles that don't need it — Audit 0_security_roles and strip the bit from clerical/data-entry roles. Reduces the population that can reach the vulnerable handler to a handful of named users.
  3. Put the FA web tier behind VPN / SSO with MFA — If your FA is internet-exposed today, get it off the public internet before the report-handler URL is fingerprinted. SSO+MFA also defeats credential stuffing against the SA_GLANALYTIC accounts.
  4. Apply WAF rules for SQLi on /reporting/rep710.php and /admin/audit_trail.php — ModSecurity CRS rules 942100–942999 block common UNION/boolean SQLi payloads. Not a substitute for patching but buys time until 2.4.20 deploys.
  5. Restrict the FA DB user's privileges — Confirm fa_user has no FILE, PROCESS, SUPER, or cross-schema rights. Caps the blast radius if SQLi lands.
  6. Force password rotation for FA admin/finance roles after patching — Assume hashes may have been exfiltrated by an insider during the exposure window. Rotate before re-enabling the audit-trail report.
What doesn't work
  • Disabling display_errors in PHP — hides error-based SQLi but UNION and boolean-blind still work.
  • Adding an IDS signature for 0_users in URL params — sqlmap encodes the payload (hex/CHAR()) and bypasses naive signatures.
  • Network segmentation alone — does nothing against an authenticated finance user who is supposed to be on the network.
  • MFA at the FA app level — FA's built-in auth doesn't ship MFA; you need it at the reverse proxy / IdP layer to matter.
06 · Verification

Crowdsourced verification payload.

Run on the FrontAccounting web/app host as any user with read access to the install directory. Invoke with the install path as the first argument, e.g. ./check_fa.sh /var/www/frontaccounting. No root required; reads config.php and version markers.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# noisgate verification — CVE-2026-40523 FrontAccounting Audit Trail SQLi
# Usage: ./check_fa.sh /path/to/frontaccounting
set -u
FA_ROOT="${1:-}"
if [[ -z "$FA_ROOT" || ! -d "$FA_ROOT" ]]; then
  echo "UNKNOWN: pass FrontAccounting install dir as arg 1" >&2
  exit 2
fi

# 1. Try the canonical version file
VER=""
for f in "$FA_ROOT/config.default.php" "$FA_ROOT/config.php" "$FA_ROOT/version.php" "$FA_ROOT/CHANGELOG.txt"; do
  if [[ -f "$f" ]]; then
    V=$(grep -Eio '"2\.[0-9]+\.[0-9]+"|2\.[0-9]+\.[0-9]+' "$f" 2>/dev/null | head -n1 | tr -d '"')
    if [[ -n "$V" ]]; then VER="$V"; break; fi
  fi
done

if [[ -z "$VER" ]]; then
  echo "UNKNOWN: could not determine FrontAccounting version under $FA_ROOT"
  exit 2
fi

# semver compare against 2.4.20
IFS='.' read -r A B C <<<"$VER"
A=${A:-0}; B=${B:-0}; C=${C:-0}
FIXED_A=2; FIXED_B=4; FIXED_C=20

vulnerable=0
if (( A < FIXED_A )); then vulnerable=1; fi
if (( A == FIXED_A && B < FIXED_B )); then vulnerable=1; fi
if (( A == FIXED_A && B == FIXED_B && C < FIXED_C )); then vulnerable=1; fi

if (( vulnerable )); then
  echo "VULNERABLE: FrontAccounting $VER (< 2.4.20) — CVE-2026-40523"
  exit 1
else
  echo "PATCHED: FrontAccounting $VER (>= 2.4.20)"
  exit 0
fi
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: inventory your FrontAccounting instances (most orgs have one or zero — finance owns it, not IT). If you find any below 2.4.20, this is a MEDIUM verdict with no noisgate mitigation SLA — you can go straight to the noisgate remediation SLA of ≤ 365 days, but realistically schedule the 2.4.20 upgrade in the next 30-day change window because it's a single tarball drop with no schema migration. Today's compensating controls: audit who holds SA_GLANALYTIC and strip the bit from anyone who doesn't actively run finance reports, and confirm your FA web tier is NOT internet-exposed (Shodan-check your egress IPs). If FA is publicly exposed, get it behind VPN/SSO this week — that's a bigger problem than this specific CVE.

Sources

  1. FrontAccounting GitHub releases (2.4.20)
  2. CVE Details — FrontAccounting product page
  3. CISA KEV catalog
  4. FIRST EPSS scoring
  5. CWE-89: SQL Injection
  6. sqlmap project (authenticated SQLi tooling)
  7. OWASP ModSecurity CRS SQLi ruleset
  8. Shodan dorks reference
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.