"多引擎"的资产识别、信息收集工具
字数 1750 2025-08-22 12:23:12
ScopeSentry插件系统开发指南
1. 插件系统概述
ScopeSentry的插件系统允许用户集成各种安全工具,实现"多引擎"的资产识别和信息收集功能。通过插件系统可以:
- 集成指纹识别工具(如EHole)
- 对收集到的数据进行二次处理
- 丰富资产标签信息
- 对特定参数进行专项测试
2. 系统模块架构
插件系统将整个流程分为13个模块:
- TargetHandler - 目标处理
- SubdomainScan - 子域名扫描
- SubdomainSecurity - 子域名安全检查
- AssetMapping - 资产映射
- PortScanPreparation - 端口扫描准备
- PortScan - 端口扫描
- PortFingerprint - 端口指纹识别
- AssetHandle - 资产处理
- URLScan - URL扫描
- URLSecurity - URL安全检查
- WebCrawler - 网页爬虫
- DirScan - 目录扫描
- VulnerabilityScan - 漏洞扫描
3. 插件开发基础
3.1 插件模板结构
插件模板可从GitHub获取:
git clone https://github.com/Autumn-27/ScopeSentry-Plugin-Template.git
模板中提供了两个模块的demo:
- AssetHandle模块示例
- SubdomainScan模块示例
3.2 插件文件结构
每个插件需要包含两个文件:
info.json- 插件元信息plugin.go- 插件实现代码
info.json示例
{
"help": "参数提示信息",
"parameter": "参数",
"name": "插件名称",
"module": "模块(需要准确)",
"version": "版本",
"introduction": "插件的简介"
}
plugin.go基本结构
package plugin
func GetName() string {
return ""
}
func Install() error {
return nil
}
func Check() error {
return nil
}
func Uninstall() error {
return nil
}
func Execute(input interface{}, op options.PluginOption) (interface{}, error) {
return nil, nil
}
4. 插件开发详解
4.1 插件生命周期方法
- GetName() - 返回插件名称,必须与info.json中的name一致
- Install() - 插件安装时执行,可用于下载依赖文件
- Check() - 安装后执行,用于验证插件环境
- Uninstall() - 插件卸载时执行
- Execute() - 插件核心执行逻辑
4.2 Execute方法详解
Execute方法接收两个参数:
input interface{}- 输入数据op options.PluginOption- 插件选项
PluginOption结构
type PluginOption struct {
Name string
Module string
Parameter string
PluginId string
ResultFunc func(interface{})
Custom interface{}
TaskId string
TaskName string
Log func(msg string, tp ...string)
Ctx context.Context
}
4.3 参数处理
参数可以使用{}引用字典和端口:
{dict.subdomain.default}- 引用字典{port.top1000}- 引用端口组
参数解析示例:
args, err := utils.Tools.ParseArgs(parameter, "cdncheck", "screenshot")
if err != nil {
// 错误处理
} else {
for key, value := range args {
if value != "" {
switch key {
case "cdncheck":
cdncheck = value
case "screenshot":
if value == "true" {
screenshot = true
}
default:
continue
}
}
}
}
4.4 模块输入输出
- AssetHandle、PortScanPreparation、PortFingerprint模块:input为引用,直接修改input即可
- 其他模块:通过
op.ResultFunc回调函数返回结果
5. 内置工具包
插件可以调用的内置包:
github.com/Autumn-27/ScopeSentry-Scan/pkg/logger- 日志github.com/Autumn-27/ScopeSentry-Scan/pkg/utils- 工具包(DNS、Request等)github.com/Autumn-27/ScopeSentry-Scan/internal/bigcache- 缓存github.com/Autumn-27/ScopeSentry-Scan/internal/mongodb- MongoDB连接github.com/Autumn-27/ScopeSentry-Scan/internal/redis- Redis连接github.com/Autumn-27/ScopeSentry-Scan/internal/pool- 协程池管理
6. EHole插件实现示例
6.1 核心代码结构
package plugin
import (
"encoding/json"
"fmt"
"github.com/Autumn-27/ScopeSentry-Scan/internal/global"
"github.com/Autumn-27/ScopeSentry-Scan/internal/options"
"github.com/Autumn-27/ScopeSentry-Scan/internal/types"
"github.com/Autumn-27/ScopeSentry-Scan/pkg/utils"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"
)
// 指纹结构体
type Fingerprints struct {
Fingerprint []Fingerprint
}
type Fingerprint struct {
Cms string
Method string
Location string
Keyword []string
}
// Execute方法实现
func Execute(input interface{}, op options.PluginOption) (interface{}, error) {
data, ok := input.(*types.AssetHttp)
if !ok {
return nil, nil
}
// 参数处理
parameter := op.Parameter
var filgerFile string
thread := 20
// 指纹文件加载
fingerFilePath := filepath.Join(global.DictPath, filgerFile)
content, err := os.ReadFile(fingerFilePath)
// 指纹匹配逻辑
var fingers Fingerprints
err = json.Unmarshal(content, &fingers)
// 并发处理
semaphore := make(chan struct{}, thread)
var wg sync.WaitGroup
uniqueCms := sync.Map{}
// 指纹匹配核心逻辑
for _, finp := range fingers.Fingerprint {
// 并发控制
semaphore <- struct{}{}
wg.Add(1)
go func(finger Fingerprint) {
defer func() {
<-semaphore
wg.Done()
}()
// 不同位置和方法的匹配逻辑
if finger.Location == "body" {
if finger.Method == "keyword" {
if iskeyword(data.ResponseBody, finger.Keyword) {
uniqueCms.Store(finger.Cms, true)
}
}
// 其他匹配方法...
}
// 其他位置匹配...
}(finp)
}
wg.Wait()
// 结果处理
var result []string
existingMap := make(map[string]bool)
// 合并原有技术栈
for _, v := range data.Technologies {
lowerV := strings.ToLower(v)
if _, exists := existingMap[lowerV]; !exists {
result = append(result, v)
existingMap[lowerV] = true
}
}
// 添加新识别的CMS
uniqueCms.Range(func(key, value interface{}) bool {
cms := key.(string)
lowerCms := strings.ToLower(cms)
if _, exists := existingMap[lowerCms]; !exists {
result = append(result, cms)
existingMap[lowerCms] = true
}
return true
})
data.Technologies = result
return nil, nil
}
6.2 关键匹配函数
// 关键词匹配
func iskeyword(str string, keyword []string) bool {
x := true
for _, k := range keyword {
if strings.Contains(str, k) {
x = x && true
} else {
x = x && false
}
}
return x
}
// 正则匹配
func isregular(str string, keyword []string) bool {
x := true
for _, k := range keyword {
re := regexp.MustCompile(k)
if re.Match([]byte(str)) {
x = x && true
} else {
x = x && false
}
}
return x
}
7. 插件调试方法
7.1 模拟环境测试
func TestEHole(plgPath string) {
plgId := utils.Tools.GenerateRandomString(8)
plgModule := "AssetHandle"
plgPath = filepath.Join(plgPath, "AssetHandle", "ehole", "plugin.go")
plugin, err := plugins.LoadCustomPlugin(plgPath, plgModule, plgId)
// 设置插件参数
plugin.SetParameter("-finger dwa -thread 20")
plugin.SetTaskId("1111")
plugin.SetTaskName("demo")
// 执行插件
_, err = plugin.Execute(&AssetHttpData)
}
7.2 直接调试模式
import (
plugin "github.com/Autumn-27/ScopeSentry-Scan/plugin/AssetHandle/ehole"
)
func TestEHoleDebug() {
op := options.PluginOption{
Name: "EHole",
Module: "AssetHandle",
Parameter: "-finger dwa -thread 20",
PluginId: "11111",
Ctx: contextmanager.GlobalContextManagers.GetContext("111111"),
}
plugin.Execute(&AssetHttpData, op)
}
8. 最佳实践
- 合理设置并发数:通过thread参数控制并发量
- 结果去重:使用sync.Map确保并发安全
- 错误处理:完善错误日志记录
- 参数验证:对输入参数进行严格验证
- 资源释放:确保所有资源在插件结束时正确释放
通过遵循这些指南,开发者可以高效地为ScopeSentry开发各种功能插件,扩展其资产识别和信息收集能力。