mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 05:56:46 +08:00

• 新增FTP插件支持标准21端口和常见替代端口 • 实现匿名访问检测和弱密码爆破功能 • 支持自动利用:目录枚举、文件下载测试、文件上传测试 • 集成-nobr模式服务识别和-ne自动利用功能 • 完整的Context超时机制和连接数管理 • 添加中英文国际化消息支持 • 基于新插件架构实现模块化设计 功能特性: - 支持jlaffaye/ftp驱动的FTP协议通信 - 智能识别vsFTPd、ProFTPD等多种FTP服务器 - 三种利用方法:目录结构探测、文件操作测试 - 完整的错误处理和连接限制处理机制
116 lines
2.3 KiB
Go
116 lines
2.3 KiB
Go
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
|
||
} |