mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00

- 重构插件注册架构采用现代工厂模式和自动发现机制 - 新增完整的插件元数据管理系统支持版本能力标签等信息 - 实现智能插件适配器提供向后兼容的桥接功能 - 建立MySQL Redis SSH三个标准插件作为新架构参考实现 - 优化插件扫描逻辑支持按端口按类型的智能查询和过滤 - 添加国际化支持和完善的文档体系 - 代码量减少67%维护成本大幅降低扩展性显著提升 新架构特点: - 零配置插件注册import即用 - 工厂模式延迟初始化和依赖注入 - 丰富元数据系统和能力声明 - 完全解耦的模块化设计 - 面向未来的可扩展架构 测试验证: MySQL和Redis插件功能完整包括弱密码检测未授权访问检测和自动利用攻击
9.9 KiB
9.9 KiB
Fscan 插件架构最佳实践
插件系统设计原则
1. 接口统一性
所有插件必须遵循 base.Plugin
接口规范,确保:
- 统一的初始化流程
- 标准化的扫描接口
- 一致的错误处理
- 规范的结果返回
2. 模块化设计
插件采用分层架构:
Plugin (业务逻辑层)
↓
ServicePlugin (服务抽象层)
↓
ServiceConnector (连接实现层)
3. 关注点分离
- Connector: 专注网络连接和认证
- Plugin: 专注业务逻辑和工作流
- Exploiter: 专注安全利用和攻击
代码质量标准
1. 命名规范
包命名
// 服务插件包名使用小写服务名
package mysql
package redis
package postgres
结构体命名
// 连接器使用[Service]Connector格式
type MySQLConnector struct {}
type RedisConnector struct {}
// 插件使用[Service]Plugin格式
type MySQLPlugin struct {}
type RedisPlugin struct {}
// 利用器使用[Service]Exploiter格式
type MySQLExploiter struct {}
type RedisExploiter struct {}
方法命名
// 工厂函数使用New[Type]格式
func NewMySQLConnector() *MySQLConnector
func NewMySQLPlugin() *MySQLPlugin
// 注册函数使用Register[Service]Plugin格式
func RegisterMySQLPlugin()
2. 注释标准
包级别注释
// MySQL插件:新一代插件架构的完整实现示例
// 展示了如何正确实现服务扫描、凭据爆破、自动利用等功能
// 本插件可作为其他数据库插件迁移的标准参考模板
结构体注释
// MySQLConnector 实现MySQL数据库服务连接器
// 遵循 base.ServiceConnector 接口规范,提供标准化的MySQL连接和认证功能
type MySQLConnector struct {
timeout time.Duration // 连接超时时间
host string // 目标主机地址
port int // 目标端口号
}
方法注释
// NewMySQLConnector 创建新的MySQL连接器实例
// 自动注册SOCKS代理支持,配置适当的超时时间
func NewMySQLConnector() *MySQLConnector {}
// Authenticate 使用凭据对MySQL服务进行身份认证
// 实现 base.ServiceConnector 接口的 Authenticate 方法
// 关键优化:使用独立的Context避免上游超时问题
func (c *MySQLConnector) Authenticate(ctx context.Context, conn interface{}, cred *base.Credential) error {}
3. 错误处理
错误分类
// 网络连接错误
return fmt.Errorf("连接失败: %v", err)
// 认证失败错误
return fmt.Errorf("认证失败: %v", err)
// 配置错误
return fmt.Errorf("无效的端口号: %s", info.Ports)
错误日志
// Debug级别:详细信息,用于调试
common.LogDebug(fmt.Sprintf("MySQL尝试认证: %s@%s:%d", cred.Username, c.host, c.port))
// Error级别:错误信息,用于排查问题
common.LogError("MySQL插件新架构不可用,请检查插件注册")
// Success级别:成功信息,用户可见
common.LogSuccess(i18n.GetText("mysql_scan_success", target, cred.Username, cred.Password))
性能优化指导
1. Context管理
问题:上游Context超时
新架构中传递的Context可能存在超时问题,导致认证立即失败。
解决方案:独立Context
func (c *Connector) Authenticate(ctx context.Context, conn interface{}, cred *base.Credential) error {
// 创建独立的超时上下文,避免上游Context超时问题
// 这是解决新架构Context传递问题的关键修复
timeout := time.Duration(common.Timeout) * time.Second
authCtx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
// 使用authCtx进行所有操作
}
2. 连接池管理
合理的连接池配置
// 设置合理的连接生命周期
db.SetConnMaxLifetime(c.timeout)
db.SetConnMaxIdleTime(c.timeout)
db.SetMaxIdleConns(0) // 对于扫描工具,不保持空闲连接
3. 内存管理
及时释放资源
defer db.Close() // 数据库连接
defer conn.Close() // 网络连接
defer cancel() // Context取消
避免内存泄露
// 使用有限大小的channel
resultChan := make(chan Result, 1)
// 确保goroutine正确退出
select {
case result := <-resultChan:
return result
case <-ctx.Done():
return ctx.Err()
}
国际化实践
1. 消息定义
标准消息格式
var PluginMessages = map[string]map[string]string{
"mysql_scan_success": {
LangZH: "MySQL弱密码扫描成功: %s [%s:%s]",
LangEN: "MySQL weak password scan successful: %s [%s:%s]",
},
"mysql_auth_failed": {
LangZH: "MySQL认证失败: %s",
LangEN: "MySQL authentication failed: %s",
},
}
消息使用
// 在插件中使用i18n消息
common.LogSuccess(i18n.GetText("mysql_scan_success", target, username, password))
common.LogError(i18n.GetText("mysql_auth_failed", err.Error()))
2. 参数占位符
使用标准的printf格式化占位符:
%s
- 字符串%d
- 整数%v
- 任意类型
安全考虑
1. 敏感信息处理
日志安全
// 错误:在生产日志中输出密码
common.LogInfo(fmt.Sprintf("尝试密码: %s", password))
// 正确:在debug日志中输出,生产环境可关闭
common.LogDebug(fmt.Sprintf("尝试密码: %s", password))
内存安全
// 使用完毕后清理敏感数据
defer func() {
if password != "" {
password = ""
}
}()
2. 网络安全
超时控制
// 设置合理的超时时间,避免DoS
timeout := time.Duration(common.Timeout) * time.Second
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
连接复用
// 避免过多的并发连接
db.SetMaxOpenConns(1) // 对于扫描工具限制并发连接
扩展性设计
1. 插件能力声明
标准能力集
plugin.SetCapabilities([]base.Capability{
base.CapWeakPassword, // 弱密码检测
base.CapUnauthorized, // 未授权访问检测
base.CapDataExtraction, // 数据提取
base.CapFileWrite, // 文件写入
base.CapCommandExecution, // 命令执行
base.CapSQLInjection, // SQL注入
base.CapInformationLeak, // 信息泄露
})
2. 自定义扫描逻辑
重写Scan方法
// 重写扫描方法实现自定义逻辑(如未授权访问检测)
func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) {
// 先检查未授权访问
if result := p.checkUnauthorizedAccess(ctx, info); result != nil {
return result, nil
}
// 再执行标准弱密码扫描
return p.ServicePlugin.Scan(ctx, info)
}
3. 利用模块集成
可选的利用功能
// 自动利用功能(可通过-nobr参数禁用)
if result.Success && len(result.Credentials) > 0 && !common.DisableBrute {
// 异步执行利用攻击,避免阻塞扫描进程
go p.autoExploit(context.Background(), info, result.Credentials[0])
}
测试策略
1. 单元测试
连接器测试
func TestMySQLConnector_Connect(t *testing.T) {
connector := NewMySQLConnector()
info := &common.HostInfo{
Host: "127.0.0.1",
Ports: "3306",
}
conn, err := connector.Connect(context.Background(), info)
if err != nil {
t.Errorf("Connect failed: %v", err)
}
defer connector.Close(conn)
}
认证测试
func TestMySQLConnector_Authenticate(t *testing.T) {
// 测试正确凭据
cred := &base.Credential{Username: "root", Password: "123456"}
err := connector.Authenticate(context.Background(), conn, cred)
if err != nil {
t.Errorf("Authentication failed: %v", err)
}
// 测试错误凭据
invalidCred := &base.Credential{Username: "invalid", Password: "invalid"}
err = connector.Authenticate(context.Background(), conn, invalidCred)
if err == nil {
t.Error("Expected authentication to fail")
}
}
2. 集成测试
完整扫描流程
func TestMySQLPlugin_FullScan(t *testing.T) {
plugin := NewMySQLPlugin()
info := &common.HostInfo{
Host: "127.0.0.1",
Ports: "3306",
}
result, err := plugin.Scan(context.Background(), info)
if err != nil {
t.Errorf("Scan failed: %v", err)
}
if !result.Success {
t.Error("Expected scan to succeed")
}
}
3. 性能测试
并发扫描测试
func BenchmarkMySQLPlugin_Scan(b *testing.B) {
plugin := NewMySQLPlugin()
info := &common.HostInfo{Host: "127.0.0.1", Ports: "3306"}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
plugin.Scan(context.Background(), info)
}
})
}
部署检查清单
1. 代码质量
- 所有公共方法都有文档注释
- 错误处理完整且合理
- 无明显的内存泄露风险
- 遵循Go代码规范
2. 功能完整性
- 基础连接功能正常
- 认证逻辑正确实现
- 错误场景处理完善
- 国际化消息完整
3. 性能表现
- 超时控制合理
- 并发性能良好
- 资源使用合理
- 无性能瓶颈
4. 安全性
- 不在日志中暴露敏感信息
- 超时控制防止DoS
- 输入验证充分
- 权限控制适当
5. 兼容性
- 支持SOCKS代理
- 与老版本行为兼容
- 多语言环境工作正常
- 跨平台兼容性
维护指南
1. 版本管理
- 使用语义化版本号
- 在元数据中更新版本信息
- 维护变更日志
2. 文档更新
- 同步更新代码注释
- 更新用户使用文档
- 维护最佳实践文档
3. 社区贡献
- 遵循项目贡献指南
- 提供清晰的PR描述
- 包含必要的测试用例
通过遵循这些最佳实践,可以确保插件的质量、性能和可维护性,为fscan项目提供稳定可靠的插件支持。