fscan/Plugins/services/neo4j/plugin.go
ZacharyZcR dc8579f554 feat: 实现Neo4j图数据库专业扫描插件
- 新增Neo4j Bolt协议识别和弱密码检测
- 支持未授权访问和默认凭据检测
- 实现ServiceConnector三层架构模式
- 添加Neo4j专用国际化消息
- 支持7474/7687端口扫描
- 自动注册到插件系统
2025-08-09 11:57:35 +08:00

244 lines
6.7 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 neo4j
import (
"context"
"fmt"
"strings"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/common/i18n"
"github.com/shadow1ng/fscan/plugins/base"
)
// Neo4jPlugin Neo4j插件实现
type Neo4jPlugin struct {
*base.ServicePlugin
exploiter *Neo4jExploiter
}
// NewNeo4jPlugin 创建Neo4j插件
func NewNeo4jPlugin() *Neo4jPlugin {
// 插件元数据
metadata := &base.PluginMetadata{
Name: "neo4j",
Version: "2.0.0",
Author: "fscan-team",
Description: "Neo4j图数据库扫描和利用插件",
Category: "service",
Ports: []int{7474, 7687}, // Neo4j HTTP端口和Bolt端口
Protocols: []string{"tcp", "bolt"},
Tags: []string{"neo4j", "graph-database", "database", "weak-password", "unauthorized"},
}
// 创建连接器和服务插件
connector := NewNeo4jConnector()
servicePlugin := base.NewServicePlugin(metadata, connector)
// 创建Neo4j插件
plugin := &Neo4jPlugin{
ServicePlugin: servicePlugin,
exploiter: NewNeo4jExploiter(),
}
// 设置能力
plugin.SetCapabilities([]base.Capability{
base.CapWeakPassword,
base.CapUnauthorized,
base.CapDataExtraction,
})
return plugin
}
// Scan 重写扫描方法进行Neo4j服务扫描
func (p *Neo4jPlugin) 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)
// 先检查未授权访问
unauthCred := &base.Credential{Username: "", Password: ""}
result, err := p.ScanCredential(ctx, info, unauthCred)
if err == nil && result.Success {
// 未授权访问成功
common.LogSuccess(i18n.GetText("neo4j_unauth_access", target))
return &base.ScanResult{
Success: true,
Service: "Neo4j",
Credentials: []*base.Credential{unauthCred},
Banner: result.Banner,
Extra: map[string]interface{}{
"service": "Neo4j",
"port": info.Ports,
"unauthorized": true,
"access_type": "no_authentication",
},
}, nil
}
// 检查默认凭据
defaultCred := &base.Credential{Username: "neo4j", Password: "neo4j"}
result, err = p.ScanCredential(ctx, info, defaultCred)
if err == nil && result.Success {
// 默认凭据成功
common.LogSuccess(i18n.GetText("neo4j_default_creds", target, defaultCred.Username, defaultCred.Password))
return &base.ScanResult{
Success: true,
Service: "Neo4j",
Credentials: []*base.Credential{defaultCred},
Banner: result.Banner,
Extra: map[string]interface{}{
"service": "Neo4j",
"port": info.Ports,
"username": defaultCred.Username,
"password": defaultCred.Password,
"type": "default-credentials",
},
}, nil
}
// 生成凭据进行暴力破解
credentials := p.generateCredentials()
// 遍历凭据进行测试
for _, cred := range credentials {
result, err := p.ScanCredential(ctx, info, cred)
if err == nil && result.Success {
// 认证成功
common.LogSuccess(i18n.GetText("neo4j_auth_success", target, cred.Username, cred.Password))
return &base.ScanResult{
Success: true,
Service: "Neo4j",
Credentials: []*base.Credential{cred},
Banner: result.Banner,
Extra: map[string]interface{}{
"service": "Neo4j",
"port": info.Ports,
"username": cred.Username,
"password": cred.Password,
"type": "weak-password",
},
}, nil
}
}
// 所有凭据都失败但可能识别到了Neo4j服务
return p.performServiceIdentification(ctx, info)
}
// generateCredentials 生成Neo4j凭据
func (p *Neo4jPlugin) generateCredentials() []*base.Credential {
var credentials []*base.Credential
// 获取Neo4j用户名字典
usernames := common.Userdict["neo4j"]
if len(usernames) == 0 {
usernames = []string{"neo4j", "admin", "administrator", "root"}
}
// 获取密码字典
passwords := common.Passwords
if len(passwords) == 0 {
passwords = []string{"", "neo4j", "admin", "password", "123456", "root"}
}
// 生成用户名密码组合
for _, username := range usernames {
for _, password := range passwords {
// 替换密码中的用户名占位符
actualPassword := strings.Replace(password, "{user}", username, -1)
credentials = append(credentials, &base.Credential{
Username: username,
Password: actualPassword,
})
}
}
return credentials
}
// Exploit 使用exploiter执行利用
func (p *Neo4jPlugin) Exploit(ctx context.Context, info *common.HostInfo, creds *base.Credential) (*base.ExploitResult, error) {
return p.exploiter.Exploit(ctx, info, creds)
}
// GetExploitMethods 获取利用方法
func (p *Neo4jPlugin) GetExploitMethods() []base.ExploitMethod {
return p.exploiter.GetExploitMethods()
}
// IsExploitSupported 检查利用支持
func (p *Neo4jPlugin) IsExploitSupported(method base.ExploitType) bool {
return p.exploiter.IsExploitSupported(method)
}
// performServiceIdentification 执行Neo4j服务识别-nobr模式
func (p *Neo4jPlugin) performServiceIdentification(ctx context.Context, info *common.HostInfo) (*base.ScanResult, error) {
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
// 尝试识别Neo4j服务
connector := NewNeo4jConnector()
conn, err := connector.Connect(ctx, info)
if err == nil && conn != nil {
if neo4jConn, ok := conn.(*Neo4jConnection); ok {
// 记录服务识别成功
common.LogSuccess(i18n.GetText("neo4j_service_identified", target, neo4jConn.info))
connector.Close(conn)
return &base.ScanResult{
Success: true,
Service: "Neo4j",
Banner: neo4jConn.info,
Extra: map[string]interface{}{
"service": "Neo4j",
"port": info.Ports,
"info": neo4jConn.info,
},
}, nil
}
}
// 如果无法识别为Neo4j返回失败
return &base.ScanResult{
Success: false,
Error: fmt.Errorf("无法识别为Neo4j服务"),
}, nil
}
// =============================================================================
// 插件注册
// =============================================================================
// RegisterNeo4jPlugin 注册Neo4j插件
func RegisterNeo4jPlugin() {
factory := base.NewSimplePluginFactory(
&base.PluginMetadata{
Name: "neo4j",
Version: "2.0.0",
Author: "fscan-team",
Description: "Neo4j图数据库扫描和利用插件",
Category: "service",
Ports: []int{7474, 7687}, // Neo4j HTTP端口和Bolt端口
Protocols: []string{"tcp", "bolt"},
Tags: []string{"neo4j", "graph-database", "database", "weak-password", "unauthorized"},
},
func() base.Plugin {
return NewNeo4jPlugin()
},
)
base.GlobalPluginRegistry.Register("neo4j", factory)
}
// 自动注册
func init() {
RegisterNeo4jPlugin()
}