move plugin safety metadata to registry

This commit is contained in:
ZacharyZcR
2026-05-18 15:57:18 +08:00
parent d4ed0867c9
commit 3dde0c6a8e
5 changed files with 52 additions and 32 deletions
+1 -30
View File
@@ -50,29 +50,6 @@ var defaultSafePlugins = []string{
"webtitle", "webtitle",
} }
var unsafePlugins = map[string]struct{}{
"cleaner": {},
"crontask": {},
"download": {},
"forwardshell": {},
"keylogger": {},
"ldpreload": {},
"minidump": {},
"reverseshell": {},
"socks5proxy": {},
"sshkey": {},
"systemdservice": {},
"winbits": {},
"winifeo": {},
"winlogon": {},
"winregistry": {},
"winschtask": {},
"winservice": {},
"winstartup": {},
"winwmi": {},
"webpoc": {},
}
// Scanner runs fscan from another Go process. // Scanner runs fscan from another Go process.
type Scanner struct { type Scanner struct {
config Config config Config
@@ -134,13 +111,7 @@ func IsSafePlugin(name string) bool {
if name == "" || !plugins.Exists(name) { if name == "" || !plugins.Exists(name) {
return false return false
} }
if plugins.HasType(name, plugins.PluginTypeLocal) { return plugins.IsSafe(name)
return false
}
if _, bad := unsafePlugins[name]; bad {
return false
}
return true
} }
// Scan runs the scanner for the provided targets and returns structured // Scan runs the scanner for the provided targets and returns structured
+10
View File
@@ -111,6 +111,16 @@ func TestListPlugins(t *testing.T) {
if _, ok := GetPlugin("definitely-missing"); ok { if _, ok := GetPlugin("definitely-missing"); ok {
t.Fatal("unknown plugin should not exist") t.Fatal("unknown plugin should not exist")
} }
webpoc, ok := GetPlugin("webpoc")
if !ok {
t.Fatal("missing webpoc plugin")
}
if webpoc.Safe {
t.Fatal("webpoc should be marked unsafe")
}
if !containsString(webpoc.Types, PluginTypeWeb) {
t.Fatalf("webpoc types = %#v, want web", webpoc.Types)
}
} }
func TestScanHonorsCanceledContext(t *testing.T) { func TestScanHonorsCanceledContext(t *testing.T) {
+33 -1
View File
@@ -43,7 +43,7 @@ const (
type Result struct { type Result struct {
Type ResultType Type ResultType
Success bool Success bool
Skipped bool // 扫描被跳过,不应输出结果 Skipped bool // 扫描被跳过,不应输出结果
Service string Service string
Username string Username string
Password string Password string
@@ -84,6 +84,7 @@ type PluginInfo struct {
factory func() Plugin factory func() Plugin
ports []int ports []int
types []string // 插件类型标签 types []string // 插件类型标签
safe bool // 是否适合默认嵌入式扫描
} }
// 插件类型常量 // 插件类型常量
@@ -123,12 +124,23 @@ func RegisterWithPorts(name string, factory func() Plugin, ports []int) {
// RegisterWithTypes 注册带类型标签的插件 // RegisterWithTypes 注册带类型标签的插件
func RegisterWithTypes(name string, factory func() Plugin, ports []int, types []string) { func RegisterWithTypes(name string, factory func() Plugin, ports []int, types []string) {
RegisterWithOptions(name, factory, ports, types, !hasPluginType(types, PluginTypeLocal))
}
// RegisterUnsafeWithTypes 注册不适合默认嵌入式扫描的插件。
func RegisterUnsafeWithTypes(name string, factory func() Plugin, ports []int, types []string) {
RegisterWithOptions(name, factory, ports, types, false)
}
// RegisterWithOptions 注册带完整元数据的插件。
func RegisterWithOptions(name string, factory func() Plugin, ports []int, types []string, safe bool) {
mutex.Lock() mutex.Lock()
defer mutex.Unlock() defer mutex.Unlock()
plugins[name] = &PluginInfo{ plugins[name] = &PluginInfo{
factory: factory, factory: factory,
ports: ports, ports: ports,
types: types, types: types,
safe: safe,
} }
} }
@@ -147,6 +159,17 @@ func HasType(pluginName string, typeName string) bool {
return false return false
} }
// IsSafe 检查插件是否适合默认嵌入式扫描。
func IsSafe(pluginName string) bool {
mutex.RLock()
defer mutex.RUnlock()
if info, exists := plugins[pluginName]; exists {
return info.safe
}
return false
}
// Get 获取插件实例 // Get 获取插件实例
func Get(name string) Plugin { func Get(name string) Plugin {
mutex.RLock() mutex.RLock()
@@ -190,6 +213,15 @@ func GetPluginPorts(name string) []int {
return []int{} // 返回空列表表示适用于所有端口 return []int{} // 返回空列表表示适用于所有端口
} }
func hasPluginType(types []string, typeName string) bool {
for _, t := range types {
if t == typeName {
return true
}
}
return false
}
// GenerateCredentials 生成测试凭据 // GenerateCredentials 生成测试凭据
func GenerateCredentials(service string, config *common.Config) []Credential { func GenerateCredentials(service string, config *common.Config) []Credential {
var credentials []Credential var credentials []Credential
+7
View File
@@ -22,3 +22,10 @@ func RegisterWebPlugin(name string, creator func() WebPlugin) {
return creator() return creator()
}, []int{}, []string{plugins.PluginTypeWeb}) }, []int{}, []string{plugins.PluginTypeWeb})
} }
// RegisterUnsafeWebPlugin 注册需要显式授权的主动Web插件。
func RegisterUnsafeWebPlugin(name string, creator func() WebPlugin) {
plugins.RegisterUnsafeWithTypes(name, func() plugins.Plugin {
return creator()
}, []int{}, []string{plugins.PluginTypeWeb})
}
+1 -1
View File
@@ -130,7 +130,7 @@ func matchCDNorWAF(fingerprints []string) string {
// init 自动注册插件 // init 自动注册插件
func init() { func init() {
RegisterWebPlugin("webpoc", func() WebPlugin { RegisterUnsafeWebPlugin("webpoc", func() WebPlugin {
return NewWebPocPlugin() return NewWebPocPlugin()
}) })
} }