fscan/Plugins/services/ftp/connector.go
ZacharyZcR 83afd0f994 feat: 实现FTP文件传输协议专业扫描插件
• 新增FTP插件支持标准21端口和常见替代端口
• 实现匿名访问检测和弱密码爆破功能
• 支持自动利用:目录枚举、文件下载测试、文件上传测试
• 集成-nobr模式服务识别和-ne自动利用功能
• 完整的Context超时机制和连接数管理
• 添加中英文国际化消息支持
• 基于新插件架构实现模块化设计

功能特性:
- 支持jlaffaye/ftp驱动的FTP协议通信
- 智能识别vsFTPd、ProFTPD等多种FTP服务器
- 三种利用方法:目录结构探测、文件操作测试
- 完整的错误处理和连接限制处理机制
2025-08-08 04:46:35 +08:00

116 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package ftp
import (
"context"
"fmt"
"time"
ftplib "github.com/jlaffaye/ftp"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/plugins/base"
)
// FTPConnector FTP连接器实现
type FTPConnector struct {
host string
port string
}
// NewFTPConnector 创建FTP连接器
func NewFTPConnector() *FTPConnector {
return &FTPConnector{}
}
// Connect 连接到FTP服务
func (c *FTPConnector) Connect(ctx context.Context, info *common.HostInfo) (interface{}, error) {
c.host = info.Host
c.port = info.Ports
// 构建连接地址
target := fmt.Sprintf("%s:%s", c.host, c.port)
// 创建FTP连接配置
config := &FTPConfig{
Target: target,
Timeout: time.Duration(common.Timeout) * time.Second,
}
return config, nil
}
// Authenticate 认证
func (c *FTPConnector) Authenticate(ctx context.Context, conn interface{}, cred *base.Credential) error {
config, ok := conn.(*FTPConfig)
if !ok {
return fmt.Errorf("无效的连接类型")
}
// 在goroutine中建立FTP连接支持Context取消
resultChan := make(chan struct {
ftpConn *ftplib.ServerConn
err error
}, 1)
go func() {
ftpConn, err := ftplib.DialTimeout(config.Target, config.Timeout)
select {
case <-ctx.Done():
if ftpConn != nil {
ftpConn.Quit()
}
case resultChan <- struct {
ftpConn *ftplib.ServerConn
err error
}{ftpConn, err}:
}
}()
// 等待连接结果或Context取消
var ftpConn *ftplib.ServerConn
var err error
select {
case result := <-resultChan:
ftpConn, err = result.ftpConn, result.err
if err != nil {
return fmt.Errorf("FTP连接失败: %v", err)
}
case <-ctx.Done():
return fmt.Errorf("FTP连接超时: %v", ctx.Err())
}
defer ftpConn.Quit()
// 在goroutine中进行登录认证
loginChan := make(chan error, 1)
go func() {
err := ftpConn.Login(cred.Username, cred.Password)
select {
case <-ctx.Done():
case loginChan <- err:
}
}()
// 等待登录结果或Context取消
select {
case err := <-loginChan:
if err != nil {
return fmt.Errorf("FTP认证失败: %v", err)
}
return nil
case <-ctx.Done():
return fmt.Errorf("FTP认证超时: %v", ctx.Err())
}
}
// Close 关闭连接
func (c *FTPConnector) Close(conn interface{}) error {
// FTP配置无需显式关闭
return nil
}
// FTPConfig FTP连接配置
type FTPConfig struct {
Target string
Timeout time.Duration
}