fscan/plugins/services/mongodb/plugin.go
ZacharyZcR 4a3f281b6b refactor: 统一Plugins目录大小写为小写
- 将所有Plugins路径重命名为plugins
- 修复Git索引与实际文件系统大小写不一致问题
- 确保跨平台兼容性和路径一致性
2025-08-12 13:08:06 +08:00

221 lines
6.0 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 mongodb
import (
"context"
"fmt"
"io"
"net"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/common/i18n"
"github.com/shadow1ng/fscan/plugins/base"
)
// MongoDBPlugin MongoDB插件实现
type MongoDBPlugin struct {
*base.ServicePlugin
exploiter *MongoDBExploiter
}
// NewMongoDBPlugin 创建MongoDB插件
func NewMongoDBPlugin() *MongoDBPlugin {
// 插件元数据
metadata := &base.PluginMetadata{
Name: "mongodb",
Version: "2.0.0",
Author: "fscan-team",
Description: "MongoDB NoSQL数据库扫描和利用插件",
Category: "service",
Ports: []int{27017, 27018, 27019}, // 默认MongoDB端口
Protocols: []string{"tcp"},
Tags: []string{"mongodb", "nosql", "database", "unauthorized"},
}
// 创建连接器和服务插件
connector := NewMongoDBConnector()
servicePlugin := base.NewServicePlugin(metadata, connector)
// 创建MongoDB插件
plugin := &MongoDBPlugin{
ServicePlugin: servicePlugin,
exploiter: NewMongoDBExploiter(),
}
// 设置能力
plugin.SetCapabilities([]base.Capability{
base.CapUnauthorized,
base.CapDataExtraction,
base.CapWeakPassword, // 将来可能支持弱密码扫描
})
return plugin
}
// Scan 重写扫描方法,检测未授权访问
func (p *MongoDBPlugin) Scan(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) {
// 如果禁用了暴力破解,只进行服务识别
if common.DisableBrute {
return p.performServiceIdentification(ctx, info)
}
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
// MongoDB主要检查未授权访问
unauthCred := &base.Credential{Username: "", Password: ""}
result, err := p.ScanCredential(ctx, info, unauthCred)
if err == nil && result.Success {
// 未授权访问成功
common.LogSuccess(i18n.GetText("mongodb_unauth_access", target))
return &base.ScanResult{
Success: true,
Service: "MongoDB",
Credentials: []*base.Credential{unauthCred},
Extra: map[string]interface{}{
"service": "MongoDB",
"port": info.Ports,
"unauthorized": true,
"access_type": "no_authentication",
},
}, nil
}
// 如果未授权访问失败,返回失败结果
return &base.ScanResult{
Success: false,
Error: fmt.Errorf("MongoDB服务需要认证或连接失败"),
}, nil
}
// 已移除未使用的 generateCredentials 方法
// Exploit 使用exploiter执行利用
func (p *MongoDBPlugin) Exploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) (*base.ExploitResult, error) {
return p.exploiter.Exploit(ctx, info, creds)
}
// GetExploitMethods 获取利用方法
func (p *MongoDBPlugin) GetExploitMethods() []base.ExploitMethod {
return p.exploiter.GetExploitMethods()
}
// IsExploitSupported 检查利用支持
func (p *MongoDBPlugin) IsExploitSupported(method base.ExploitType) bool {
return p.exploiter.IsExploitSupported(method)
}
// performServiceIdentification 执行MongoDB服务识别-nobr模式
func (p *MongoDBPlugin) performServiceIdentification(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) {
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
// 尝试识别MongoDB服务
mongoInfo, isMongo := p.identifyMongoDBService(ctx, info)
if isMongo {
// 记录服务识别成功
common.LogSuccess(i18n.GetText("mongodb_service_identified", target, mongoInfo))
return &base.ScanResult{
Success: true,
Service: "MongoDB",
Banner: mongoInfo,
Extra: map[string]interface{}{
"service": "MongoDB",
"port": info.Ports,
"info": mongoInfo,
},
}, nil
}
// 如果无法识别为MongoDB返回失败
return &base.ScanResult{
Success: false,
Error: fmt.Errorf("无法识别为MongoDB服务"),
}, nil
}
// identifyMongoDBService 通过协议识别MongoDB服务
func (p *MongoDBPlugin) identifyMongoDBService(ctx context.Context, info *common.HostInfo) (string, bool) {
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
timeout := time.Duration(common.Timeout) * time.Second
// 尝试建立TCP连接
conn, err := net.DialTimeout("tcp", target, timeout)
if err != nil {
return "", false
}
defer conn.Close()
// 设置操作超时
conn.SetDeadline(time.Now().Add(timeout))
// 尝试发送MongoDB查询来识别服务
msgPacket := createOpMsgPacket()
if _, err := conn.Write(msgPacket); err != nil {
return "", false
}
// 读取响应
reply := make([]byte, 1024)
n, err := conn.Read(reply)
if err != nil && err != io.EOF {
// 尝试OP_QUERY查询
queryPacket := createOpQueryPacket()
if _, err := conn.Write(queryPacket); err != nil {
return "", false
}
n, err = conn.Read(reply)
if err != nil && err != io.EOF {
return "", false
}
}
if n > 0 {
response := string(reply[:n])
// 检查是否包含MongoDB相关内容
if strings.Contains(response, "totalLinesWritten") ||
strings.Contains(response, "MongoDB") ||
strings.Contains(response, "WiredTiger") ||
strings.Contains(response, "unauthorized") {
// 尝试提取版本信息
if strings.Contains(response, "MongoDB") {
return "MongoDB服务 (已识别协议响应)", true
}
return "MongoDB服务", true
}
}
return "", false
}
// =============================================================================
// 插件注册
// =============================================================================
// RegisterMongoDBPlugin 注册MongoDB插件
func RegisterMongoDBPlugin() {
factory := base.NewSimplePluginFactory(
&base.PluginMetadata{
Name: "mongodb",
Version: "2.0.0",
Author: "fscan-team",
Description: "MongoDB NoSQL数据库扫描和利用插件",
Category: "service",
Ports: []int{27017, 27018, 27019}, // 默认MongoDB端口
Protocols: []string{"tcp"},
Tags: []string{"mongodb", "nosql", "database", "unauthorized"},
},
func() base.Plugin {
return NewMongoDBPlugin()
},
)
base.GlobalPluginRegistry.Register("mongodb", factory)
}
// 自动注册
func init() {
RegisterMongoDBPlugin()
}