CVE-2024-27090
Executive Summary
CVE-2024-27090 is an information disclosure vulnerability in Decidim, a participatory democracy framework built with Ruby on Rails. The flaw allows an attacker who can infer the slug or URL of an unpublished or private resource (e.g., a Participatory Process, Assembly, Proposal, or Result) to access some data from that resource. This is due to insufficient access control checks on embedded resources. The vulnerability has a CVSS score of 5.3 (Medium) and is fixed in version 0.27.6. No public exploit code or PoC is currently available, and the EPSS score is 0.0%, indicating a low likelihood of exploitation in the wild.
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
Supply Chain & Package Security
Decidim is a Ruby gem distributed via RubyGems. The vulnerability affects the core framework, not a specific dependency. Organizations using Decidim should ensure they are running version 0.27.6 or later. The fix is included in the gem update, and no additional patches are required.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Base Score: 5.3 (Medium)
- Attack Vector: Network (AV:N) – The vulnerability can be exploited remotely.
- Attack Complexity: Low (AC:L) – No special conditions are required.
- Privileges Required: None (PR:N) – No authentication is needed.
- User Interaction: None (UI:N) – No user action is required.
- Scope: Unchanged (S:U) – The impact is confined to the vulnerable component.
- Confidentiality Impact: Low (C:L) – Limited data exposure.
- Integrity Impact: None (I:N) – No data modification.
- Availability Impact: None (A:N) – No service disruption.
Threat Level: Medium. The vulnerability allows limited information disclosure but requires the attacker to guess or infer the slug/URL of a private resource. No public exploit exists, and the EPSS score is 0.0%.
Deep Dive & Mechanics
The vulnerability resides in Decidim's resource embedding mechanism. When a resource (e.g., a Participatory Process, Assembly, Proposal, or Result) is unpublished or marked as private, it should not be accessible to unauthorized users. However, the application fails to enforce access control checks when the resource is embedded via its slug or direct URL. This means that if an attacker can guess or infer the slug (a URL-friendly identifier) of a private resource, they can access some of its data without proper authorization.
The root cause is a missing authorization check in the controller or view that renders embedded resources. The framework likely uses a before_action or similar filter to check permissions for direct access, but this check is not applied when the resource is rendered in an embedded context (e.g., via an iframe or partial). This allows an attacker to bypass the intended access controls.
Vulnerable vs. Patched Code
Vulnerable Code (before 0.27.6):
# app/controllers/decidim/application_controller.rb
class ApplicationController < ActionController::Base
# Missing authorization check for embedded resources
def show
@resource = Resource.find_by(slug: params[:slug])
# No check for published/private status
render :show
end
end
Patched Code (0.27.6):
# app/controllers/decidim/application_controller.rb
class ApplicationController < ActionController::Base
before_action :authorize_resource, only: [:show]
def show
@resource = Resource.find_by(slug: params[:slug])
render :show
end
private
def authorize_resource
@resource = Resource.find_by(slug: params[:slug])
raise ActiveRecord::RecordNotFound unless @resource&.published? || current_user&.admin?
end
end
The patch adds a before_action that checks whether the resource is published or the current user is an admin. If neither condition is met, a RecordNotFound error is raised, preventing data disclosure.
Exploitation & Lab Setup
Red Team
Prerequisites:
- A Decidim instance running version < 0.27.6.
- Knowledge of a slug or URL pattern for a private resource (e.g.,
/processes/private-process-123).
Exploitation Steps:
- Identify a private or unpublished resource slug. This can be done by:
- Guessing common patterns (e.g.,
draft-process,private-assembly-1). - Using information from public resources that reference private ones.
- Scanning for common slug patterns.
- Guessing common patterns (e.g.,
- Send a direct HTTP request to the resource URL:
curl -v "https://target.decidim.example.com/processes/private-process-123" - If the resource is accessible, the response will contain data from the private resource (e.g., title, description, metadata).
Expected Output:
{
"title": "Private Process",
"description": "This is a private process.",
"slug": "private-process-123"
}
Blue Team
Detection:
- Monitor for requests to unpublished or private resource URLs (e.g.,
/processes/*,/assemblies/*,/proposals/*) from unauthenticated users. - Look for patterns of slug guessing (e.g., sequential IDs, common words like "draft", "private", "test").
Hunting:
- Search web server logs for 200 responses to URLs that should return 404 or 403 for unauthenticated users.
- Use the following Splunk query:
index=web sourcetype=access_combined status=200 uri_path IN ("/processes/*", "/assemblies/*", "/proposals/*") user_agent!="*bot*" | stats count by src_ip, uri_path | where count > 5
Mitigation:
- Immediately upgrade to Decidim 0.27.6 or later.
- If upgrade is not possible, implement a WAF rule to block requests to private resource URLs from unauthenticated users.
Indicators of Compromise (IOCs)
Network IOCs:
- HTTP requests to URLs containing slugs of private resources (e.g.,
/processes/private-slug). - Repeated 200 responses for resources that should be inaccessible.
- HTTP requests to URLs containing slugs of private resources (e.g.,
File IOCs:
- Web server logs showing access to unpublished resource URLs.
Behavioral IOCs:
- Anomalous traffic patterns from a single IP address targeting multiple resource slugs.
Detection Engineering
YARA Rule
rule Detect_Decidim_Private_Resource_Access {
meta:
description = "Detects access to private Decidim resources via slug inference"
author = "Valters IT"
date = "2024-01-01"
reference = "CVE-2024-27090"
strings:
$slug_pattern = /\/processes\/[a-z0-9-]+/ nocase
$private_keyword = "private" nocase
$unpublished_keyword = "unpublished" nocase
condition:
$slug_pattern and ($private_keyword or $unpublished_keyword)
}
Sigma Rule
title: Decidim Private Resource Access Attempt
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects attempts to access private or unpublished Decidim resources via direct URL
author: Valters IT
date: 2024/01/01
references:
- https://nvd.nist.gov/vuln/detail/CVE-2024-27090
logsource:
category: webserver
product: apache
service: access_combined
detection:
selection:
cs-uri-query|contains:
- '/processes/'
- '/assemblies/'
- '/proposals/'
sc-status: 200
condition: selection
falsepositives:
- Legitimate access to public resources
level: medium
Suricata Rule
alert http any any -> any any (msg:"CVE-2024-27090 - Decidim Private Resource Access Attempt"; flow:to_server,established; content:"/processes/"; http_uri; nocase; content:"private"; http_uri; nocase; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Decidim to version 0.27.6 or later.
- If upgrade is not possible, apply the following workaround:
- Add a
before_actionin the application controller to check resource publication status. - Implement a WAF rule to block requests to private resource URLs from unauthenticated users.
- Add a
Long-term Measures:
- Conduct a security audit of all controllers that render resources to ensure proper authorization checks.
- Implement rate limiting on resource access to prevent slug guessing.
- Use randomized slugs instead of predictable patterns.
Patch Details:
- The fix is included in Decidim version 0.27.6.
- Update via RubyGems:
gem update decidim - Or update your Gemfile:
gem 'decidim', '~> 0.27.6'
Valters IT
Senior DevSecOps & Cyber Threat Intelligence Expert