Here is the combined list of vulnerabilities, formatted as markdown, with duplicates removed and descriptions consolidated:
Unsafe Deserialization with YAMLSerializer
-
Description:
- An attacker finds a way to inject data into the Redis cache. This could be through a separate vulnerability in the application using
django-redis-cache
or if the Redis instance is exposed and not properly secured. - The attacker crafts a malicious YAML payload designed to execute arbitrary code upon deserialization. A sample payload could be:
!!python/object/apply:os.system ["touch /tmp/pwned"]
. - The attacker sets a cache key in Redis with this malicious YAML payload as the value, for example using
redis-cli
commandSET malicious_key '!!python/object/apply:os.system ["touch /tmp/pwned"]'
. - The Django application, configured to use
redis_cache.RedisCache
withYAMLSerializer
, attempts to retrieve and deserialize this cache key usingcache.get('malicious_key')
. - The
YAMLSerializer
'sdeserialize
method inredis_cache/serializers.py
usesyaml.load(value, Loader=yaml.FullLoader)
.yaml.FullLoader
is known to be unsafe and vulnerable to arbitrary code execution. When processing the malicious YAML payload, arbitrary code execution occurs on the server. The vulnerability occurs because theYAMLSerializer
inredis_cache/serializers.py
usesyaml.FullLoader
when deserializing YAML data.FullLoader
is known to be unsafe and can execute arbitrary code if the YAML data contains malicious payloads. An attacker can exploit a YAML deserialization vulnerability if the application is configured to use theYAMLSerializer
.
- An attacker finds a way to inject data into the Redis cache. This could be through a separate vulnerability in the application using
-
Impact: Arbitrary code execution on the server. An attacker can gain full control of the server, potentially leading to data breaches, service disruption, and further malicious activities. Successful exploitation allows an external attacker to achieve arbitrary code execution on the server hosting the Django application. This can lead to complete compromise of the server and the application, including data theft, data manipulation, and further attacks on internal systems.
-
Vulnerability Rank: Critical
-
Currently implemented mitigations: None. The
django-redis-cache
project provides theYAMLSerializer
option without any specific warnings about its unsafe nature when handling potentially untrusted data. The code inredis_cache/serializers.py
directly usesyaml.FullLoader
without any safeguards. -
Missing mitigations:
- Remove or strongly discourage the use of
YAMLSerializer
withyaml.FullLoader
due to its inherent unsafe deserialization properties. - If
YAMLSerializer
is to be kept, switch to usingyaml.SafeLoader
which is safer but has limited functionality. Alternatively, provide a very clear and prominent warning in the documentation about the severe security risks associated with usingYAMLSerializer
andyaml.FullLoader
, especially when the Redis cache might store data that could be influenced by external actors. - Recommend and promote the use of safer serializers by default, such as
JSONSerializer
orPickleSerializer
(while still noting the risks ofpickle
with untrusted input). - The
YAMLSerializer
should be changed to useyaml.SafeLoader
instead ofyaml.FullLoader
.SafeLoader
is designed to prevent the deserialization of unsafe YAML constructs that can lead to code execution. - Alternatively, the documentation should strongly warn against using
YAMLSerializer
in production environments, especially when caching potentially untrusted data, and recommend using safer serializers likeJSONSerializer
orPickleSerializer
with appropriate security considerations.
- Remove or strongly discourage the use of
-
Preconditions:
- A Django application is using
django-redis-cache
. - The Django application's cache configuration is set to use
YAMLSerializer
(i.e.,OPTIONS: {'SERIALIZER_CLASS': 'redis_cache.serializers.YAMLSerializer'}
). - An attacker is able to inject data into the Redis cache. This could arise from various scenarios, such as:
- A separate vulnerability in the Django application that allows cache poisoning.
- An improperly secured Redis instance that is accessible to the attacker.
- Internal application logic that inadvertently stores attacker-influenced data in the cache.
The Django application must be configured to use
redis_cache.serializers.YAMLSerializer
for caching. This is configured via theCACHES
setting in Django'ssettings.py
. An attacker must be able to influence or control the data that gets stored in the cache. This could happen if the application directly or indirectly caches user inputs, or if there is another vulnerability that allows cache poisoning.
- A Django application is using
-
Source Code Analysis:
- File:
/code/redis_cache/serializers.py
- Class:
YAMLSerializer
- Method:
deserialize(self, value)
class YAMLSerializer(BaseSerializer): def serialize(self, value): return yaml.dump(value, encoding='utf-8', Dumper=yaml.Dumper) def deserialize(self, value): return yaml.load(value, Loader=yaml.FullLoader)
- The
deserialize
method utilizesyaml.load(value, Loader=yaml.FullLoader)
. The use ofyaml.FullLoader
makes the deserialization process vulnerable to arbitrary code execution if thevalue
originates from or is influenced by an untrusted source. Although in typical cache usage, data is serialized and deserialized within the application's control, scenarios where an attacker can inject data into the cache create a critical security vulnerability whenYAMLSerializer
is employed. - The
deserialize
method of theYAMLSerializer
class usesyaml.load(value, Loader=yaml.FullLoader)
.yaml.FullLoader
inPyYAML
is known to be vulnerable to arbitrary code execution because it allows deserialization of arbitrary Python objects from the YAML stream, including those that can execute code upon instantiation. If an attacker can inject a specially crafted YAML payload into the cache and the application later deserializes this data usingYAMLSerializer
, the malicious YAML can trigger arbitrary code execution on the server.
- File:
-
Security Test Case:
- Set up a Django project and install the
django-redis-cache
library. - Configure the Django cache settings in
settings.py
to useredis_cache.RedisCache
withYAMLSerializer
:
CACHES = { 'default': { 'BACKEND': 'redis_cache.RedisCache', 'LOCATION': '127.0.0.1:6381', # Or your Redis server location 'OPTIONS': { 'SERIALIZER_CLASS': 'redis_cache.serializers.YAMLSerializer' }, } }
- Create a Django view in
tests/views.py
(or any suitable app) to retrieve and deserialize a cache key:
from django.core.cache import caches from django.http import HttpResponse def vulnerable_view(request): cache = caches['default'] key = 'yaml_injection_test_key' value_from_cache = cache.get(key) return HttpResponse(f"Attempted deserialization. Check server for side effects.")
- Add a URL pattern for this view in
tests/urls.py
(or your app's urls.py):
from django.urls import path from . import views urlpatterns = [ path('vulnerable_yaml_view/', views.vulnerable_view, name='vulnerable_yaml_view'), ]
- Inject a malicious YAML payload into the Redis cache using
redis-cli
:
redis-cli -p 6381 # Adjust port if necessary SET yaml_injection_test_key '!!python/object/apply:os.system ["touch /tmp/pwned_by_yaml_deserialize"]'
- Access the vulnerable view in a web browser or using
curl
:http://your_django_host/vulnerable_yaml_view/
. - Check if the file
/tmp/pwned_by_yaml_deserialize
has been created on the server. Successful creation of this file indicates arbitrary code execution due to unsafe YAML deserialization, confirming the vulnerability.
Alternatively for test case from list 3:
- Modify the test settings file (
/code/tests/settings.py
) to configure the default cache to useYAMLSerializer
as described in list 3 step 1. - Create a new test view in
/code/tests/views.py
to set and retrieve a malicious YAML payload in the cache as described in list 3 step 2. - Add these views to the test URLs in
/code/tests/urls.py
as described in list 3 step 3. - Run the Django test server (e.g., using
./tests/runtests.py
). - Access the
set_yaml/
URL in a browser or usingcurl
(e.g.,http://127.0.0.1:8000/set_yaml/
). This will set the malicious YAML payload in the cache. - Access the
get_data/
URL (e.g.,http://127.0.0.1:8000/get_data/
). This will retrieve and deserialize the YAML data from the cache. - Check if the file
/tmp/pwned
has been created on the server. If the file exists, it confirms that the malicious YAML payload was executed, demonstrating arbitrary code execution vulnerability. Expected result: After performing the test case steps, the file/tmp/pwned
should be created, indicating successful arbitrary code execution due to YAML deserialization vulnerability.
- Set up a Django project and install the
Insecure Deserialization via PickleSerializer
-
Description: An attacker who gains access to the Redis cache (for example by exploiting network misconfiguration or weak authentication) can inject a malicious pickle payload into the cache. When the application later reads this key using the default PickleSerializer, the untrusted data is deserialized with Python’s
pickle.loads()
without any integrity or type checks. Since pickle may execute arbitrary code during deserialization, this process can cause arbitrary code execution on the server. -
Impact: Arbitrary code execution on the host running the Django application. This can lead to a full compromise of the server, data theft, or further lateral movement within the network.
-
Vulnerability Rank: Critical
-
Currently Implemented Mitigations:
- The project provides alternative serializer classes (e.g., JSONSerializer, MSGPackSerializer, YAMLSerializer) that do not allow arbitrary code execution by design.
- However, by default the settings rely on the PickleSerializer when no override is provided.
-
Missing Mitigations:
- No built‑in safeguard is implemented around pickle deserialization to verify the integrity or authenticity of cached data.
- There is no strict enforcement (within the library) to prefer a safe serializer in public deployments.
-
Preconditions:
- The Redis instance must be accessible to external attackers (for example, because of misconfiguration or weak network access controls).
- The cache configuration is set to use the default PickleSerializer (or a configuration that enables it).
-
Source Code Analysis:
- In
/code/redis_cache/serializers.py
, thePickleSerializer
defines:serialize(self, value)
→ usespickle.dumps(value, self.pickle_version)
.deserialize(self, value)
→ directly callspickle.loads(force_bytes(value))
.
- In
/code/redis_cache/backends/base.py
, when a cache lookup is performed (for example, via theget()
orget_or_set()
methods), the retrieved raw value is processed byget_value()
, which internally callsself.deserialize(value)
. - There is no additional validation or integrity check over the serialized data, so if an attacker injects a crafted pickle payload into Redis, it will be deserialized without any protection.
- In
-
Security Test Case:
- Deploy the application in a test environment using the default settings (which use PickleSerializer).
- Reconfigure the Redis instance temporarily so that it is accessible on an external interface (or simulate attacker access via an open network channel) and note that its weak password is in use.
- Using a Redis client (for example, via
redis-cli
), connect to the Redis server at the configured location (e.g. 127.0.0.1:6381) with the password “yadayada”. - Prepare and set a key with a malicious pickle payload. (For testing purposes, use a payload that triggers a benign action such as writing a marker file or toggling a debug flag.)
– For example, set the key
malicious_key
to a pickle‑serialized payload that, when deserialized, executes a controlled script. - In the application, trigger code that issues a cache lookup on the key (e.g. via a view that calls
cache.get('malicious_key')
). - Observe that the malicious payload is executed (for instance, the marker file is created), confirming arbitrary code execution via deserialization.
Weak Default Redis Authentication
-
Description: The project’s configuration (especially in test settings such as in
/code/tests/settings.py
) hardcodes a weak Redis password (“yadayada”). If the same configuration is deployed (or if production settings are mis‐configured using these defaults) and the Redis instance is exposed to external networks, an attacker can connect to Redis using this password. Once connected, the attacker may read or write data to the cache, alter cached application data, or inject malicious payloads (which, when combined with the insecure deserialization issue, can lead to further compromise). -
Impact: Unauthorized access to the caching backend can result in cache poisoning, leakage of sensitive application data, and may even pave the way toward arbitrary code execution.
-
Vulnerability Rank: High
-
Currently Implemented Mitigations:
- A password is specified in the cache configuration; however, the chosen password (“yadayada”) is weak and predictable.
-
Missing Mitigations:
- There is no mechanism enforcing the use of strong, randomly generated passwords.
- No network-level access controls (such as firewall restrictions) are integrated into the project’s configuration to protect the Redis instance from exposure to untrusted networks.
-
Preconditions:
- The Redis instance is deployed using the provided configuration with the weak password.
- The Redis server is accessible from external networks (e.g. due to misconfiguration or overly permissive firewall settings).
-
Source Code Analysis:
- In
/code/tests/settings.py
(as well as in other test case configuration files), the cache configuration underOPTIONS
includes:"PASSWORD": "yadayada"
.
- In
/code/redis_cache/connection.py
, when establishing connections to Redis, this password is passed directly (via the keyword arguments to the connection pool) without any additional strengthening or verification.
- In
-
Security Test Case:
- Deploy the application (or a test instance of the application) using the provided configuration.
- From an external network (or simulate external access), use a Redis client tool (for instance,
redis-cli
) to connect to the Redis instance at the configured address (e.g. 127.0.0.1:6381). - Authenticate using the password “yadayada” and verify that the authentication succeeds.
- Issue basic Redis commands (such as GET, SET, and KEYS) to demonstrate that the attacker can view and modify cache data.
- Document the successful unauthorized access as confirmation of the vulnerability.
Hardcoded Weak Django SECRET_KEY
-
Description: In
/code/tests/settings.py
the Django settingSECRET_KEY
is hardcoded as “shh...it's a seakret”. If this test configuration (or a similarly weak key) is inadvertently deployed in production, the predictable and publicly known secret key will compromise Django’s cryptographic signing. An attacker can use the known secret to forge session cookies, CSRF tokens, or other signed data, which may lead to session hijacking or other types of attacks against the web application. -
Impact: The compromise of the Django secret key can result in session hijacking, authentication bypass, and CSRF attacks—all of which can lead to unauthorized access or data manipulation in the application.
-
Vulnerability Rank: High
-
Currently Implemented Mitigations:
- The hardcoded key appears only in the test settings. It is assumed that production deployments will override this value.
-
Missing Mitigations:
- There is no built‑in measure to enforce the use of a strong, unpredictable secret key.
- No warning or check exists within the library code to prevent accidental deployment of a weak key.
-
Preconditions:
- The application uses the test configuration (or any configuration with a similarly weak, hardcoded key) in production.
- An attacker is able to craft or modify signed cookies or tokens using the known secret key.
-
Source Code Analysis:
- In
/code/tests/settings.py
, the setting:SECRET_KEY = "shh...it's a seakret"
is defined without any randomness or obfuscation.
- As Django relies on this key for signing session cookies, CSRF tokens, and other security‑critical data, any disclosure or use of this key in production inherently undermines the application’s security.
- In
-
Security Test Case:
- Deploy the Django application using the test settings containing the hardcoded secret key.
- Using the known secret, an attacker can forge a session cookie (or CSRF token) that appears valid to the application.
- Submit requests with the forged cookie to access authenticated endpoints or perform state‑changing operations.
- Verify that the application accepts the forged tokens and grants access or performs unintended actions, confirming that the hardcoded key leads to exploitable weakness.