CVE-2021-23176
Executive Summary
CVE-2021-23176 is an improper access control vulnerability in the reporting engine of the l10n_fr_fec module shipped with Odoo Community and Odoo Enterprise versions 15.0 and earlier. An authenticated remote attacker can craft malicious RPC packets to bypass authorization checks and extract sensitive accounting information, including financial records that should be restricted. The vulnerability carries a CVSS score of 6.5 (Medium severity) and is highly relevant to organizations using Odoo's French localization module (l10n_fr_fec) for statutory financial reporting, as exploitation results in significant confidentiality loss without requiring elevated privileges beyond a standard user account.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The underlying flaw resides in the l10n_fr_fec module of Odoo, which implements the French Fichier des Écritures Comptables (FEC) — a statutory requirement for exporting accounting journal entries in a standardized format. The module exposes a reporting engine that generates these financial export files. Due to improper access control, the reporting engine fails to enforce proper authorization checks when processing RPC (Remote Procedure Call) requests.
Odoo's architecture relies heavily on its RPC framework, which allows clients (web frontend, desktop clients, or custom scripts) to invoke methods on server-side models. Each model method in Odoo typically includes access control through the check_access_rights and check_access_rule mechanisms, which verify both ir.model.access permissions (CRUD rights per model) and record rules (row-level restrictions). The vulnerability in the l10n_fr_fec reporting engine indicates that at least one method callable via RPC bypasses or inadequately applies these checks, allowing any authenticated user to invoke the FEC report generation and retrieve accounting data they are not authorized to view.
The attack surface is the Odoo XML-RPC and JSON-RPC endpoints, which are exposed on the standard Odoo web port (typically 8069 for HTTP or 443 behind a reverse proxy). The flaw is classifiable under CWE-284 (Improper Access Control) — a horizontal privilege escalation issue where a low-privileged authenticated user can access financial data reserved for accounting roles.
The exact vulnerable method names and RPC endpoint paths are not disclosed in the available data. However, the description states that exploitation occurs "via crafted RPC packets," meaning the attacker sends a direct RPC call to invoke the reporting engine's export function. The attacker would need to supply the correct database name (Odoo multi-tenant databases require a db parameter in RPC calls), valid credentials for any user account, and the method signature of the vulnerable FEC export function.
Notably, the flaw affects both Odoo Community and Odoo Enterprise editions, spanning all versions up to and including 15.0. The French FEC module is typically installed on Odoo instances used by French businesses or organizations operating in France, making the vulnerable population geographically concentrated but financially significant.
Exploitation Scenarios
Strictly based on the NVD description and provided data. No public PoC or exploit code is available; the attack chain below is inferred from the vulnerability class.
Step 1 — Reconnaissance and Target Identification
An attacker begins by identifying exposed Odoo instances. Odoo's web interface is distinctive and can be fingerprinted via HTTP headers (X-Odoo-Version), the /web/login page, or the presence of /web/database/manager. Shodan queries such as http.title:"Odoo" or product-based filters can quickly enumerate targets. Once a target is found, the attacker must confirm the presence of the French localization module (l10n_fr_fec). This may be confirmed by accessing specific FEC-related menu endpoints (e.g., /web#menu_id=... with FEC-specific menu labels) or by attempting to invoke the RPC method directly and observing error responses that reference the module name.
Step 2 — Triggering the Flaw
The attacker needs valid credentials for any user account on the Odoo instance — even a low-privileged portal user or sales user would suffice, given the improper access control nature of the flaw. With credentials in hand, the attacker crafts an RPC call using either:
- XML-RPC: POST request to
/xmlrpc/2/objectwith a payload specifying the database name, user ID, password, the target model (likely the FEC reporting model), the vulnerable method name, and parameters to trigger the FEC report export. - JSON-RPC: POST request to
/jsonrpcwith a similar structured call.
The crafted packet must precisely match the method signature expected by the reporting engine. Since exact method names are not disclosed in available intelligence, an attacker would need to reverse-engineer the l10n_fr_fec module (via the publicly available Odoo source code on GitHub) to identify the callable method and its required parameters.
Step 3 — Payload Execution and Data Extraction
The vulnerable method, when invoked with appropriate parameters (e.g., a fiscal year or date range), returns the FEC export — typically structured accounting data containing all journal entries for the specified period. Because access control checks are bypassed, the response includes the full financial records without triggering authorization errors. The attacker can then iterate over multiple fiscal periods or entities to extract a comprehensive dataset. The data is typically returned in a structured format (CSV, XML, or JSON), making automated exfiltration straightforward.
Step 4 — Post-Exploitation Impact
The extracted accounting data contains highly sensitive financial information:
- General ledger entries with full journal details
- Account numbers and descriptions
- Transaction amounts, dates, and reference numbers
- Supplier and customer financial details
- Potentially salary data, tax information, and inter-company transactions
This data can be used for corporate espionage, fraud planning, identity theft (if personal data of individuals is embedded in journal entry descriptions), or sold on dark web marketplaces. The attacker maintains their authenticated session, meaning the vulnerability can be re-triggered repeatedly to extract updated data as new accounting entries are posted.
Impact Assessment
CVSS Breakdown (derived from vector components):
- Attack Vector (AV:N): Network — remotely exploitable without physical access
- Attack Complexity (AC:L): Low — no unusual conditions required; standard RPC call suffices
- Privileges Required (PR:L): Low — requires only a standard authenticated account
- User Interaction (UI:N): None — no victim interaction needed
- Scope (S:U): Unchanged — impact is contained to the Odoo application
- Confidentiality (C:H): High — complete loss of accounting data confidentiality
- Integrity (I:N): None — no data modification possible
- Availability (A:N): None — no availability impact
Business Impact:
The confidentiality impact is rated High, which is appropriate given that accounting records are among the most sensitive datasets an organization possesses. The disclosure of FEC data could:
- Violate regulatory compliance — In France, FEC data is used for tax audits; a breach of this data may trigger mandatory breach notification under GDPR (since accounting data often includes personal data) and NIS directives.
- Damage competitive position — Financial details reveal margins, supplier pricing, customer contracts, and strategic investments.
- Enable secondary fraud — Knowledge of vendor payment patterns enables invoice fraud (business email compromise targeted at the organization's finance team).
- Expose insider information — For publicly traded companies, premature disclosure of financial performance could constitute a market abuse violation.
Affected Systems: All Odoo deployments — Community and Enterprise — up to version 15.0 with the l10n_fr_fec module installed. The module is standard in French localizations; organizations in France, Belgium, Switzerland, Luxembourg, and other francophone markets are primary targets. However, any Odoo instance with the module enabled — regardless of geographic location — is vulnerable.
Blast Radius: The vulnerability is limited to the Odoo application itself (Scope: Unchanged) and does not directly compromise the underlying host operating system or database server. However, the data exfiltration impact extends well beyond the application boundary, potentially affecting the entire organization's financial confidentiality posture.
Detection Guidance
Sigma Rule
title: Odoo l10n_fr_fec Reporting Engine - Unauthorized Access Attempt
id: 5e03b5f0-4f70-4b6c-9d6c-5a0c5574e0e1
status: experimental
description: Detects attempts to access the Odoo FEC reporting engine via RPC calls by low-privileged users, potentially exploiting CVE-2021-23176.
author: Valtersi Threat Intelligence
date: 2024/05/15
tags:
- attack.initial-access
- attack.t1190
- cve.2021-23176
logsource:
product: odoo
category: application
detection:
selection_rpc:
event.category: rpc
rpc.model|contains: "fec"
selection_lowpriv:
user.roles|contains: "portal"
selection_response:
response.status_code: 200
response.size|gte: 10000
condition: selection_rpc and selection_lowpriv and selection_response
falsepositives:
- Legitimate portal users accessing reporting features if business logic allows
- Administrators with misconfigured role assignments
level: high
YARA Rule
rule Detect_Odoo_FEC_RPC_Exploitation {
meta:
author = "Valtersi Threat Intelligence"
description = "Detects Odoo RPC payloads targeting l10n_fr_fec reporting engine (CVE-2021-23176)"
cve = "CVE-2021-23176"
date = "2024-05-15"
severity = "high"
strings:
$fec_model = "l10n_fr_fec" ascii wide
$fec_report = "fec.report" ascii wide
$rpc_exec = "execute_kw" ascii wide
$rpc_call = "call_kw" ascii wide
$xmlrpc = "xmlrpc/2/object" ascii wide
$jsonrpc = "jsonrpc" ascii wide
$export_model = "export" ascii wide
$get_lines = "get_lines" ascii wide
$date_range = "date_from" ascii wide
$fiscal_year = "fiscalyear_id" ascii wide
condition:
(any of ($rpc*) and any of ($fec*) and 2 of ($export*))
or
(any of ($rpc*) and any of ($fec*) and any of ($date_range*))
}
Suricata IDS Rule
alert http any any -> any any (msg:"Odoo CVE-2021-23176 - FEC RPC Exploitation Attempt"; flow:established,to_server; content:"POST"; http_method; content:"/xmlrpc/2/object"; http_uri; nocase; content:"execute_kw"; http_client_body; content:"l10n_fr_fec"; http_client_body; nocase; content:"get_lines"; http_client_body; nocase; classtype:attempted-recon; reference:cve,2021-23176; reference:url,https://nvd.nist.gov/vuln/detail/CVE-2021-23176; sid:10023176; rev:1;)
Elastic Detection
sequence by user.name, host.name with maxspan=5m
[network where event.category == "network" and network.protocol == "http"
and url.path in ("/xmlrpc/2/object", "/jsonrpc")
and url.path != null
and http.request.method == "POST"]
[file where event.category == "file" and file.extension in ("xml", "csv", "json")
and process.name == "odoo"
and file.size > 10000]
[authentication where event.category == "authentication"
and authentication.result == "success"
and user.roles in ("portal", "public", "base.group_user")]
Splunk SPL Query
index=odoo sourcetype=access_combined
| where uri_path="/xmlrpc/2/object" OR uri_path="/jsonrpc"
| spath input=form_data
| rename form_data{}.args{}.kwargs.model as model
| where model LIKE "%fec%"
| rename form_data{}.args{}.kwargs.method as rpc_method
| rename form_data{}.args{}.kwargs.args{}.date_from as date_from
| stats count by user src_ip model rpc_method date_from _time
| where count > 5
| eval severity="HIGH", cve="CVE-2021-23176", tactic="Initial Access"
| table _time user src_ip model rpc_method date_from count severity cve
Wazuh OSSEC Rule
<group name="odoo,">
<rule id="700878" level="15">
<decoded_as>json</decoded_as>
<field name="source">odoo.rpc</field>
<regex>l10n_fr_fec</regex>
<regex>get_lines</regex>
<regex>execute_kw</regex>
<description>Odoo CVE-2021-23176 - Attempted unauthorized access to FEC reporting module</description>
<mitre>
<id>T1190</id>
</mitre>
<group>cve_2021_23176,attp_t1190,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch Confidence: 3/4 — LIKELY. Two independent sources (CNA and Debian) confirm a fix is available, although the exact version number of the patched release is not provided in the available data.
1) Immediate Mitigations
- Upgrade Odoo to the latest patched version. Since the affected version is "15.0 and earlier," any release after the initial 15.0 GA that includes the security fix should be applied. For 15.0 users, verify the exact patch version via Odoo's security advisory channel.
- If immediate patching is impossible, restrict access to the
l10n_fr_fecreporting model by:- Removing the module's access rights from all non-accounting user groups in Settings → Users → Access Rights.
- Removing the
l10n_fr_fecmodule from non-essential databases entirely, if the statutory FEC requirement can be fulfilled by alternative reporting tools.
- Implement network-level access control: Restrict access to Odoo's RPC endpoints (
/xmlrpc/2/objectand/jsonrpc) to trusted IP ranges via firewall rules or reverse-proxy ACLs. - Enable two-factor authentication (2FA) for all Odoo user accounts to raise the bar for credential compromise, which is a prerequisite for exploiting this vulnerability.
2) Patch/Upgrade Steps
- Schedule a maintenance window — Odoo upgrades require downtime.
- Backup the production database and file store (
/var/lib/odoo/filestore) before beginning. - Review custom modules for compatibility with the target version and run upgrade tests in a staging environment first.
- Execute the upgrade using the standard Odoo upgrade process (for Community:
apt upgradeor pulling the new Docker image; for Enterprise: use the Odoo upgrade service or manual package replacement). - After upgrade, run the module update for
l10n_fr_fecusing Odoo's Apps → Update functionality. - Verify the fix by attempting (with a test user account) to invoke the FEC reporting RPC method and confirming that access is properly denied.
3) Long-Term Hardening
- Adopt a least-privilege access model for all Odoo users: review group memberships quarterly and remove any users with unnecessary access to financial modules.
- Enable comprehensive logging at the Odoo application layer, capturing all RPC calls, user IDs, source IPs, and model/method invocations. Feed these logs into a SIEM for continuous monitoring.
- Deploy a WAF (Web Application Firewall) in front of the Odoo instance with rules to inspect RPC payloads for known malicious patterns.
- Monitor Odoo security advisories and subscribe to the vendor's security notification list for rapid response to future vulnerabilities.
- Conduct periodic penetration testing of the Odoo deployment, focusing on access control mechanisms and multi-tenant isolation boundaries.
References
- NVD Entry: https://nvd.nist.gov/vuln/detail/CVE-2021-23176
- Odoo Security Advisory: https://www.odoo.com/security/advisories (referencing CVE-2021-23176 and confirming the fix in version 15.0+)
- Debian Security Tracker: https://security-tracker.debian.org/tracker/CVE-2021-23176 (confirms the Debian package fix)
- Odoo Source Code (GitHub) —
l10n_fr_fecmodule: https://github.com/odoo/odoo/tree/15.0/addons/l10n_fr_fec (for authorized researchers reviewing the patch diff)
Threat Actor Campaigns: As of the intelligence date, there is no evidence of active exploitation in the wild. The CISA KEV catalog does not list this CVE, and the EPSS score of 0.00788 (53.0% percentile) indicates a low but non-zero probability of exploitation. No threat actor campaigns or exploit-in-the-wild reports have been identified. This does not diminish the risk, as the low EPSS percentile may reflect the limited geographic spread of the affected module (French localization) rather than the absence of attacker interest.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.