flask读mem获取secret_key
flask读mem获取secret_key
secret_key用于作为密钥对会话数据进行加密,flask session的伪造需要先获得secret_key。
前两点为普通的session伪造,最后一点为读mem获取secret_key
①明文secret_key
题目源码里直接给出了secret_key,只需要用flask-session-cookie-manager伪造即可
例题:[HCTF 2018]admin (BUU)
②不安全的随机数secret_key
题目用于生成secret_key的随机数函数是不安全的,可预测
例题:[CISCN2019 华东南赛区]Web4 (BUU)
题目中的key生成部分代码如下
1 |
|
uuid.getnode()获取的是sys/class/net/eth0/address中的MAC地址转十进制的值
对于伪随机数,如果seed
是固定的,生成的随机数是可以预测的,也就是顺序固定的。
所以只要本地使用一样的seed生成随机数即可获得secret_key
安全随机数有哪些
编程语言 | 安全随机数 | 备注 |
---|---|---|
C/C++ | CryptGenRandom(Windows) libsodium,randombytes_buf() | 原理:依据当前进程ID、当前线程ID、当前时间、用户名、计算机名、CPU计数器等,生成随机数,和/dev/random一样,效率低,消耗资源大 |
.NET(C#) | System.Security.Cryptography.RNGCryptoServiceProvider | 原理:和CryptGenRandom(Windows)类似 |
Perl | Math::Random::Secure | 原理:所使用的种子种类繁多,且是随机使用的,攻击者可能要费劲10多年才能遍历完成 |
Python | os.urandom random.SystemRandom() | 原理:函数返回的随机字节,是操作系统所带的随机函数产生,具有特异性这里”urandom”里”u”应该指的是”unexpected”–难以预料 |
Ruby | Sysrandom(取代SecureRandom) | 适用于生成session token原理:使用/dev/urandom |
JAVA | java.security.SecureRandom | 原理:提供加密强度高的随机数生成器,默认条件下(不传其他种子的话,默认种子来源是/dev/random,但是存在熵耗尽导致阻塞的现象),就可以产生安全的随机数;解决熵值耗尽的方法要不就是不断增加熵值,要不就种子来源换成/dev/urandom |
PHP | mcrypt_create_iv, openssl_random_pseudo_bytes,random_bytes,random_int | 原理:random_bytes/random_int – 不同系统上,源头不同,Windows上使用CryptGenRandom,Linux上使用getrandom(2)或/dev/urandom |
GNU/Linux或Unix | 读取/dev/random or /dev/urandom | 4.3讲的很清楚了 |
不安全的随机数
编程语言 | 弱伪随机数 | 备注 |
C/C++ | srand( time() ) + rand() | 以时间为种子,产生随机数 |
C# | Random() System.Guid() | |
Perl | srand( time() ) + rand() | 以时间为种子,产生随机数 |
Python | import numpy rng = numpy.random.RandomState( time() ) array_rand_num = rng.uniform() ————————— import random random.seed() | |
Ruby | srand( time() ) + rand() | 以时间为种子,产生随机数 |
JAVA | Random | |
PHP | srand() + rand() mtstrand() + mtrand() |
③secret_key具有特征字符串
secret_key是生成的随机数,且不可预测,但是拼接了字符串
例题:[Nepnep-catCTF2022] catcat
题目中生成secret_key的部分代码如下
1 |
|
后面拼接了一个*abcdefgh
python存储对象的位置在堆上,flask对象自然也在,这里的secret_key又在app.config[‘SECRET_KEY’]里。所以可以通过读取内存内容获得secret_key,读取/proc/self/mem
就可以得到进程的内存内容。
但是不能直接读,/proc/self/mem内容较多而且存在不可读写部分(未被映射的区域),直接读取会导致程序崩溃。
/proc/self/maps文件的内容为内存代码段基址,应该结合/proc/self/maps得到当前进程的内存映射关系来确定读的偏移值。
只有读取的偏移值是被映射的区域才能正确读取内存内容。
正确读取mem后,在mem里找secret_key即可。(前面的题按理来说也行,但是mem里面乱七八糟的字符串有点多,不好找。
poc:
1 |
|
参考
000.【Web安全】你所使用的随机数真的安全吗? - 残夜悠悠伴我心 - 博客园 (cnblogs.com)
/proc/self/ - 简书 (jianshu.com)
(´∇`) 被你发现啦~ 攻防世界 x Nepnep x CATCTF 2022 Nepnep战队官方WP | xia0ji233’s blog