CVE-2020-10594
📋 TL;DR
This vulnerability in drf-jwt 1.15.x allows attackers with access to a blacklisted or invalidated JWT token to obtain a new, valid token through the refresh endpoint. The blacklist protection mechanism fails to properly validate tokens during refresh operations, enabling authentication bypass. This affects any system using the vulnerable drf-jwt library for Django REST Framework authentication.
💻 Affected Systems
- drf-jwt (Styria-Digital fork of django-rest-framework-jwt)
📦 What is this software?
⚠️ Risk & Real-World Impact
Worst Case
Complete authentication bypass allowing attackers to impersonate any user, access sensitive data, and perform unauthorized actions as authenticated users.
Likely Case
Attackers with stolen or previously valid tokens can maintain persistent access to user accounts even after token revocation.
If Mitigated
Limited impact with proper token expiration policies and additional authentication layers, though refresh functionality remains compromised.
🎯 Exploit Status
Exploitation requires access to a previously valid token (stolen, leaked, or otherwise obtained). The vulnerability is well-documented in GitHub issues with technical details.
🛠️ Fix & Mitigation
✅ Official Fix
Patch Version: 1.15.1
Vendor Advisory: https://github.com/Styria-Digital/django-rest-framework-jwt/issues/36
Restart Required: Yes
Instructions:
1. Update drf-jwt package: pip install drf-jwt==1.15.1
2. Restart Django application
3. Verify blacklist protection works with token refresh
🔧 Temporary Workarounds
Disable token refresh endpoint
allTemporarily disable JWT token refresh functionality until patching is possible
# In Django settings.py or JWT configuration
JWT_AUTH = {
'JWT_ALLOW_REFRESH': False,
# Other JWT settings...
}
Implement custom token refresh validation
allAdd middleware or custom view to validate blacklisted tokens before refresh
# Custom refresh view example
from rest_framework_jwt.views import refresh_jwt_token
from rest_framework_jwt.blacklist.models import BlacklistedToken
class SecureRefreshView(refresh_jwt_token):
def post(self, request, *args, **kwargs):
token = request.data.get('token')
if BlacklistedToken.objects.filter(token=token).exists():
return Response({'error': 'Token blacklisted'}, status=400)
return super().post(request, *args, **kwargs)
🧯 If You Can't Patch
- Disable JWT token refresh functionality entirely in application configuration
- Implement additional authentication checks (MFA, IP restrictions) for sensitive operations
🔍 How to Verify
Check if Vulnerable:
Check installed drf-jwt version: pip show drf-jwt | grep Version. If version is 1.15.0 or earlier 1.15.x, system is vulnerable.
Check Version:
pip show drf-jwt | grep Version
Verify Fix Applied:
1. Verify version is 1.15.1 or higher
2. Test that blacklisted tokens cannot be refreshed
3. Validate refresh endpoint returns error for invalidated tokens
📡 Detection & Monitoring
Log Indicators:
- Multiple refresh attempts with same token
- Refresh requests succeeding after token invalidation
- Unusual refresh patterns from single user
Network Indicators:
- HTTP POST requests to /api-token-refresh/ endpoint with previously used tokens
- Refresh token reuse patterns
SIEM Query:
source="django" AND (url_path="/api-token-refresh/" OR message="token refresh") AND status=200 | stats count by src_ip, user
🔗 References
- https://github.com/Styria-Digital/django-rest-framework-jwt/issues/36
- https://github.com/jpadilla/django-rest-framework-jwt/issues/484
- https://pypi.org/project/drf-jwt/1.15.1/#history
- https://github.com/Styria-Digital/django-rest-framework-jwt/issues/36
- https://github.com/jpadilla/django-rest-framework-jwt/issues/484
- https://pypi.org/project/drf-jwt/1.15.1/#history