Here is the combined list of vulnerabilities, formatted as markdown:
This document outlines the identified vulnerabilities, combining information from the provided lists and removing duplicates. Each vulnerability is detailed with its description, potential impact, severity ranking, mitigation status, and steps for verification and remediation.
- The
docker-compose.yml
file provided with the application configures a Redis service. - The command used to start the Redis server includes
--enable-debug-command yes
and--protected-mode no
. --enable-debug-command yes
activates debug commands in Redis, which are intended for development and debugging, not for production environments. These commands can expose sensitive internal server details and allow for advanced server manipulation.--protected-mode no
disables a crucial security feature in Redis. Protected mode, when enabled, restricts access from remote clients if no explicitbind
orrequirepass
configuration is set. Disabling it without implementing other access control measures makes the Redis instance vulnerable to unauthorized access if the Redis port is publicly accessible.- Furthermore, the
docker-compose.yml
exposes Redis ports6379
(and Sentinel port26379
) to the host machine using theports
directive, making them potentially accessible from outside the Docker host. - If a publicly accessible instance of the application is deployed using this
docker-compose.yml
, and the Redis port (6379) is exposed to the internet, an external attacker can directly connect to the Redis instance without any authentication. - Once connected, the attacker can execute any Redis commands, including debug commands enabled by
--enable-debug-command yes
. This allows them to retrieve sensitive information, manipulate data, or even potentially achieve Remote Code Execution (RCE) by leveraging Redis configuration commands if the server user has sufficient write permissions on the filesystem.
- Critical. Unauthorized access to the Redis instance by an attacker can lead to severe consequences:
- Information Disclosure: Attackers can use debug and other Redis commands to retrieve sensitive information about the Redis server's internal state, configuration, cached data, and potentially application data stored in Redis.
- Data Manipulation and Corruption: Attackers can modify, delete, or add data within the Redis cache, leading to data corruption, application malfunction, or denial of service.
- Remote Code Execution (RCE): In certain misconfigurations where the Redis server process has sufficient filesystem write permissions, attackers can leverage Redis commands like
CONFIG SET dir
andCONFIG SET dbfilename
combined withSAVE
to write malicious files (e.g., web shells) to the server's filesystem. If the web server can then access and execute these files, it can result in complete server compromise and remote code execution. - System Information Leakage: Debug commands expose internal system information which can be valuable for further attacks.
- None. The described vulnerability originates from an insecure default configuration within the provided
docker-compose.yml
file. There are no mitigations implemented in thedocker-compose.yml
or the application code by default to address this misconfiguration.
- Secure default configuration in
docker-compose.yml
for production deployments:- Enable protected mode: Remove
--protected-mode no
from theredis-server
command. Redis default is protected modeyes
, so simply removing the flag will enable it. Alternatively, explicitly set--protected-mode yes
. - Disable debug commands: Remove
--enable-debug-command yes
from theredis-server
command. Debug commands should be strictly disabled in production environments. - Implement Authentication: Configure Redis to require authentication by setting the
requirepass
option in aredis.conf
file. Mount this configuration file into the Redis container. - Restrict Network Exposure: Avoid exposing Redis ports directly to the public internet. If external access is necessary, implement strict firewall rules or network segmentation to limit access to only authorized IP addresses or networks. For development environments, consider binding Redis to
localhost
only. - Principle of Least Privilege: Ensure that the Redis server process runs with the minimum necessary privileges to reduce the impact of potential RCE vulnerabilities.
- Enable protected mode: Remove
- The application is deployed using the provided, insecure
docker-compose.yml
configuration. - The server where the
docker-compose.yml
is deployed is publicly accessible, or the Redis ports (6379 and/or 26379) are reachable from an attacker's network. - No additional network security measures (like firewalls) are in place to restrict access to the Redis ports.
- The root cause of this vulnerability is not within the application's Python source code, but in the configuration specified in the
docker/docker-compose.yml
file. - The insecure configuration is introduced by the following lines in the
docker-compose.yml
:File: /code/docker/docker-compose.yml Content: services: redis: image: redis:latest container_name: redis-primary command: redis-server --enable-debug-command yes --protected-mode no ports: - 6379:6379 # ...
- Specifically, the
command: redis-server --enable-debug-command yes --protected-mode no
line sets the insecure flags. Theports: - "6379:6379"
line exposes the port, making the misconfiguration exploitable if deployed in a public environment.
- Deploy the application using the provided
docker-compose.yml
by runningdocker compose -f docker/docker-compose.yml up -d
. - Determine the public IP address or hostname of the server where the Docker containers are running. Let's assume it is
<YOUR_PUBLIC_IP>
. Ensure that port 6379 on this server is accessible from your testing environment. - On your attacker machine, install
redis-cli
if it's not already installed. - Open a terminal and connect to the exposed Redis instance using
redis-cli -h <YOUR_PUBLIC_IP> -p 6379
. - If the connection is established successfully without prompting for a password (you should see the Redis prompt
127.0.0.1:6379>
), the vulnerability is present. - Execute the
INFO
command in theredis-cli
console. Examine the output and verify thatprotected_mode:no
is listed. - Execute the
CONFIG GET debug-output-options
command. Verify that debug commands are enabled by checking the output. - Attempt to set and retrieve a key to confirm basic Redis functionality:
SET testkey testvalue
GET testkey
- Verify that
GET testkey
returnstestvalue
.
- Attempt to execute a debug command, for example,
DEBUG OBJECT testkey
. Verify that debug information related to the key is returned, confirming that debug commands are enabled. - The successful execution of these steps (unauthenticated connection,
protected_mode:no
, debug commands enabled, basic Redis command execution) confirms the insecure Redis configuration vulnerability.
- The
django-redis
package, by default, utilizesPickleSerializer
for serializing and deserializing data stored in the Redis cache. - The
PickleSerializer
relies on Python's built-inpickle
module. - The
loads
method ofPickleSerializer
directly callspickle.loads(value)
on data retrieved from the Redis cache without any sanitization or verification. - Python's
pickle
module is known to be insecure when used to deserialize data from untrusted sources. Deserializing a malicious pickle payload can lead to arbitrary code execution. - If an attacker can inject a specially crafted, malicious pickle payload into the Redis cache (cache poisoning), for instance, by directly accessing a misconfigured Redis instance or through another vulnerability in the application that allows cache manipulation, the application becomes vulnerable.
- When the application subsequently retrieves this poisoned data from the cache using methods like
cache.get()
, thePickleSerializer
will deserialize the malicious payload usingpickle.loads()
. - This deserialization process will execute the embedded malicious code within the context of the application server, potentially leading to Remote Code Execution (RCE) and complete compromise of the hosting server.
- Critical. Successful exploitation of this vulnerability can lead to:
- Remote Code Execution (RCE): An attacker can execute arbitrary code on the server hosting the application. This is the most severe impact, potentially allowing for full system takeover.
- Data Leakage: Attackers can use RCE to access sensitive data stored on the server, including application secrets, database credentials, and user data.
- System Takeover: RCE allows attackers to gain complete control over the compromised server, enabling them to install backdoors, manipulate application functionality, and use the server for further malicious activities, such as lateral movement within a network.
- The
django-redis
package does not enforce or provide a safe serialization mechanism by default. - While
django-redis
allows administrators to configure alternative serializers (like JSON or msgpack) through theSERIALIZER
setting in the cache configuration, the default remainsPickleSerializer
. - There are no built-in checks, signatures, or validation mechanisms to ensure the integrity and trustworthiness of data being deserialized using
PickleSerializer
. - No warnings or runtime flags are raised when
PickleSerializer
is used in environments where the Redis instance might be accessible to untrusted actors, potentially leading to accidental insecure deployments.
- Enforce or Recommend a Safer Default Serializer: The package should default to a safer serializer, such as JSON or msgpack, which do not inherently carry the risk of arbitrary code execution during deserialization.
- Provide Clear Security Guidance: Documentation should prominently warn against the security risks of using
PickleSerializer
, especially in production environments or when the Redis cache might be exposed to untrusted networks or potential cache poisoning attacks. Recommendations for safer alternatives and secure Redis configuration should be clearly provided. - Implement Optional Integrity Checks: Consider adding optional mechanisms to verify the integrity and origin of cached data, such as digital signatures or HMAC, especially when using serializers like Pickle. However, switching to a safer serializer is generally a more effective first step.
- Runtime Warning for Insecure Default in Production: Implement a runtime warning or configuration check that alerts administrators if
PickleSerializer
is being used in a production-like environment where Redis might be accessible to untrusted actors.
- The
django-redis
cache backend is configured to use the defaultPickleSerializer
. - The Redis cache instance is reachable by an external attacker. This could be due to misconfiguration, exposure to a public network without proper authentication or firewalling, or other network vulnerabilities.
- The application stores data in the cache that could potentially be influenced or poisoned by external input, or the application operates in an environment where untrusted sources can inject data into the cache.
- The vulnerability resides in the
PickleSerializer
class withindjango_redis/serializers/pickle.py
:# File: django_redis/serializers/pickle.py import pickle class PickleSerializer: def __init__(self, pickle_version=pickle.HIGHEST_PROTOCOL): self._pickle_version = pickle_version def dumps(self, value): return pickle.dumps(value, self._pickle_version) def loads(self, value): return pickle.loads(value) # UNSAFE DESERIALIZATION
- The
loads(value)
method directly callspickle.loads(value)
without any safety checks. - In
django_redis/client/default.py
(and similar client code), when retrieving data from the cache:# File: django_redis/client/default.py (example) def get(self, key, default=None, version=None, client=None): # ... value = self.connection.get(key) # Raw data from Redis if value is None: return default value = self.decode(value) # Decode from bytes (if needed) value = self._serializer.loads(value) # UNSAFE DESERIALIZATION return value
- The retrieved raw data from Redis is passed to
self._serializer.loads(value)
, which, if usingPickleSerializer
, will execute the unsafepickle.loads()
call. - If an attacker can inject a malicious pickle payload into Redis under a key that the application retrieves, the
get()
operation will trigger the unsafe deserialization and execute the attacker's code.
- Setup:
- Deploy the application with the default cache configuration, ensuring
PickleSerializer
is in use. - For testing, make the Redis instance accessible to your attacker machine (this could be in a controlled test environment simulating a misconfigured production setup).
- Deploy the application with the default cache configuration, ensuring
- Payload Creation:
- On your attacker machine, create a malicious pickle payload. This payload should contain Python code that, when deserialized, will perform an observable action, such as writing a specific message to a file on the server.
- Example payload generation (attacker machine):
import pickle import os class MaliciousPayload: def __reduce__(self): return (os.system, ('echo "Vulnerable" > /tmp/vuln.txt',)) payload = pickle.dumps(MaliciousPayload()) print(payload)
- Injection:
- Manually inject the generated malicious pickle payload into the Redis store. You can use
redis-cli
or a Redis client library for this. Choose a key that you know the application will later attempt to retrieve from the cache (e.g.,test_pickle_key
). - Using
redis-cli
:redis-cli -h <REDIS_HOST> -p <REDIS_PORT> SET test_pickle_key "$(python -c 'import pickle; import os; class MaliciousPayload: def __reduce__(self): return (os.system, ("echo \"Vulnerable\" > /tmp/vuln.txt",)); print(pickle.dumps(MaliciousPayload()).decode("latin-1"))')"
- Manually inject the generated malicious pickle payload into the Redis store. You can use
- Trigger:
- Trigger the application to retrieve the value associated with the key
test_pickle_key
from the cache. This might involve accessing a specific URL or performing an action in the application that results in acache.get('test_pickle_key')
call.
- Trigger the application to retrieve the value associated with the key
- Verification:
- After triggering the cache retrieval, check for the observable action on the server. In the example payload, this is checking for the existence of the
/tmp/vuln.txt
file and verifying its content is "Vulnerable". - If the file
/tmp/vuln.txt
exists and contains "Vulnerable", it confirms that the malicious pickle payload was successfully deserialized and executed, demonstrating the Unsafe Deserialization vulnerability.
- After triggering the cache retrieval, check for the observable action on the server. In the example payload, this is checking for the existence of the
Recommendation:
For both vulnerabilities, immediate remediation is strongly advised, especially for any deployments resembling production environments.
- For Insecure Redis Configuration: Harden the Redis configuration by enabling protected mode, disabling debug commands, implementing authentication, and restricting network access. Review and adjust the
docker-compose.yml
to reflect these secure settings for non-development deployments. - For Unsafe Deserialization: Switch the default serializer from
PickleSerializer
to a safer alternative like JSON or msgpack by configuring theSERIALIZER
option in thedjango-redis
cache settings. Ensure that Redis instances are properly secured to prevent unauthorized access and cache poisoning attacks, regardless of the serializer in use.
These vulnerabilities, particularly when combined, pose a significant risk to the application's security and should be addressed with high priority.