fscan/Plugins/base/exploiter.go
ZacharyZcR 43f210ffc6 feat: 实现新一代插件注册系统完全替代传统手动注册模式
- 重构插件注册架构采用现代工厂模式和自动发现机制
- 新增完整的插件元数据管理系统支持版本能力标签等信息
- 实现智能插件适配器提供向后兼容的桥接功能
- 建立MySQL Redis SSH三个标准插件作为新架构参考实现
- 优化插件扫描逻辑支持按端口按类型的智能查询和过滤
- 添加国际化支持和完善的文档体系
- 代码量减少67%维护成本大幅降低扩展性显著提升

新架构特点:
- 零配置插件注册import即用
- 工厂模式延迟初始化和依赖注入
- 丰富元数据系统和能力声明
- 完全解耦的模块化设计
- 面向未来的可扩展架构

测试验证: MySQL和Redis插件功能完整包括弱密码检测未授权访问检测和自动利用攻击
2025-08-07 11:28:34 +08:00

246 lines
7.1 KiB
Go

package base
import (
"context"
"fmt"
"github.com/shadow1ng/fscan/common"
"sort"
)
// =============================================================================
// 通用利用器基础实现
// =============================================================================
// BaseExploiter 基础利用器,提供通用的利用逻辑
type BaseExploiter struct {
Name string
exploitMethods []ExploitMethod
}
// NewBaseExploiter 创建基础利用器
func NewBaseExploiter(name string) *BaseExploiter {
return &BaseExploiter{
Name: name,
exploitMethods: make([]ExploitMethod, 0),
}
}
// AddExploitMethod 添加利用方法
func (e *BaseExploiter) AddExploitMethod(method ExploitMethod) {
e.exploitMethods = append(e.exploitMethods, method)
// 按优先级排序
sort.Slice(e.exploitMethods, func(i, j int) bool {
return e.exploitMethods[i].Priority > e.exploitMethods[j].Priority
})
}
// GetExploitMethods 获取支持的利用方法
func (e *BaseExploiter) GetExploitMethods() []ExploitMethod {
return e.exploitMethods
}
// IsExploitSupported 检查是否支持指定的利用方法
func (e *BaseExploiter) IsExploitSupported(exploitType ExploitType) bool {
for _, method := range e.exploitMethods {
if method.Type == exploitType {
return true
}
}
return false
}
// Exploit 执行利用操作
func (e *BaseExploiter) Exploit(ctx context.Context, info *common.HostInfo, creds *Credential) (*ExploitResult, error) {
// 按优先级尝试不同的利用方法
for _, method := range e.exploitMethods {
// 检查前置条件
if !e.checkConditions(method.Conditions, info, creds) {
common.LogDebug(fmt.Sprintf("利用方法 %s 前置条件不满足,跳过", method.Name))
continue
}
common.LogDebug(fmt.Sprintf("尝试利用方法: %s", method.Name))
// 执行利用
result, err := method.Handler(ctx, info, creds)
if err != nil {
common.LogError(fmt.Sprintf("利用方法 %s 执行失败: %v", method.Name, err))
continue
}
if result != nil && result.Success {
common.LogSuccess(fmt.Sprintf("利用方法 %s 执行成功", method.Name))
result.Type = method.Type
result.Method = method.Name
return result, nil
}
}
return nil, fmt.Errorf("所有利用方法都失败")
}
// checkConditions 检查前置条件
func (e *BaseExploiter) checkConditions(conditions []string, info *common.HostInfo, creds *Credential) bool {
for _, condition := range conditions {
if !e.evaluateCondition(condition, info, creds) {
return false
}
}
return true
}
// evaluateCondition 评估单个条件
func (e *BaseExploiter) evaluateCondition(condition string, info *common.HostInfo, creds *Credential) bool {
switch condition {
case "has_credentials":
return creds != nil && (creds.Username != "" || creds.Password != "")
case "has_username_password":
return creds != nil && creds.Username != "" && creds.Password != ""
case "has_password_only":
return creds != nil && creds.Password != "" && creds.Username == ""
case "unauthorized_access":
return creds == nil || (creds.Username == "" && creds.Password == "")
default:
// 默认条件满足
return true
}
}
// =============================================================================
// 常用利用方法实现
// =============================================================================
// ExploitMethodBuilder 利用方法构建器
type ExploitMethodBuilder struct {
method ExploitMethod
}
// NewExploitMethod 创建利用方法构建器
func NewExploitMethod(exploitType ExploitType, name string) *ExploitMethodBuilder {
return &ExploitMethodBuilder{
method: ExploitMethod{
Type: exploitType,
Name: name,
Priority: 5, // 默认优先级
Conditions: make([]string, 0),
},
}
}
// WithDescription 设置描述
func (b *ExploitMethodBuilder) WithDescription(desc string) *ExploitMethodBuilder {
b.method.Description = desc
return b
}
// WithPriority 设置优先级
func (b *ExploitMethodBuilder) WithPriority(priority int) *ExploitMethodBuilder {
b.method.Priority = priority
return b
}
// WithConditions 设置前置条件
func (b *ExploitMethodBuilder) WithConditions(conditions ...string) *ExploitMethodBuilder {
b.method.Conditions = conditions
return b
}
// WithHandler 设置处理函数
func (b *ExploitMethodBuilder) WithHandler(handler ExploitHandler) *ExploitMethodBuilder {
b.method.Handler = handler
return b
}
// Build 构建利用方法
func (b *ExploitMethodBuilder) Build() ExploitMethod {
return b.method
}
// =============================================================================
// 利用结果处理工具
// =============================================================================
// SaveExploitResult 保存利用结果
func SaveExploitResult(info *common.HostInfo, result *ExploitResult, pluginName string) {
if result == nil || !result.Success {
return
}
target := fmt.Sprintf("%s:%d", info.Host, info.Ports)
var message string
switch result.Type {
case ExploitWeakPassword:
message = fmt.Sprintf("%s %s 弱密码利用成功", pluginName, target)
case ExploitUnauthorized:
message = fmt.Sprintf("%s %s 未授权访问利用成功", pluginName, target)
case ExploitCommandExec:
message = fmt.Sprintf("%s %s 命令执行利用成功", pluginName, target)
case ExploitFileWrite:
message = fmt.Sprintf("%s %s 文件写入利用成功", pluginName, target)
case ExploitSQLInjection:
message = fmt.Sprintf("%s %s SQL注入利用成功", pluginName, target)
default:
message = fmt.Sprintf("%s %s %s 利用成功", pluginName, target, result.Type)
}
if result.Output != "" {
message += fmt.Sprintf(" 输出: %s", result.Output)
}
common.LogSuccess(message)
// 保存文件信息
if len(result.Files) > 0 {
common.LogSuccess(fmt.Sprintf("创建/修改的文件: %v", result.Files))
}
// 保存Shell信息
if result.Shell != nil {
common.LogSuccess(fmt.Sprintf("获得Shell: %s %s:%d 用户:%s",
result.Shell.Type, result.Shell.Host, result.Shell.Port, result.Shell.User))
}
}
// =============================================================================
// 常用利用工具函数
// =============================================================================
// CreateSuccessExploitResult 创建成功的利用结果
func CreateSuccessExploitResult(exploitType ExploitType, method string) *ExploitResult {
return &ExploitResult{
Success: true,
Type: exploitType,
Method: method,
Extra: make(map[string]interface{}),
}
}
// CreateFailedExploitResult 创建失败的利用结果
func CreateFailedExploitResult(exploitType ExploitType, method string, err error) *ExploitResult {
return &ExploitResult{
Success: false,
Type: exploitType,
Method: method,
Error: err,
Extra: make(map[string]interface{}),
}
}
// AddOutputToResult 向结果添加输出
func AddOutputToResult(result *ExploitResult, output string) {
if result.Output == "" {
result.Output = output
} else {
result.Output += "\n" + output
}
}
// AddFileToResult 向结果添加文件
func AddFileToResult(result *ExploitResult, filename string) {
if result.Files == nil {
result.Files = make([]string, 0)
}
result.Files = append(result.Files, filename)
}