fscan/plugins/services/smbghost.go
ZacharyZcR 8f54702c02 refactor: 精准修复插件系统三个设计问题
经Linus式架构审计,发现并修复插件系统中的具体问题:

## 核心修复

### 1. 消除local插件GetPorts()方法冗余
- 删除21个local插件中无意义的GetPorts()方法
- 简化local.Plugin接口:移除端口概念
- 理由:本地插件不涉及网络,端口概念完全多余

### 2. 消除web插件GetPorts()方法冗余
- 删除2个web插件中无用的GetPorts()方法
- 简化web.WebPlugin接口:专注智能HTTP检测
- 理由:Web插件使用动态HTTP检测,预定义端口无价值

### 3. 统一插件命名规范
- 统一所有插件接口使用Name()方法(符合Go惯例)
- 消除GetName()与Name()不一致问题
- 简化适配器:不再需要方法名转换

## 技术改进

接口精简:
- local插件:GetName() + GetPorts() → Name()
- web插件:GetName() + GetPorts() → Name()
- services插件:GetName() → Name()(保留GetPorts(),业务必需)

代码减少:
- 删除23个无用GetPorts()方法
- 重命名52个Name()方法
- 简化3个插件接口定义

## 影响范围

修改文件:55个插件文件
代码变更:-155行 +61行(净减少94行)
功能影响:零破坏性,保持所有业务逻辑不变

这是基于业务需求分析的精准重构,消除真正多余的部分,
保持系统架构合理性和向后兼容性。
2025-08-26 20:38:39 +08:00

