CVE-2024-32651 – Server Side Template Injection (Changedetection.io)
TL;DR
A Server Side Template Injection in changedetection.io caused by usage of unsafe functions of Jinja2 allows Remote Command Execution on the server host. Update changedetection.io to version 0.45.21 or later.
A huge thanks to the mantainer (https://github.com/dgtlmoon) that was very responsive and collaborative to fix the issue, request a CVE number and inform the users.
What is Changedetection.io
Changedetection.io is a tool designed to monitor web pages for changes. It’s extremely useful for being notified on changes for news articles, product updates, or any other online content.
It’s a fully open-source product, you can check the source code on GitHub: https://github.com/dgtlmoon/changedetection.io (about 15k stars at the time of writing). It’s possible to deploy a self-hosted or a cloud-hosted version (https://changedetection.io/).
Some of its key features:
- Notification Support: Whenever a change is detected, Changedetection.io notifies you using a plenty of different formats (Discord, Slack, Telegram, Rocket.Chat, Email, Matrix, NTFY, Office 365… more than 85 formats in total).
- Target Elements: Select only what you need, easily choose elements to monitor. The tool highlights the specific modifications made to the webpage since the last check, making it easy to spot changes at a glance.
- Browser Steps: Perform searches, Log in with username and password, Add to cart, Interact with fields, buttons and many more possibilities.
- Re-stock alerts: Monitor out-of-stock products and get alerts when those products are back in stock.
- Archive: Changedetection.io maintains an archive of the monitored web pages, enabling you to view the historical changes over time.
Vulnerability Details
SSTI, or Server-Side Template Injection, represents a security vulnerability where an attacker inserts harmful content into a server-side template. When the server processes this template to create dynamic web pages, it executes the injected code too. This poses serious risks such as data exposure, unauthorized entry, and even remote code execution on the server.
Putting that down simply, imagine a web app that crafts HTML pages using templates. If an attacker injects their own template code into the server’s workflow, they gain the power to modify the page’s structure and potentially trigger harmful actions. For instance, they could insert code to access confidential server data or tamper with the app’s behavior in undesirable ways. SSTI flaws demand careful handling to prevent exploitation.
The following examples illustrate the dangers of SSTI vulnerabilities and why it’s crucial for developers to properly validate and sanitize user input to prevent such attacks.
Remote Code Execution: In more severe cases, an attacker might be able to execute arbitrary code on the server by injecting template code that triggers server-side commands. For example: {{ 3*3 }}
. If the server evaluates this input as Python code, it would execute 3*3
and return 7
(joking, 9 obviously).
Now, imagine if an attacker injects more complex Python code to perform malicious actions, like deleting files or accessing system resources. This could lead to a complete compromise of the server.
Web page Manipulation: SSTI can also be used to manipulate the page presented by the application. For instance, an attacker might inject template code to alter the layout of the page, insert malicious Javascript code, or redirect users to phishing sites:
{% if user.is_admin %}
<script>alert('admin pwned');</script>
{% endif %}
In this example, if the attacker can inject this code into a template and the server evaluates it, every user viewing the page might be subjected to a malicious script, potentially leading to further compromise or unauthorized actions.
Accessing Sensitive Data: Let’s say a web application uses templates to display user profiles. The template might include code to fetch the user’s information from a database and render it on the profile page.
However, if the application doesn’t properly sanitize user input and an attacker can inject template code, they might inject something like: {{ database.password }}
. If this input gets processed by the server, the attacker could potentially access sensitive information such as database passwords, API keys, or other confidential data stored on the server.
In this specific case, changedetection.io uses Jinja (https://jinja.palletsprojects.com/) as templating engine to build the management dashboard.
The following is a snippet of code taken from changedetection.io (0.45.20, vulnerable to this CVE) codebase:
from jinja2 import Environment, BaseLoader
...
# Get the notification body from datastore
jinja2_env = Environment(loader=BaseLoader)
n_body = jinja2_env.from_string(n_object.get('notification_body', '')).render(**notification_parameters)
n_title = jinja2_env.from_string(n_object.get('notification_title', '')).render(**notification_parameters)
The issue lays in the usage of the default Jinja2 environment (https://jinja.palletsprojects.com/en/3.1.x/api/#jinja2.Environment). The latter doesn’t prevent any SSTI injection, as opposed to SandboxedEnvironment, which is as the name suggests…guess it… sandboxed, safe. Citing the SandboxedEnvironment description:
“The sandboxed environment. It works like the regular environment but tells the compiler to generate sandboxed code. Additionally subclasses of this environment may override the methods that tell the runtime what attributes or functions are safe to access.”
It’s still a mistery why PalletsProjects doesn’t make the sandboxed one the default. As written in the security considerations, the sandboxed environment is not the “best” in terms of security, it can be still improved. They suggest to use ImmutableSandboxedEnvironment, that prevents modifying lists and dictionaries. Read more here https://jinja.palletsprojects.com/en/3.1.x/sandbox/#security-considerations.
Proof of Concept
Deploy a vulnerable version of changedetection.io using the official docker image (we’re using version 0.45.20
).
docker run -p "127.0.0.1:5000:5000" -v datastore-volume:/datastore --name changedetection.io ghcr.io/dgtlmoon/changedetection.io:0.45.20
If everything works correctly, you should be able to access the main page without any password needed at http://127.0.0.1:5000/. Confirm the version you’re using is the correct one, see the version banner on the upper right corner.
For the PoC we use the YCombinator News website because it changes very frequently.
Click on the “Edit” button, you should see this page. Set 30 seconds as time between checks, so the target URL will be frenquently monitored.
Navigate to the “Notifications” tab. Here we have to insert some values:
- We use Telegram as notification system. This is not needed in a real-case exploit, but it’s useful for the PoC as we’ll read the output of the system command we execute directly in a Telegram message. In order to setup Telegram notifications, we need a bot. Follow this guide https://github.com/caronc/apprise/wiki/Notify_telegram to setup a bot and obtain a valid AppRise Telegram URL. The URL should be something like this:
tgram://bottoken/ChatID
. - The “Notification Title” value is not important, we use “SSTI Test”, but we could use whatever input.
- In the “Notification Body” we insert the actual payload, that is:
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}
Now we can click “Save” and return to the main page. Now the monitoring should be triggered, if not just click on the button “Recheck”.
If the YCombinator News website actually had a change, we should receive a Telegram notification with the output of the id
system command.
Nuclei Template
The following is a Nuclei template that checks if a target is vulnerable to CVE-2024-32651.
This is safe template! It doesn’t perform any injection, it just extracts the version and checks if the target is vulnerable.
id: CVE-2024-32651
info:
name: Change Detection - Server Side Template Injection
author: edoardottt
severity: critical
description: |
A Server Side Template Injection in changedetection.io caused by usage of unsafe functions of Jinja2 allows Remote Command Execution on the server host.
reference:
- https://nvd.nist.gov/vuln/detail/CVE-2024-32651
- https://github.com/dgtlmoon/changedetection.io/security/advisories/GHSA-4r7v-whpg-8rx3
- https://github.com/dgtlmoon/changedetection.io/releases/tag/0.45.21
- https://www.onsecurity.io/blog/server-side-template-injection-with-jinja2
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
cvss-score: 10
cve-id: CVE-2024-32651
cwe-id: CWE-1336
epss-score: 0.00045
epss-percentile: 0.14322
metadata:
verified: true
max-request: 1
shodan-query: html:"Change Detection"
tags: cve,cve2024,changedetection,ssti,rce,passive
http:
- method: GET
path:
- "{{RootURL}}/"
redirects: true
max-redirects: 2
extractors:
- type: xpath
name: version
internal: true
xpath:
- "//*[@id=\"right-sticky\"]"
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: word
part: body
words:
- "Change Detection"
condition: and
- type: dsl
dsl:
- compare_versions(version, '<= 0.45.20')
In order to help the Infosec community we’ve uploaded this template to the official nuclei-templates database too: nuclei-templates/CVE-2024-32651.yaml.
You can use this template using:
nuclei -t CVE-2024-32651.yaml -u "http://example.com/"
It’s possible to check is a target is vulnerable istantly because the root page contains the version string.
Changes were suggested to avoid fingerprinting en masse (dgtlmoon/changedetection.io#2190).
Impact
Consider that changedetection.io can be installed using docker, pip and direct installation from source (https://github.com/dgtlmoon/changedetection.io?tab=readme-ov-file#installation). With the docker installation method, the RCE will have less severe impact with regards to the other two methods as the attacker must find a way to escape from the container in order to compromise the server host.
A potential attacker exploiting this CVE could:
- Exfiltration of Confidential Information: Attackers could use the compromised server as a staging ground to exfiltrate confidential information from within the network. This could include proprietary business data, customer records, or even login credentials stored insecurely.
- Compromise the entire system: An attacker could gain full control over the server hosting the web application. This means they could read, modify, or delete any files, install malware or backdoors, and even pivot to other systems within the network.
- Escalate Privileges: If the web application runs with elevated privileges, an attacker could use the RCE vulnerability to escalate their access within the system or network, gaining even more control and potentially compromising additional resources.
- Perform Denial of Service (DoS) Attacks: An attacker could use the compromised server to launch DoS attacks against other systems or services, potentially disrupting operations, causing financial losses, or damaging the reputation of the affected organization.
- Manipulate and/or steal data: With control over the server, an attacker could access sensitive data stored on the system or in connected databases. This could include personal information, financial data, or intellectual property. They could also manipulate this data, either by altering it, deleting it, or holding it for ransom.
Examples of actions a real attacker could perform with an RCE vulnerability include:
- Executing commands to pivot to other systems within the network.
- Accessing sensitive files such as password hashes or configuration files.
- Installing malware or backdoors to maintain persistent access.
- Deleting critical system files to render the server inoperable.
- Launching further attacks, such as phishing campaigns or additional exploitation of other vulnerabilities.
Given the severity of RCE vulnerabilities, it’s crucial to patch them as soon as possible and implement proper security measures to prevent future occurrences. Read the following section to understand how to stay safe.
Remediation
There are two things to do, the first is the actual patch, the second is a security best-practice:
- Update changedetection.io to version
0.45.21
or later. The mantainer pushed the patch to this vulnerability in version0.45.21
. - Add a password for the login. Use a strong password. Navigate to
/settings#general
to set a password.
The second one is not a mitigation for CVE-2024-32651, just a best-practice to avoid random users accessing your changedetection.io instance.
Consider also that there could be other vulnerabilities as well in the latest version too, so having a password to protect unauthorized users is always a good option.
Since changedetection.io is a open-source project, we suggested changes through a GitHub issue to add a password by default (dgtlmoon/changedetection.io#2339).
Conclusions
We can search exposed changedetection.io instances on Shodan using the query http.favicon.hash:471975650
(https://www.shodan.io/search?query=http.favicon.hash%3A471975650).
At the time of writing nearly 700 instances were exposed, very few of them applied the official patch and some don’t even have a password protection.
In conclusion, the CVE presents a critical risk due to its potential for remote command execution. This vulnerability exposes systems to unauthorized access and malicious manipulation of sensitive data, posing significant security threats to affected environments. It’s really important for organizations to install the official patch quickly and implement additional security measures, such as network segmentation and access controls to minimize the impact of this vulnerability.
Proactive monitoring and threat detection mechanisms are also essential to detect and respond to any attempted exploitation. If organizations deal with this problem fast and thoroughly, they’ll be safer from potential hackers and other security issues.