266 lines
6.2 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 services
import (
"bytes"
"context"
"fmt"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
)
// SmbGhostPlugin CVE-2020-0796 SMB Ghost漏洞检测插件
type SmbGhostPlugin struct {
name string
ports []int
}
// SMB Ghost 检测数据包
const smbGhostPacket = "\x00" + // session
"\x00\x00\xc0" + // length
"\xfeSMB@\x00" + // protocol
//[MS-SMB2]: SMB2 NEGOTIATE Request
//https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e14db7ff-763a-4263-8b10-0c3944f52fc5
"\x00\x00" +
"\x00\x00" +
"\x00\x00" +
"\x00\x00" +
"\x1f\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
// [MS-SMB2]: SMB2 NEGOTIATE_CONTEXT
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/15332256-522e-4a53-8cd7-0bd17678a2f7
"$\x00" +
"\x08\x00" +
"\x01\x00" +
"\x00\x00" +
"\x7f\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"x\x00" +
"\x00\x00" +
"\x02\x00" +
"\x00\x00" +
"\x02\x02" +
"\x10\x02" +
"\x22\x02" +
"$\x02" +
"\x00\x03" +
"\x02\x03" +
"\x10\x03" +
"\x11\x03" +
"\x00\x00\x00\x00" +
// [MS-SMB2]: SMB2_PREAUTH_INTEGRITY_CAPABILITIES
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/5a07bd66-4734-4af8-abcf-5a44ff7ee0e5
"\x01\x00" +
"&\x00" +
"\x00\x00\x00\x00" +
"\x01\x00" +
"\x20\x00" +
"\x01\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00" +
// [MS-SMB2]: SMB2_COMPRESSION_CAPABILITIES
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/78e0c942-ab41-472b-b117-4a95ebe88271
"\x03\x00" +
"\x0e\x00" +
"\x00\x00\x00\x00" +
"\x01\x00" + //CompressionAlgorithmCount
"\x00\x00" +
"\x01\x00\x00\x00" +
"\x01\x00" + //LZNT1
"\x00\x00" +
"\x00\x00\x00\x00"
// NewSmbGhostPlugin 创建SMB Ghost插件
func NewSmbGhostPlugin() *SmbGhostPlugin {
return &SmbGhostPlugin{
name: "smbghost",
ports: []int{445},
}
}
// GetName 实现Plugin接口
func (p *SmbGhostPlugin) Name() string {
return p.name
}
// GetPorts 实现Plugin接口
func (p *SmbGhostPlugin) GetPorts() []int {
return p.ports
}
// Scan 执行SMB Ghost漏洞检测
func (p *SmbGhostPlugin) Scan(ctx context.Context, info *common.HostInfo) *ScanResult {
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
// 检查端口
if info.Ports != "445" {
return &ScanResult{
Success: false,
Service: "smbghost",
Error: fmt.Errorf("SMB Ghost插件仅支持445端口"),
}
}
// 执行漏洞检测
vulnerable, err := p.detectVulnerability(ctx, info)
if err != nil {
return &ScanResult{
Success: false,
Service: "smbghost",
Error: fmt.Errorf("检测失败: %v", err),
}
}
if vulnerable {
common.LogSuccess(fmt.Sprintf("SMB Ghost %s CVE-2020-0796 漏洞存在", target))
return &ScanResult{
Success: true,
Service: "smbghost",
Banner: "CVE-2020-0796 SMB Ghost漏洞",
}
}
return &ScanResult{
Success: false,
Service: "smbghost",
Error: fmt.Errorf("未发现CVE-2020-0796漏洞"),
}
}
// detectVulnerability 检测SMB Ghost漏洞
func (p *SmbGhostPlugin) detectVulnerability(ctx context.Context, info *common.HostInfo) (bool, error) {
addr := fmt.Sprintf("%s:445", info.Host)
timeout := time.Duration(common.Timeout) * time.Second
// 建立TCP连接
conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout)
if err != nil {
return false, fmt.Errorf("连接失败: %v", err)
}
defer conn.Close()
// 设置连接超时
if err = conn.SetDeadline(time.Now().Add(timeout)); err != nil {
return false, fmt.Errorf("设置超时失败: %v", err)
}
// 发送SMB Ghost检测数据包
if _, err = conn.Write([]byte(smbGhostPacket)); err != nil {
return false, fmt.Errorf("发送数据包失败: %v", err)
}
// 读取响应
buff := make([]byte, 1024)
n, err := conn.Read(buff)
if err != nil || n == 0 {
return false, fmt.Errorf("读取响应失败: %v", err)
}
// 分析响应检测CVE-2020-0796特征
// 检查条件:
// 1. 响应包含"Public"字符串
// 2. 响应长度大于等于76字节
// 3. 特征字节匹配 (0x11,0x03) 和 (0x02,0x00)
if bytes.Contains(buff[:n], []byte("Public")) &&
len(buff[:n]) >= 76 &&
bytes.Equal(buff[72:74], []byte{0x11, 0x03}) &&
bytes.Equal(buff[74:76], []byte{0x02, 0x00}) {
return true, nil
}
return false, nil
}
// gatherSystemInfo 收集系统信息
func (p *SmbGhostPlugin) gatherSystemInfo(ctx context.Context, info *common.HostInfo) string {
addr := fmt.Sprintf("%s:445", info.Host)
timeout := time.Duration(common.Timeout) * time.Second
conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout)
if err != nil {
return ""
}
defer conn.Close()
// 发送标准SMB协商请求获取系统信息
negotiateReq := []byte{
0x00, 0x00, 0x00, 0x85,
0xfe, 0x53, 0x4d, 0x42, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x24, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x02,
0x22, 0x02, 0x24, 0x02, 0x00, 0x03, 0x02, 0x03,
0x10, 0x03, 0x11, 0x03,
}
conn.SetDeadline(time.Now().Add(timeout))
conn.Write(negotiateReq)
buff := make([]byte, 1024)
n, err := conn.Read(buff)
if err != nil || n < 65 {
return ""
}
var sysInfo strings.Builder
sysInfo.WriteString("SMB服务检测成功\n")
// 解析SMB版本
if n >= 72 {
dialect := uint16(buff[70]) | uint16(buff[71])<<8
switch dialect {
case 0x0311:
sysInfo.WriteString("SMB版本: 3.1.1 (存在CVE-2020-0796风险)\n")
case 0x0302:
sysInfo.WriteString("SMB版本: 3.0.2\n")
case 0x0300:
sysInfo.WriteString("SMB版本: 3.0.0\n")
default:
sysInfo.WriteString(fmt.Sprintf("SMB版本: 未知 (0x%04x)\n", dialect))
}
}
return sysInfo.String()
}
// init 自动注册插件
func init() {
// 使用高效注册方式:直接传递端口信息,避免实例创建
RegisterPluginWithPorts("smbghost", func() Plugin {
return NewSmbGhostPlugin()
}, []int{445})
}