mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-07-13 12:52:44 +08:00
feat: 分离结果输出和日志
This commit is contained in:
parent
c6c613a17b
commit
97e9ac7161
@ -847,7 +847,10 @@ var PortMap = map[int][]string{
|
||||
|
||||
var Passwords = []string{"123456", "admin", "admin123", "root", "", "pass123", "pass@123", "password", "Password", "P@ssword123", "123123", "654321", "111111", "123", "1", "admin@123", "Admin@123", "admin123!@#", "{user}", "{user}1", "{user}111", "{user}123", "{user}@123", "{user}_123", "{user}#123", "{user}@111", "{user}@2019", "{user}@123#4", "P@ssw0rd!", "P@ssw0rd", "Passw0rd", "qwe123", "12345678", "test", "test123", "123qwe", "123qwe!@#", "123456789", "123321", "666666", "a123456.", "123456~a", "123456!a", "000000", "1234567890", "8888888", "!QAZ2wsx", "1qaz2wsx", "abc123", "abc123456", "1qaz@WSX", "a11111", "a12345", "Aa1234", "Aa1234.", "Aa12345", "a123456", "a123123", "Aa123123", "Aa123456", "Aa12345.", "sysadmin", "system", "1qaz!QAZ", "2wsx@WSX", "qwe123!@#", "Aa123456!", "A123456s!", "sa123456", "1q2w3e", "Charge123", "Aa123456789", "elastic123"}
|
||||
|
||||
var Outputfile = "result.txt"
|
||||
var (
|
||||
Outputfile string // 输出文件路径
|
||||
OutputFormat string // 输出格式
|
||||
)
|
||||
|
||||
// 添加一个全局的进度条变量
|
||||
var ProgressBar *progressbar.ProgressBar
|
||||
|
@ -160,6 +160,7 @@ func Flag(Info *HostInfo) {
|
||||
|
||||
// 输出配置
|
||||
flag.StringVar(&Outputfile, "o", "result.txt", "指定结果输出文件名")
|
||||
flag.StringVar(&OutputFormat, "f", "txt", "指定输出格式 (txt/json/csv)")
|
||||
flag.BoolVar(&DisableSave, "no", false, "禁止保存扫描结果")
|
||||
flag.BoolVar(&Silent, "silent", false, "启用静默扫描模式(减少屏幕输出)")
|
||||
flag.BoolVar(&NoColor, "nocolor", false, "禁用彩色输出显示")
|
||||
|
274
Common/Log.go
274
Common/Log.go
@ -1,12 +1,9 @@
|
||||
package Common
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
@ -16,118 +13,123 @@ import (
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
// 全局变量定义
|
||||
var (
|
||||
// 全局变量
|
||||
// 扫描状态管理器,记录最近一次成功和错误的时间
|
||||
status = &ScanStatus{lastSuccess: time.Now(), lastError: time.Now()}
|
||||
|
||||
// 扫描计数
|
||||
Num int64 // 总任务数
|
||||
End int64 // 已完成任务数
|
||||
|
||||
// 文件写入器
|
||||
fileWriter *bufferedFileWriter
|
||||
// Num 表示待处理的总任务数量
|
||||
Num int64
|
||||
// End 表示已经完成的任务数量
|
||||
End int64
|
||||
)
|
||||
|
||||
// ScanStatus 记录扫描状态
|
||||
// ScanStatus 用于记录和管理扫描状态的结构体
|
||||
type ScanStatus struct {
|
||||
mu sync.RWMutex
|
||||
total int64
|
||||
completed int64
|
||||
lastSuccess time.Time
|
||||
lastError time.Time
|
||||
mu sync.RWMutex // 读写互斥锁,用于保护并发访问
|
||||
total int64 // 总任务数
|
||||
completed int64 // 已完成任务数
|
||||
lastSuccess time.Time // 最近一次成功的时间
|
||||
lastError time.Time // 最近一次错误的时间
|
||||
}
|
||||
|
||||
// LogEntry 日志条目
|
||||
// LogEntry 定义单条日志的结构
|
||||
type LogEntry struct {
|
||||
Level string // "ERROR", "INFO", "SUCCESS", "DEBUG"
|
||||
Time time.Time
|
||||
Content string
|
||||
Level string // 日志级别: ERROR/INFO/SUCCESS/DEBUG
|
||||
Time time.Time // 日志时间
|
||||
Content string // 日志内容
|
||||
}
|
||||
|
||||
// LogLevel 定义日志等级常量
|
||||
// 定义系统支持的日志级别常量
|
||||
const (
|
||||
LogLevelAll = "ALL" // 输出所有日志
|
||||
LogLevelError = "ERROR" // 错误日志
|
||||
LogLevelInfo = "INFO" // 信息日志
|
||||
LogLevelSuccess = "SUCCESS" // 成功日志
|
||||
LogLevelDebug = "DEBUG" // 调试日志
|
||||
LogLevelAll = "ALL" // 显示所有级别日志
|
||||
LogLevelError = "ERROR" // 仅显示错误日志
|
||||
LogLevelInfo = "INFO" // 仅显示信息日志
|
||||
LogLevelSuccess = "SUCCESS" // 仅显示成功日志
|
||||
LogLevelDebug = "DEBUG" // 仅显示调试日志
|
||||
)
|
||||
|
||||
// 定义日志颜色映射
|
||||
// 日志级别对应的显示颜色映射
|
||||
var logColors = map[string]color.Attribute{
|
||||
LogLevelError: color.FgRed,
|
||||
LogLevelInfo: color.FgYellow,
|
||||
LogLevelSuccess: color.FgGreen,
|
||||
LogLevelDebug: color.FgBlue,
|
||||
}
|
||||
|
||||
// JsonOutput JSON输出的结构体
|
||||
type JsonOutput struct {
|
||||
Level string `json:"level"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Message string `json:"message"`
|
||||
LogLevelError: color.FgRed, // 错误日志显示红色
|
||||
LogLevelInfo: color.FgYellow, // 信息日志显示黄色
|
||||
LogLevelSuccess: color.FgGreen, // 成功日志显示绿色
|
||||
LogLevelDebug: color.FgBlue, // 调试日志显示蓝色
|
||||
}
|
||||
|
||||
// InitLogger 初始化日志系统
|
||||
func InitLogger() {
|
||||
// 禁用标准日志输出
|
||||
log.SetOutput(io.Discard)
|
||||
if !DisableSave {
|
||||
fileWriter = newBufferedFileWriter()
|
||||
}
|
||||
}
|
||||
|
||||
// formatLogMessage 格式化日志消息
|
||||
// formatLogMessage 格式化日志消息为标准格式
|
||||
// 返回格式:[时间] [级别] 内容
|
||||
func formatLogMessage(entry *LogEntry) string {
|
||||
timeStr := entry.Time.Format("2006-01-02 15:04:05")
|
||||
return fmt.Sprintf("[%s] [%s] %s", timeStr, entry.Level, entry.Content)
|
||||
}
|
||||
|
||||
// 修改 printLog 函数
|
||||
// printLog 根据日志级别打印日志
|
||||
func printLog(entry *LogEntry) {
|
||||
// 默认情况(LogLevelInfo)下打印 INFO、SUCCESS、ERROR
|
||||
if LogLevel == LogLevelInfo {
|
||||
// 根据当前设置的日志级别过滤日志
|
||||
switch LogLevel {
|
||||
case LogLevelInfo:
|
||||
// INFO模式下只打印 INFO、SUCCESS、ERROR 级别的日志
|
||||
if entry.Level != LogLevelInfo &&
|
||||
entry.Level != LogLevelSuccess &&
|
||||
entry.Level != LogLevelError {
|
||||
return
|
||||
}
|
||||
} else if LogLevel == LogLevelDebug || LogLevel == LogLevelAll {
|
||||
// Debug或ALL模式打印所有日志
|
||||
} else if entry.Level != LogLevel {
|
||||
// 其他情况只打印指定等级的日志
|
||||
case LogLevelDebug, LogLevelAll:
|
||||
// Debug或ALL模式下打印所有日志
|
||||
default:
|
||||
// 其他模式下只打印指定级别的日志
|
||||
if entry.Level != LogLevel {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
OutputMutex.Lock()
|
||||
defer OutputMutex.Unlock()
|
||||
|
||||
// 确保清除当前进度条
|
||||
if ProgressBar != nil {
|
||||
ProgressBar.Clear()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
// 处理进度条
|
||||
clearAndWaitProgress()
|
||||
|
||||
// 打印日志
|
||||
// 打印日志消息
|
||||
logMsg := formatLogMessage(entry)
|
||||
if !NoColor {
|
||||
// 使用彩色输出
|
||||
if colorAttr, ok := logColors[entry.Level]; ok {
|
||||
color.New(colorAttr).Println(logMsg)
|
||||
} else {
|
||||
fmt.Println(logMsg)
|
||||
}
|
||||
} else {
|
||||
// 普通输出
|
||||
fmt.Println(logMsg)
|
||||
}
|
||||
|
||||
// 确保日志完全输出
|
||||
// 等待日志输出完成
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
|
||||
// 重新渲染进度条
|
||||
// 重新显示进度条
|
||||
if ProgressBar != nil {
|
||||
ProgressBar.RenderBlank()
|
||||
}
|
||||
}
|
||||
|
||||
// clearAndWaitProgress 清除进度条并等待
|
||||
func clearAndWaitProgress() {
|
||||
if ProgressBar != nil {
|
||||
ProgressBar.Clear()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
// LogError 记录错误日志,自动包含文件名和行号信息
|
||||
func LogError(errMsg string) {
|
||||
// 获取调用者的文件名和行号
|
||||
_, file, line, ok := runtime.Caller(1)
|
||||
if !ok {
|
||||
file = "unknown"
|
||||
@ -137,182 +139,60 @@ func LogError(errMsg string) {
|
||||
|
||||
errorMsg := fmt.Sprintf("%s:%d - %s", file, line, errMsg)
|
||||
|
||||
if ProgressBar != nil {
|
||||
ProgressBar.Clear()
|
||||
}
|
||||
|
||||
entry := &LogEntry{
|
||||
Level: LogLevelError,
|
||||
Time: time.Now(),
|
||||
Content: errorMsg,
|
||||
}
|
||||
|
||||
printLog(entry)
|
||||
if fileWriter != nil {
|
||||
fileWriter.write(entry)
|
||||
handleLog(entry)
|
||||
}
|
||||
|
||||
// handleLog 统一处理日志的输出
|
||||
func handleLog(entry *LogEntry) {
|
||||
if ProgressBar != nil {
|
||||
ProgressBar.Clear()
|
||||
}
|
||||
|
||||
printLog(entry)
|
||||
|
||||
if ProgressBar != nil {
|
||||
ProgressBar.RenderBlank()
|
||||
}
|
||||
}
|
||||
|
||||
// LogInfo 记录信息日志
|
||||
func LogInfo(msg string) {
|
||||
if ProgressBar != nil {
|
||||
ProgressBar.Clear()
|
||||
}
|
||||
|
||||
entry := &LogEntry{
|
||||
handleLog(&LogEntry{
|
||||
Level: LogLevelInfo,
|
||||
Time: time.Now(),
|
||||
Content: msg,
|
||||
})
|
||||
}
|
||||
|
||||
printLog(entry)
|
||||
if fileWriter != nil {
|
||||
fileWriter.write(entry)
|
||||
}
|
||||
|
||||
if ProgressBar != nil {
|
||||
ProgressBar.RenderBlank()
|
||||
}
|
||||
}
|
||||
|
||||
// LogSuccess 记录成功日志,并更新最后成功时间
|
||||
func LogSuccess(result string) {
|
||||
if ProgressBar != nil {
|
||||
ProgressBar.Clear()
|
||||
}
|
||||
|
||||
entry := &LogEntry{
|
||||
Level: LogLevelSuccess,
|
||||
Time: time.Now(),
|
||||
Content: result,
|
||||
}
|
||||
|
||||
printLog(entry)
|
||||
if fileWriter != nil {
|
||||
fileWriter.write(entry)
|
||||
}
|
||||
handleLog(entry)
|
||||
|
||||
// 更新最后成功时间
|
||||
status.mu.Lock()
|
||||
status.lastSuccess = time.Now()
|
||||
status.mu.Unlock()
|
||||
|
||||
if ProgressBar != nil {
|
||||
ProgressBar.RenderBlank()
|
||||
}
|
||||
}
|
||||
|
||||
// LogDebug 记录调试日志
|
||||
func LogDebug(msg string) {
|
||||
if ProgressBar != nil {
|
||||
ProgressBar.Clear()
|
||||
}
|
||||
|
||||
entry := &LogEntry{
|
||||
handleLog(&LogEntry{
|
||||
Level: LogLevelDebug,
|
||||
Time: time.Now(),
|
||||
Content: msg,
|
||||
}
|
||||
|
||||
printLog(entry)
|
||||
if fileWriter != nil {
|
||||
fileWriter.write(entry)
|
||||
}
|
||||
|
||||
if ProgressBar != nil {
|
||||
ProgressBar.RenderBlank()
|
||||
}
|
||||
}
|
||||
|
||||
func newBufferedFileWriter() *bufferedFileWriter {
|
||||
file, err := os.OpenFile(Outputfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
fmt.Printf("[ERROR] 打开输出文件失败 %s: %v\n", Outputfile, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
writer := bufio.NewWriter(file)
|
||||
return &bufferedFileWriter{
|
||||
file: file,
|
||||
writer: writer,
|
||||
jsonEnc: json.NewEncoder(writer),
|
||||
}
|
||||
}
|
||||
|
||||
type bufferedFileWriter struct {
|
||||
file *os.File
|
||||
writer *bufio.Writer
|
||||
jsonEnc *json.Encoder
|
||||
mu sync.Mutex // 添加互斥锁保护写入
|
||||
}
|
||||
|
||||
func (w *bufferedFileWriter) write(entry *LogEntry) {
|
||||
if w == nil {
|
||||
return
|
||||
}
|
||||
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
var err error
|
||||
if JsonFormat {
|
||||
output := JsonOutput{
|
||||
Level: entry.Level,
|
||||
Timestamp: entry.Time,
|
||||
Message: entry.Content,
|
||||
}
|
||||
err = w.jsonEnc.Encode(output)
|
||||
} else {
|
||||
logMsg := formatLogMessage(entry) + "\n"
|
||||
_, err = w.writer.WriteString(logMsg)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("[ERROR] 写入日志失败: %v\n", err)
|
||||
// 尝试重新打开文件
|
||||
if err := w.reopen(); err != nil {
|
||||
fmt.Printf("[ERROR] 重新打开文件失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 每隔一定数量的写入才进行一次Flush
|
||||
if err := w.writer.Flush(); err != nil {
|
||||
fmt.Printf("[ERROR] 刷新缓冲区失败: %v\n", err)
|
||||
if err := w.reopen(); err != nil {
|
||||
fmt.Printf("[ERROR] 重新打开文件失败: %v\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *bufferedFileWriter) reopen() error {
|
||||
if w.file != nil {
|
||||
w.file.Close()
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(Outputfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.file = file
|
||||
w.writer = bufio.NewWriter(file)
|
||||
w.jsonEnc = json.NewEncoder(w.writer)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *bufferedFileWriter) close() {
|
||||
if w != nil {
|
||||
w.writer.Flush()
|
||||
w.file.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func CloseLogger() {
|
||||
if fileWriter != nil {
|
||||
fileWriter.close()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// CheckErrs 检查是否为需要重试的错误
|
||||
|
247
Common/Output.go
Normal file
247
Common/Output.go
Normal file
@ -0,0 +1,247 @@
|
||||
// output.go
|
||||
|
||||
package Common
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 全局输出管理器
|
||||
var ResultOutput *OutputManager
|
||||
|
||||
// OutputManager 输出管理器结构体
|
||||
type OutputManager struct {
|
||||
mu sync.Mutex
|
||||
outputPath string
|
||||
outputFormat string
|
||||
file *os.File
|
||||
csvWriter *csv.Writer
|
||||
jsonEncoder *json.Encoder
|
||||
isInitialized bool
|
||||
}
|
||||
|
||||
// ResultType 定义结果类型
|
||||
type ResultType string
|
||||
|
||||
const (
|
||||
HOST ResultType = "HOST" // 主机存活
|
||||
PORT ResultType = "PORT" // 端口开放
|
||||
SERVICE ResultType = "SERVICE" // 服务识别
|
||||
VULN ResultType = "VULN" // 漏洞发现
|
||||
)
|
||||
|
||||
// ScanResult 扫描结果结构
|
||||
type ScanResult struct {
|
||||
Time time.Time `json:"time"` // 发现时间
|
||||
Type ResultType `json:"type"` // 结果类型
|
||||
Target string `json:"target"` // 目标(IP/域名/URL)
|
||||
Status string `json:"status"` // 状态描述
|
||||
Details map[string]interface{} `json:"details"` // 详细信息
|
||||
}
|
||||
|
||||
// InitOutput 初始化输出系统
|
||||
func InitOutput() error {
|
||||
LogDebug("开始初始化输出系统")
|
||||
|
||||
// 验证输出格式
|
||||
switch OutputFormat {
|
||||
case "txt", "json", "csv":
|
||||
// 有效的格式
|
||||
default:
|
||||
return fmt.Errorf("不支持的输出格式: %s", OutputFormat)
|
||||
}
|
||||
|
||||
// 验证输出路径
|
||||
if Outputfile == "" {
|
||||
return fmt.Errorf("输出文件路径不能为空")
|
||||
}
|
||||
|
||||
dir := filepath.Dir(Outputfile)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
LogDebug(fmt.Sprintf("创建输出目录失败: %v", err))
|
||||
return fmt.Errorf("创建输出目录失败: %v", err)
|
||||
}
|
||||
|
||||
manager := &OutputManager{
|
||||
outputPath: Outputfile,
|
||||
outputFormat: OutputFormat,
|
||||
}
|
||||
|
||||
if err := manager.initialize(); err != nil {
|
||||
LogDebug(fmt.Sprintf("初始化输出管理器失败: %v", err))
|
||||
return fmt.Errorf("初始化输出管理器失败: %v", err)
|
||||
}
|
||||
|
||||
ResultOutput = manager
|
||||
LogDebug("输出系统初始化完成")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (om *OutputManager) initialize() error {
|
||||
om.mu.Lock()
|
||||
defer om.mu.Unlock()
|
||||
|
||||
if om.isInitialized {
|
||||
LogDebug("输出管理器已经初始化,跳过")
|
||||
return nil
|
||||
}
|
||||
|
||||
LogDebug(fmt.Sprintf("正在打开输出文件: %s", om.outputPath))
|
||||
file, err := os.OpenFile(om.outputPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
LogDebug(fmt.Sprintf("打开输出文件失败: %v", err))
|
||||
return fmt.Errorf("打开输出文件失败: %v", err)
|
||||
}
|
||||
om.file = file
|
||||
|
||||
switch om.outputFormat {
|
||||
case "csv":
|
||||
LogDebug("初始化CSV写入器")
|
||||
om.csvWriter = csv.NewWriter(file)
|
||||
headers := []string{"Time", "Type", "Target", "Status", "Details"}
|
||||
if err := om.csvWriter.Write(headers); err != nil {
|
||||
LogDebug(fmt.Sprintf("写入CSV头失败: %v", err))
|
||||
file.Close()
|
||||
return fmt.Errorf("写入CSV头失败: %v", err)
|
||||
}
|
||||
om.csvWriter.Flush()
|
||||
case "json":
|
||||
LogDebug("初始化JSON编码器")
|
||||
om.jsonEncoder = json.NewEncoder(file)
|
||||
om.jsonEncoder.SetIndent("", " ")
|
||||
case "txt":
|
||||
LogDebug("初始化文本输出")
|
||||
default:
|
||||
LogDebug(fmt.Sprintf("不支持的输出格式: %s", om.outputFormat))
|
||||
}
|
||||
|
||||
om.isInitialized = true
|
||||
LogDebug("输出管理器初始化完成")
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveResult 保存扫描结果
|
||||
func SaveResult(result *ScanResult) error {
|
||||
if ResultOutput == nil {
|
||||
LogDebug("输出系统未初始化")
|
||||
return fmt.Errorf("输出系统未初始化")
|
||||
}
|
||||
|
||||
LogDebug(fmt.Sprintf("正在保存结果 - 类型: %s, 目标: %s", result.Type, result.Target))
|
||||
return ResultOutput.saveResult(result)
|
||||
}
|
||||
|
||||
func (om *OutputManager) saveResult(result *ScanResult) error {
|
||||
om.mu.Lock()
|
||||
defer om.mu.Unlock()
|
||||
|
||||
if !om.isInitialized {
|
||||
LogDebug("输出管理器未初始化")
|
||||
return fmt.Errorf("输出管理器未初始化")
|
||||
}
|
||||
|
||||
var err error
|
||||
switch om.outputFormat {
|
||||
case "txt":
|
||||
err = om.writeTxt(result)
|
||||
case "json":
|
||||
err = om.writeJson(result)
|
||||
case "csv":
|
||||
err = om.writeCsv(result)
|
||||
default:
|
||||
LogDebug(fmt.Sprintf("不支持的输出格式: %s", om.outputFormat))
|
||||
return fmt.Errorf("不支持的输出格式: %s", om.outputFormat)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
LogDebug(fmt.Sprintf("保存结果失败: %v", err))
|
||||
} else {
|
||||
LogDebug(fmt.Sprintf("成功保存结果 - 类型: %s, 目标: %s", result.Type, result.Target))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (om *OutputManager) writeTxt(result *ScanResult) error {
|
||||
// 格式化 Details 为键值对字符串
|
||||
var details string
|
||||
if len(result.Details) > 0 {
|
||||
pairs := make([]string, 0, len(result.Details))
|
||||
for k, v := range result.Details {
|
||||
pairs = append(pairs, fmt.Sprintf("%s=%v", k, v))
|
||||
}
|
||||
details = strings.Join(pairs, ", ")
|
||||
}
|
||||
|
||||
txt := fmt.Sprintf("[%s] [%s] Target: %s, Status: %s, Details: {%s}\n",
|
||||
result.Time.Format("2006-01-02 15:04:05"),
|
||||
result.Type,
|
||||
result.Target,
|
||||
result.Status,
|
||||
details,
|
||||
)
|
||||
_, err := om.file.WriteString(txt)
|
||||
return err
|
||||
}
|
||||
|
||||
func (om *OutputManager) writeJson(result *ScanResult) error {
|
||||
return om.jsonEncoder.Encode(result)
|
||||
}
|
||||
|
||||
func (om *OutputManager) writeCsv(result *ScanResult) error {
|
||||
details, err := json.Marshal(result.Details)
|
||||
if err != nil {
|
||||
details = []byte("{}")
|
||||
}
|
||||
|
||||
record := []string{
|
||||
result.Time.Format("2006-01-02 15:04:05"),
|
||||
string(result.Type),
|
||||
result.Target,
|
||||
result.Status,
|
||||
string(details),
|
||||
}
|
||||
|
||||
if err := om.csvWriter.Write(record); err != nil {
|
||||
return err
|
||||
}
|
||||
om.csvWriter.Flush()
|
||||
return om.csvWriter.Error()
|
||||
}
|
||||
|
||||
// CloseOutput 关闭输出系统
|
||||
func CloseOutput() error {
|
||||
if ResultOutput == nil {
|
||||
LogDebug("输出系统未初始化,无需关闭")
|
||||
return nil
|
||||
}
|
||||
|
||||
LogDebug("正在关闭输出系统")
|
||||
ResultOutput.mu.Lock()
|
||||
defer ResultOutput.mu.Unlock()
|
||||
|
||||
if !ResultOutput.isInitialized {
|
||||
LogDebug("输出管理器未初始化,无需关闭")
|
||||
return nil
|
||||
}
|
||||
|
||||
if ResultOutput.csvWriter != nil {
|
||||
LogDebug("刷新CSV写入器缓冲区")
|
||||
ResultOutput.csvWriter.Flush()
|
||||
}
|
||||
|
||||
if err := ResultOutput.file.Close(); err != nil {
|
||||
LogDebug(fmt.Sprintf("关闭文件失败: %v", err))
|
||||
return fmt.Errorf("关闭文件失败: %v", err)
|
||||
}
|
||||
|
||||
ResultOutput.isInitialized = false
|
||||
LogDebug("输出系统已关闭")
|
||||
return nil
|
||||
}
|
21
Core/ICMP.go
21
Core/ICMP.go
@ -45,22 +45,33 @@ func CheckLive(hostslist []string, Ping bool) []string {
|
||||
return AliveHosts
|
||||
}
|
||||
|
||||
// handleAliveHosts 处理存活主机信息
|
||||
func handleAliveHosts(chanHosts chan string, hostslist []string, isPing bool) {
|
||||
for ip := range chanHosts {
|
||||
if _, ok := ExistHosts[ip]; !ok && IsContain(hostslist, ip) {
|
||||
ExistHosts[ip] = struct{}{}
|
||||
AliveHosts = append(AliveHosts, ip)
|
||||
|
||||
// 输出存活信息
|
||||
if !Common.Silent {
|
||||
// 使用Output系统保存存活主机信息
|
||||
protocol := "ICMP"
|
||||
if isPing {
|
||||
protocol = "PING"
|
||||
}
|
||||
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.HOST,
|
||||
Target: ip,
|
||||
Status: "alive",
|
||||
Details: map[string]interface{}{
|
||||
"protocol": protocol,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
|
||||
// 保留原有的控制台输出
|
||||
if !Common.Silent {
|
||||
Common.LogSuccess(fmt.Sprintf("目标 %-15s 存活 (%s)", ip, protocol))
|
||||
}
|
||||
|
||||
AliveHosts = append(AliveHosts, ip)
|
||||
}
|
||||
livewg.Done()
|
||||
}
|
||||
|
200
Core/PortScan.go
200
Core/PortScan.go
@ -110,18 +110,31 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
|
||||
address := fmt.Sprintf("%s:%d", addr.ip, addr.port)
|
||||
Common.LogSuccess(fmt.Sprintf("端口开放 %s", address))
|
||||
|
||||
// 保存端口开放信息
|
||||
portResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.PORT,
|
||||
Target: addr.ip,
|
||||
Status: "open",
|
||||
Details: map[string]interface{}{
|
||||
"port": addr.port,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(portResult)
|
||||
|
||||
// 创建扫描结果
|
||||
result := ScanResult{
|
||||
Address: addr.ip,
|
||||
Port: addr.port,
|
||||
}
|
||||
|
||||
// 只在未跳过指纹识别时进行服务识别
|
||||
// 服务识别
|
||||
if !Common.SkipFingerprint && conn != nil {
|
||||
scanner := NewPortInfoScanner(addr.ip, addr.port, conn, time.Duration(timeout)*time.Second)
|
||||
if serviceInfo, err := scanner.Identify(); err == nil {
|
||||
result.Service = serviceInfo
|
||||
|
||||
// 构造日志消息
|
||||
var logMsg strings.Builder
|
||||
logMsg.WriteString(fmt.Sprintf("服务识别 %s => ", address))
|
||||
|
||||
@ -133,20 +146,42 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
|
||||
logMsg.WriteString(fmt.Sprintf(" 版本:%s", serviceInfo.Version))
|
||||
}
|
||||
|
||||
// 构造服务详情
|
||||
details := map[string]interface{}{
|
||||
"port": addr.port,
|
||||
"service": serviceInfo.Name,
|
||||
}
|
||||
|
||||
if serviceInfo.Version != "" {
|
||||
details["version"] = serviceInfo.Version
|
||||
}
|
||||
if v, ok := serviceInfo.Extras["vendor_product"]; ok && v != "" {
|
||||
details["product"] = v
|
||||
logMsg.WriteString(fmt.Sprintf(" 产品:%s", v))
|
||||
}
|
||||
if v, ok := serviceInfo.Extras["os"]; ok && v != "" {
|
||||
details["os"] = v
|
||||
logMsg.WriteString(fmt.Sprintf(" 系统:%s", v))
|
||||
}
|
||||
if v, ok := serviceInfo.Extras["info"]; ok && v != "" {
|
||||
details["info"] = v
|
||||
logMsg.WriteString(fmt.Sprintf(" 信息:%s", v))
|
||||
}
|
||||
|
||||
if len(serviceInfo.Banner) > 0 && len(serviceInfo.Banner) < 100 {
|
||||
details["banner"] = strings.TrimSpace(serviceInfo.Banner)
|
||||
logMsg.WriteString(fmt.Sprintf(" Banner:[%s]", strings.TrimSpace(serviceInfo.Banner)))
|
||||
}
|
||||
|
||||
// 保存服务识别结果
|
||||
serviceResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.SERVICE,
|
||||
Target: addr.ip,
|
||||
Status: "identified",
|
||||
Details: details,
|
||||
}
|
||||
Common.SaveResult(serviceResult)
|
||||
|
||||
Common.LogSuccess(logMsg.String())
|
||||
}
|
||||
}
|
||||
@ -198,164 +233,3 @@ func excludeNoPorts(ports []int) []int {
|
||||
|
||||
return newPorts
|
||||
}
|
||||
|
||||
//func SynScan(ip string, port int, timeout int64) (bool, error) {
|
||||
// ifName := getInterfaceName()
|
||||
//
|
||||
// sendConn, err := net.ListenPacket("ip4:tcp", "0.0.0.0")
|
||||
// if err != nil {
|
||||
// return false, fmt.Errorf("发送套接字错误: %v", err)
|
||||
// }
|
||||
// defer sendConn.Close()
|
||||
//
|
||||
// rawConn, err := ipv4.NewRawConn(sendConn)
|
||||
// if err != nil {
|
||||
// return false, fmt.Errorf("原始连接错误: %v", err)
|
||||
// }
|
||||
//
|
||||
// dstIP := net.ParseIP(ip)
|
||||
// if dstIP == nil {
|
||||
// return false, fmt.Errorf("IP地址无效: %s", ip)
|
||||
// }
|
||||
//
|
||||
// handle, err := pcap.OpenLive(ifName, 65536, true, pcap.BlockForever)
|
||||
// if err != nil {
|
||||
// ifaces, err := pcap.FindAllDevs()
|
||||
// if err != nil {
|
||||
// return false, fmt.Errorf("网络接口错误: %v", err)
|
||||
// }
|
||||
//
|
||||
// var found bool
|
||||
// for _, iface := range ifaces {
|
||||
// handle, err = pcap.OpenLive(iface.Name, 65536, true, pcap.BlockForever)
|
||||
// if err == nil {
|
||||
// found = true
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if !found {
|
||||
// return false, fmt.Errorf("未找到可用网络接口")
|
||||
// }
|
||||
// }
|
||||
// defer handle.Close()
|
||||
//
|
||||
// srcPort := 12345 + port
|
||||
// filter := fmt.Sprintf("tcp and src port %d and dst port %d", port, srcPort)
|
||||
// if err := handle.SetBPFFilter(filter); err != nil {
|
||||
// return false, fmt.Errorf("过滤器错误: %v", err)
|
||||
// }
|
||||
//
|
||||
// // TCP头部设置保持不变
|
||||
// tcpHeader := &ipv4.Header{
|
||||
// Version: 4,
|
||||
// Len: 20,
|
||||
// TotalLen: 40,
|
||||
// TTL: 64,
|
||||
// Protocol: 6,
|
||||
// Dst: dstIP,
|
||||
// }
|
||||
//
|
||||
// // SYN包构造保持不变
|
||||
// synPacket := make([]byte, 20)
|
||||
// binary.BigEndian.PutUint16(synPacket[0:2], uint16(srcPort))
|
||||
// binary.BigEndian.PutUint16(synPacket[2:4], uint16(port))
|
||||
// binary.BigEndian.PutUint32(synPacket[4:8], uint32(1))
|
||||
// binary.BigEndian.PutUint32(synPacket[8:12], uint32(0))
|
||||
// synPacket[12] = 0x50
|
||||
// synPacket[13] = 0x02
|
||||
// binary.BigEndian.PutUint16(synPacket[14:16], uint16(8192))
|
||||
// binary.BigEndian.PutUint16(synPacket[16:18], uint16(0))
|
||||
// binary.BigEndian.PutUint16(synPacket[18:20], uint16(0))
|
||||
//
|
||||
// checksum := calculateTCPChecksum(synPacket, tcpHeader.Src, tcpHeader.Dst)
|
||||
// binary.BigEndian.PutUint16(synPacket[16:18], checksum)
|
||||
//
|
||||
// if err := rawConn.WriteTo(tcpHeader, synPacket, nil); err != nil {
|
||||
// return false, fmt.Errorf("SYN包发送错误: %v", err)
|
||||
// }
|
||||
//
|
||||
// packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
|
||||
// packetSource.DecodeOptions.Lazy = true
|
||||
// packetSource.NoCopy = true
|
||||
//
|
||||
// timeoutChan := time.After(time.Duration(timeout) * time.Second)
|
||||
//
|
||||
// for {
|
||||
// select {
|
||||
// case packet := <-packetSource.Packets():
|
||||
// tcpLayer := packet.Layer(layers.LayerTypeTCP)
|
||||
// if tcpLayer == nil {
|
||||
// continue
|
||||
// }
|
||||
//
|
||||
// tcp, ok := tcpLayer.(*layers.TCP)
|
||||
// if !ok {
|
||||
// continue
|
||||
// }
|
||||
//
|
||||
// if tcp.SYN && tcp.ACK {
|
||||
// return true, nil
|
||||
// }
|
||||
//
|
||||
// if tcp.RST {
|
||||
// return false, nil
|
||||
// }
|
||||
//
|
||||
// case <-timeoutChan:
|
||||
// return false, nil
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//// calculateTCPChecksum 计算TCP校验和
|
||||
//func calculateTCPChecksum(tcpHeader []byte, srcIP, dstIP net.IP) uint16 {
|
||||
// // 创建伪首部
|
||||
// pseudoHeader := make([]byte, 12)
|
||||
// copy(pseudoHeader[0:4], srcIP.To4())
|
||||
// copy(pseudoHeader[4:8], dstIP.To4())
|
||||
// pseudoHeader[8] = 0
|
||||
// pseudoHeader[9] = 6 // TCP协议号
|
||||
// pseudoHeader[10] = byte(len(tcpHeader) >> 8)
|
||||
// pseudoHeader[11] = byte(len(tcpHeader))
|
||||
//
|
||||
// // 计算校验和
|
||||
// var sum uint32
|
||||
//
|
||||
// // 计算伪首部的校验和
|
||||
// for i := 0; i < len(pseudoHeader)-1; i += 2 {
|
||||
// sum += uint32(pseudoHeader[i])<<8 | uint32(pseudoHeader[i+1])
|
||||
// }
|
||||
//
|
||||
// // 计算TCP头的校验和
|
||||
// for i := 0; i < len(tcpHeader)-1; i += 2 {
|
||||
// sum += uint32(tcpHeader[i])<<8 | uint32(tcpHeader[i+1])
|
||||
// }
|
||||
//
|
||||
// // 如果长度为奇数,处理最后一个字节
|
||||
// if len(tcpHeader)%2 == 1 {
|
||||
// sum += uint32(tcpHeader[len(tcpHeader)-1]) << 8
|
||||
// }
|
||||
//
|
||||
// // 将高16位加到低16位
|
||||
// for sum > 0xffff {
|
||||
// sum = (sum >> 16) + (sum & 0xffff)
|
||||
// }
|
||||
//
|
||||
// // 取反
|
||||
// return ^uint16(sum)
|
||||
//}
|
||||
//
|
||||
//// 获取系统对应的接口名
|
||||
//func getInterfaceName() string {
|
||||
// switch runtime.GOOS {
|
||||
// case "windows":
|
||||
// return "\\Device\\NPF_Loopback"
|
||||
// case "linux":
|
||||
// return "lo"
|
||||
// case "darwin":
|
||||
// return "lo0"
|
||||
// default:
|
||||
// return "lo"
|
||||
// }
|
||||
//}
|
||||
|
@ -14,8 +14,9 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
Common.LogDebug("尝试默认账户 admin:admin")
|
||||
|
||||
// 首先测试默认账户
|
||||
@ -26,13 +27,29 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
|
||||
flag, err := ActiveMQConn(info, "admin", "admin")
|
||||
if flag {
|
||||
Common.LogSuccess(fmt.Sprintf("ActiveMQ服务 %v:%v 成功爆破 用户名: admin 密码: admin",
|
||||
info.Host, info.Ports))
|
||||
successMsg := fmt.Sprintf("ActiveMQ服务 %s 成功爆破 用户名: admin 密码: admin", target)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "activemq",
|
||||
"username": "admin",
|
||||
"password": "admin",
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
Common.LogError(fmt.Sprintf("ActiveMQ服务 %v:%v 默认账户尝试失败: %v",
|
||||
info.Host, info.Ports, err))
|
||||
errMsg := fmt.Sprintf("ActiveMQ服务 %s 默认账户尝试失败: %v", target, err)
|
||||
Common.LogError(errMsg)
|
||||
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
@ -46,8 +63,7 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
|
||||
totalUsers := len(Common.Userdict["activemq"])
|
||||
totalPass := len(Common.Passwords)
|
||||
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)",
|
||||
totalUsers, totalPass))
|
||||
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||
|
||||
tried := 0
|
||||
total := totalUsers * totalPass
|
||||
@ -65,7 +81,6 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行连接测试
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -82,14 +97,29 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success {
|
||||
Common.LogSuccess(fmt.Sprintf("ActiveMQ服务 %v:%v 成功爆破 用户名: %v 密码: %v",
|
||||
info.Host, info.Ports, user, pass))
|
||||
successMsg := fmt.Sprintf("ActiveMQ服务 %s 成功爆破 用户名: %v 密码: %v", target, user, pass)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "activemq",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
@ -97,9 +127,8 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("ActiveMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
errMsg := fmt.Sprintf("ActiveMQ服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v", target, user, pass, err)
|
||||
Common.LogError(errMsg)
|
||||
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
@ -149,14 +178,10 @@ func ActiveMQConn(info *Common.HostInfo, user string, pass string) (bool, error)
|
||||
response := string(respBuf[:n])
|
||||
|
||||
if strings.Contains(response, "CONNECTED") {
|
||||
result := fmt.Sprintf("ActiveMQ服务 %v:%v 爆破成功 用户名: %v 密码: %v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
Common.LogSuccess(result)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if strings.Contains(response, "Authentication failed") ||
|
||||
strings.Contains(response, "ERROR") {
|
||||
if strings.Contains(response, "Authentication failed") || strings.Contains(response, "ERROR") {
|
||||
return false, fmt.Errorf("认证失败")
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,10 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
maxRetries := Common.MaxRetries
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
Common.LogDebug("尝试无认证访问...")
|
||||
|
||||
// 首先测试无认证访问
|
||||
@ -27,8 +28,24 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
|
||||
|
||||
flag, err := CassandraConn(info, "", "")
|
||||
if flag && err == nil {
|
||||
Common.LogSuccess(fmt.Sprintf("Cassandra服务 %v:%v 无认证访问成功",
|
||||
info.Host, info.Ports))
|
||||
successMsg := fmt.Sprintf("Cassandra服务 %s 无认证访问成功", target)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存无认证访问结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "cassandra",
|
||||
"auth_type": "anonymous",
|
||||
"type": "unauthorized-access",
|
||||
"description": "数据库允许无认证访问",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
return err
|
||||
}
|
||||
if err != nil && Common.CheckErrs(err) != nil {
|
||||
@ -54,13 +71,11 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
if retryCount > 0 {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -77,37 +92,47 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
successLog := fmt.Sprintf("Cassandra服务 %v:%v 爆破成功 用户名: %v 密码: %v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
Common.LogSuccess(successLog)
|
||||
successMsg := fmt.Sprintf("Cassandra服务 %s 爆破成功 用户名: %v 密码: %v", target, user, pass)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存爆破成功结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "cassandra",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("Cassandra服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
errlog := fmt.Sprintf("Cassandra服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v", target, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -116,6 +141,7 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
// CassandraConn 清理后的连接测试函数
|
||||
func CassandraConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
host, port := info.Host, info.Ports
|
||||
timeout := time.Duration(Common.Timeout) * time.Second
|
||||
@ -123,7 +149,7 @@ func CassandraConn(info *Common.HostInfo, user string, pass string) (bool, error
|
||||
cluster := gocql.NewCluster(host)
|
||||
cluster.Port, _ = strconv.Atoi(port)
|
||||
cluster.Timeout = timeout
|
||||
cluster.ProtoVersion = 4 // 指定协议版本
|
||||
cluster.ProtoVersion = 4
|
||||
cluster.Consistency = gocql.One
|
||||
|
||||
if user != "" || pass != "" {
|
||||
@ -133,7 +159,6 @@ func CassandraConn(info *Common.HostInfo, user string, pass string) (bool, error
|
||||
}
|
||||
}
|
||||
|
||||
// 增加重试机制
|
||||
cluster.RetryPolicy = &gocql.SimpleRetryPolicy{NumRetries: 3}
|
||||
|
||||
session, err := cluster.CreateSession()
|
||||
@ -142,7 +167,6 @@ func CassandraConn(info *Common.HostInfo, user string, pass string) (bool, error
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
// 使用更简单的查询测试连接
|
||||
var version string
|
||||
if err := session.Query("SELECT peer FROM system.peers").Scan(&version); err != nil {
|
||||
if err := session.Query("SELECT now() FROM system.local").Scan(&version); err != nil {
|
||||
@ -150,13 +174,5 @@ func CassandraConn(info *Common.HostInfo, user string, pass string) (bool, error
|
||||
}
|
||||
}
|
||||
|
||||
result := fmt.Sprintf("Cassandra服务 %v:%v ", host, port)
|
||||
if user != "" {
|
||||
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
|
||||
} else {
|
||||
result += "无需认证即可访问"
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
@ -16,8 +16,9 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
Common.LogDebug("尝试无认证访问...")
|
||||
|
||||
// 首先测试无认证访问
|
||||
@ -27,8 +28,22 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
flag, err := ElasticConn(info, "", "")
|
||||
if flag && err == nil {
|
||||
Common.LogSuccess(fmt.Sprintf("Elasticsearch服务 %v:%v 无需认证",
|
||||
info.Host, info.Ports))
|
||||
successMsg := fmt.Sprintf("Elasticsearch服务 %s 无需认证", target)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存无认证访问结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "elasticsearch",
|
||||
"type": "unauthorized-access",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
return err
|
||||
}
|
||||
if err != nil && Common.CheckErrs(err) != nil {
|
||||
@ -61,7 +76,6 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行连接尝试
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -78,36 +92,49 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
Common.LogSuccess(fmt.Sprintf("Elasticsearch服务 %v:%v 爆破成功 用户名: %v 密码: %v",
|
||||
info.Host, info.Ports, user, pass))
|
||||
successMsg := fmt.Sprintf("Elasticsearch服务 %s 爆破成功 用户名: %v 密码: %v",
|
||||
target, user, pass)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存弱密码结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "elasticsearch",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("Elasticsearch服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
errlog := fmt.Sprintf("Elasticsearch服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
target, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -121,7 +148,6 @@ func ElasticConn(info *Common.HostInfo, user string, pass string) (bool, error)
|
||||
host, port := info.Host, info.Ports
|
||||
timeout := time.Duration(Common.Timeout) * time.Second
|
||||
|
||||
// 构造请求客户端
|
||||
client := &http.Client{
|
||||
Timeout: timeout,
|
||||
Transport: &http.Transport{
|
||||
@ -129,39 +155,22 @@ func ElasticConn(info *Common.HostInfo, user string, pass string) (bool, error)
|
||||
},
|
||||
}
|
||||
|
||||
// 构造基础URL
|
||||
baseURL := fmt.Sprintf("http://%s:%s", host, port)
|
||||
|
||||
// 创建请求
|
||||
req, err := http.NewRequest("GET", baseURL+"/_cat/indices", nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 如果提供了认证信息,添加Basic认证头
|
||||
if user != "" || pass != "" {
|
||||
auth := base64.StdEncoding.EncodeToString([]byte(user + ":" + pass))
|
||||
req.Header.Add("Authorization", "Basic "+auth)
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 检查响应状态
|
||||
if resp.StatusCode == 200 {
|
||||
result := fmt.Sprintf("Elasticsearch服务 %v:%v ", host, port)
|
||||
if user != "" {
|
||||
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
|
||||
} else {
|
||||
result += "无需认证即可访问"
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, fmt.Errorf("认证失败")
|
||||
return resp.StatusCode == 200, nil
|
||||
}
|
||||
|
@ -14,18 +14,36 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
Common.LogDebug("尝试匿名登录...")
|
||||
|
||||
// 先尝试匿名登录
|
||||
// 尝试匿名登录
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
flag, err := FtpConn(info, "anonymous", "")
|
||||
if flag && err == nil {
|
||||
success, dirs, err := FtpConn(info, "anonymous", "")
|
||||
if success && err == nil {
|
||||
Common.LogSuccess("匿名登录成功!")
|
||||
|
||||
// 保存匿名登录结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "ftp",
|
||||
"username": "anonymous",
|
||||
"password": "",
|
||||
"type": "anonymous-login",
|
||||
"directories": dirs,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
return nil
|
||||
}
|
||||
errlog := fmt.Sprintf("ftp %v:%v %v %v", info.Host, info.Ports, "anonymous", err)
|
||||
errlog := fmt.Sprintf("ftp %s %v", target, err)
|
||||
Common.LogError(errlog)
|
||||
break
|
||||
}
|
||||
@ -37,7 +55,7 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
|
||||
tried := 0
|
||||
total := totalUsers * totalPass
|
||||
|
||||
// 遍历所有用户名密码组合
|
||||
// 遍历用户名密码组合
|
||||
for _, user := range Common.Userdict["ftp"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
tried++
|
||||
@ -52,30 +70,46 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行FTP连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
dirs []string
|
||||
err error
|
||||
}, 1)
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := FtpConn(info, user, pass)
|
||||
success, dirs, err := FtpConn(info, user, pass)
|
||||
select {
|
||||
case done <- struct {
|
||||
success bool
|
||||
dirs []string
|
||||
err error
|
||||
}{success, err}:
|
||||
}{success, dirs, err}:
|
||||
default:
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
select {
|
||||
case result := <-done:
|
||||
if result.success && result.err == nil {
|
||||
successLog := fmt.Sprintf("FTP %v:%v %v %v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
successLog := fmt.Sprintf("FTP服务 %s 成功爆破 用户名: %v 密码: %v", target, user, pass)
|
||||
Common.LogSuccess(successLog)
|
||||
|
||||
// 保存爆破成功结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "ftp",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
"directories": result.dirs,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
lastErr = result.err
|
||||
@ -83,18 +117,16 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
|
||||
lastErr = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
// 错误处理
|
||||
if lastErr != nil {
|
||||
errlog := fmt.Sprintf("ftp %v:%v %v %v %v",
|
||||
info.Host, info.Ports, user, pass, lastErr)
|
||||
errlog := fmt.Sprintf("FTP服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
target, user, pass, lastErr)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 如果是密码错误,直接尝试下一个组合
|
||||
if strings.Contains(lastErr.Error(), "Login incorrect") {
|
||||
break
|
||||
}
|
||||
|
||||
// 如果是连接数限制,等待后重试
|
||||
if strings.Contains(lastErr.Error(), "too many connections") {
|
||||
Common.LogDebug("连接数过多,等待5秒...")
|
||||
time.Sleep(5 * time.Second)
|
||||
@ -112,39 +144,45 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
// FtpConn 建立FTP连接并尝试登录
|
||||
func FtpConn(info *Common.HostInfo, user string, pass string) (flag bool, err error) {
|
||||
Host, Port, Username, Password := info.Host, info.Ports, user, pass
|
||||
func FtpConn(info *Common.HostInfo, user string, pass string) (success bool, directories []string, err error) {
|
||||
Host, Port := info.Host, info.Ports
|
||||
|
||||
// 建立FTP连接
|
||||
conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v", Host, Port), time.Duration(Common.Timeout)*time.Second)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, nil, err
|
||||
}
|
||||
// 确保连接被关闭
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
conn.Quit() // 发送QUIT命令关闭连接
|
||||
conn.Quit()
|
||||
}
|
||||
}()
|
||||
|
||||
// 尝试登录
|
||||
if err = conn.Login(Username, Password); err != nil {
|
||||
return false, err
|
||||
if err = conn.Login(user, pass); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
// 登录成功,获取目录信息
|
||||
result := fmt.Sprintf("ftp %v:%v:%v %v", Host, Port, Username, Password)
|
||||
// 获取目录信息
|
||||
dirs, err := conn.List("")
|
||||
if err == nil && len(dirs) > 0 {
|
||||
// 最多显示前6个目录
|
||||
directories = make([]string, 0, min(6, len(dirs)))
|
||||
for i := 0; i < len(dirs) && i < 6; i++ {
|
||||
name := dirs[i].Name
|
||||
if len(name) > 50 {
|
||||
name = name[:50]
|
||||
}
|
||||
result += "\n [->]" + name
|
||||
directories = append(directories, name)
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
return true, directories, nil
|
||||
}
|
||||
|
||||
// min 返回两个整数中的较小值
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
@ -148,15 +148,7 @@ func read(text []byte, host string) error {
|
||||
name = ""
|
||||
}
|
||||
|
||||
// 构建基础结果
|
||||
result := fmt.Sprintf("NetInfo 扫描结果")
|
||||
result += fmt.Sprintf("\n目标主机: %s", host)
|
||||
if name != "" {
|
||||
result += fmt.Sprintf("\n主机名: %s", name)
|
||||
}
|
||||
result += "\n发现的网络接口:"
|
||||
|
||||
// 用于分类存储地址
|
||||
// 用于收集地址信息
|
||||
var ipv4Addrs []string
|
||||
var ipv6Addrs []string
|
||||
seenAddresses := make(map[string]bool)
|
||||
@ -184,7 +176,6 @@ func read(text []byte, host string) error {
|
||||
if addr != "" && !seenAddresses[addr] {
|
||||
seenAddresses[addr] = true
|
||||
|
||||
// 分类IPv4和IPv6地址
|
||||
if strings.Contains(addr, ":") {
|
||||
ipv6Addrs = append(ipv6Addrs, addr)
|
||||
} else if net.ParseIP(addr) != nil {
|
||||
@ -193,22 +184,46 @@ func read(text []byte, host string) error {
|
||||
}
|
||||
}
|
||||
|
||||
// 输出IPv4地址
|
||||
// 构建详细信息
|
||||
details := map[string]interface{}{
|
||||
"hostname": name,
|
||||
"ipv4": ipv4Addrs,
|
||||
"ipv6": ipv6Addrs,
|
||||
}
|
||||
|
||||
// 保存扫描结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.SERVICE,
|
||||
Target: host,
|
||||
Status: "identified",
|
||||
Details: details,
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
|
||||
// 构建控制台输出
|
||||
var output strings.Builder
|
||||
output.WriteString("NetInfo 扫描结果")
|
||||
output.WriteString(fmt.Sprintf("\n目标主机: %s", host))
|
||||
if name != "" {
|
||||
output.WriteString(fmt.Sprintf("\n主机名: %s", name))
|
||||
}
|
||||
output.WriteString("\n发现的网络接口:")
|
||||
|
||||
if len(ipv4Addrs) > 0 {
|
||||
result += "\n IPv4地址:"
|
||||
output.WriteString("\n IPv4地址:")
|
||||
for _, addr := range ipv4Addrs {
|
||||
result += fmt.Sprintf("\n └─ %s", addr)
|
||||
output.WriteString(fmt.Sprintf("\n └─ %s", addr))
|
||||
}
|
||||
}
|
||||
|
||||
// 输出IPv6地址
|
||||
if len(ipv6Addrs) > 0 {
|
||||
result += "\n IPv6地址:"
|
||||
output.WriteString("\n IPv6地址:")
|
||||
for _, addr := range ipv6Addrs {
|
||||
result += fmt.Sprintf("\n └─ %s", addr)
|
||||
output.WriteString(fmt.Sprintf("\n └─ %s", addr))
|
||||
}
|
||||
}
|
||||
|
||||
Common.LogSuccess(result)
|
||||
Common.LogSuccess(output.String())
|
||||
return nil
|
||||
}
|
||||
|
@ -11,14 +11,16 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// IMAPScan 主扫描函数
|
||||
func IMAPScan(info *Common.HostInfo) (tmperr error) {
|
||||
if Common.DisableBrute {
|
||||
return
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
totalUsers := len(Common.Userdict["imap"])
|
||||
totalPass := len(Common.Passwords)
|
||||
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||
@ -26,20 +28,17 @@ func IMAPScan(info *Common.HostInfo) (tmperr error) {
|
||||
tried := 0
|
||||
total := totalUsers * totalPass
|
||||
|
||||
// 遍历所有用户名密码组合
|
||||
for _, user := range Common.Userdict["imap"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
tried++
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
if retryCount > 0 {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行IMAP连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -56,23 +55,38 @@ func IMAPScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
if result.success {
|
||||
successMsg := fmt.Sprintf("IMAP服务 %s 爆破成功 用户名: %v 密码: %v", target, user, pass)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "imap",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("IMAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
errMsg := fmt.Sprintf("IMAP服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v", target, user, pass, err)
|
||||
Common.LogError(errMsg)
|
||||
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
@ -90,23 +104,22 @@ func IMAPScan(info *Common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
// IMAPConn 连接测试函数
|
||||
func IMAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
host, port := info.Host, info.Ports
|
||||
timeout := time.Duration(Common.Timeout) * time.Second
|
||||
addr := fmt.Sprintf("%s:%s", host, port)
|
||||
|
||||
// 首先尝试普通连接
|
||||
Common.LogDebug(fmt.Sprintf("尝试普通连接: %s", addr))
|
||||
// 尝试普通连接
|
||||
conn, err := net.DialTimeout("tcp", addr, timeout)
|
||||
if err == nil {
|
||||
if flag, err := tryIMAPAuth(conn, host, port, user, pass, timeout); err == nil {
|
||||
if flag, err := tryIMAPAuth(conn, user, pass, timeout); err == nil {
|
||||
return flag, nil
|
||||
}
|
||||
conn.Close()
|
||||
}
|
||||
|
||||
// 如果普通连接失败,尝试TLS连接
|
||||
Common.LogDebug(fmt.Sprintf("尝试TLS连接: %s", addr))
|
||||
// 尝试TLS连接
|
||||
tlsConfig := &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
@ -116,10 +129,11 @@ func IMAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
return tryIMAPAuth(conn, host, port, user, pass, timeout)
|
||||
return tryIMAPAuth(conn, user, pass, timeout)
|
||||
}
|
||||
|
||||
func tryIMAPAuth(conn net.Conn, host string, port string, user string, pass string, timeout time.Duration) (bool, error) {
|
||||
// tryIMAPAuth 尝试IMAP认证
|
||||
func tryIMAPAuth(conn net.Conn, user string, pass string, timeout time.Duration) (bool, error) {
|
||||
conn.SetDeadline(time.Now().Add(timeout))
|
||||
|
||||
reader := bufio.NewReader(conn)
|
||||
@ -145,9 +159,6 @@ func tryIMAPAuth(conn net.Conn, host string, port string, user string, pass stri
|
||||
}
|
||||
|
||||
if strings.Contains(response, "a001 OK") {
|
||||
result := fmt.Sprintf("IMAP服务 %v:%v 爆破成功 用户名: %v 密码: %v",
|
||||
host, port, user, pass)
|
||||
Common.LogSuccess(result)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,10 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
|
||||
// 首先测试无认证访问
|
||||
// 尝试无认证访问
|
||||
Common.LogDebug("尝试无认证访问...")
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
if retryCount > 0 {
|
||||
@ -24,6 +25,20 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
flag, err := KafkaConn(info, "", "")
|
||||
if flag && err == nil {
|
||||
// 保存无认证访问结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "kafka",
|
||||
"type": "unauthorized-access",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
Common.LogSuccess(fmt.Sprintf("Kafka服务 %s 无需认证即可访问", target))
|
||||
return nil
|
||||
}
|
||||
if err != nil && Common.CheckErrs(err) != nil {
|
||||
@ -49,13 +64,11 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
if retryCount > 0 {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行Kafka连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -72,33 +85,44 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
// 保存爆破成功结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "kafka",
|
||||
"type": "weak-password",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
Common.LogSuccess(fmt.Sprintf("Kafka服务 %s 爆破成功 用户名: %s 密码: %s", target, user, pass))
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("Kafka服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
Common.LogError(fmt.Sprintf("Kafka服务 %s 尝试失败 用户名: %s 密码: %s 错误: %v",
|
||||
target, user, pass, err))
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,13 +156,6 @@ func KafkaConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
consumer, err := sarama.NewConsumer(brokers, config)
|
||||
if err == nil {
|
||||
defer consumer.Close()
|
||||
result := fmt.Sprintf("Kafka服务 %v:%v ", host, port)
|
||||
if user != "" {
|
||||
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
|
||||
} else {
|
||||
result += "无需认证即可访问"
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@ -146,13 +163,6 @@ func KafkaConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
client, err := sarama.NewClient(brokers, config)
|
||||
if err == nil {
|
||||
defer client.Close()
|
||||
result := fmt.Sprintf("Kafka服务 %v:%v ", host, port)
|
||||
if user != "" {
|
||||
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
|
||||
} else {
|
||||
result += "无需认证即可访问"
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
@ -14,13 +14,28 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
Common.LogDebug("尝试匿名访问...")
|
||||
|
||||
// 首先尝试匿名访问
|
||||
flag, err := LDAPConn(info, "", "")
|
||||
if flag && err == nil {
|
||||
// 记录匿名访问成功
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "ldap",
|
||||
"type": "anonymous-access",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
Common.LogSuccess(fmt.Sprintf("LDAP服务 %s 匿名访问成功", target))
|
||||
return err
|
||||
}
|
||||
|
||||
@ -44,7 +59,6 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行LDAP连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -61,30 +75,42 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
// 记录成功爆破的凭据
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "ldap",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
Common.LogSuccess(fmt.Sprintf("LDAP服务 %s 爆破成功 用户名: %v 密码: %v", target, user, pass))
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("LDAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
errlog := fmt.Sprintf("LDAP服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v", target, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
@ -97,11 +123,8 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
func LDAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
host, port := info.Host, info.Ports
|
||||
address := fmt.Sprintf("%s:%s", info.Host, info.Ports)
|
||||
timeout := time.Duration(Common.Timeout) * time.Second
|
||||
address := fmt.Sprintf("%s:%s", host, port)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("尝试连接: %s", address))
|
||||
|
||||
// 配置LDAP连接
|
||||
l, err := ldap.Dial("tcp", address)
|
||||
@ -115,11 +138,9 @@ func LDAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
|
||||
// 尝试绑定
|
||||
if user != "" {
|
||||
// 构造DN
|
||||
bindDN := fmt.Sprintf("cn=%s,dc=example,dc=com", user)
|
||||
err = l.Bind(bindDN, pass)
|
||||
} else {
|
||||
// 匿名绑定
|
||||
err = l.UnauthenticatedBind("")
|
||||
}
|
||||
|
||||
@ -141,14 +162,5 @@ func LDAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 记录成功结果
|
||||
result := fmt.Sprintf("LDAP服务 %v:%v ", host, port)
|
||||
if user != "" {
|
||||
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
|
||||
} else {
|
||||
result += "匿名访问成功"
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
@ -203,14 +203,30 @@ func MS17010Scan(info *Common.HostInfo) error {
|
||||
return fmt.Errorf("管道响应不完整")
|
||||
}
|
||||
|
||||
// 漏洞检测
|
||||
// 漏洞检测部分添加 Output
|
||||
if reply[9] == 0x05 && reply[10] == 0x02 && reply[11] == 0x00 && reply[12] == 0xc0 {
|
||||
// 构造基本详情
|
||||
details := map[string]interface{}{
|
||||
"port": "445",
|
||||
"vulnerability": "MS17-010",
|
||||
}
|
||||
if os != "" {
|
||||
details["os"] = os
|
||||
Common.LogSuccess(fmt.Sprintf("发现漏洞 %s [%s] MS17-010", ip, os))
|
||||
} else {
|
||||
Common.LogSuccess(fmt.Sprintf("发现漏洞 %s MS17-010", ip))
|
||||
}
|
||||
|
||||
// 保存 MS17-010 漏洞结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: ip,
|
||||
Status: "vulnerable",
|
||||
Details: details,
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
|
||||
// DOUBLEPULSAR 后门检测
|
||||
trans2SessionSetupRequest[28] = treeID[0]
|
||||
trans2SessionSetupRequest[29] = treeID[1]
|
||||
@ -230,14 +246,42 @@ func MS17010Scan(info *Common.HostInfo) error {
|
||||
|
||||
if reply[34] == 0x51 {
|
||||
Common.LogSuccess(fmt.Sprintf("发现后门 %s DOUBLEPULSAR", ip))
|
||||
|
||||
// 保存 DOUBLEPULSAR 后门结果
|
||||
backdoorResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: ip,
|
||||
Status: "backdoor",
|
||||
Details: map[string]interface{}{
|
||||
"port": "445",
|
||||
"type": "DOUBLEPULSAR",
|
||||
"os": os,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(backdoorResult)
|
||||
}
|
||||
|
||||
// Shellcode利用
|
||||
// Shellcode 利用部分保持不变
|
||||
if Common.Shellcode != "" {
|
||||
defer MS17010EXP(info)
|
||||
}
|
||||
} else if os != "" {
|
||||
Common.LogInfo(fmt.Sprintf("系统信息 %s [%s]", ip, os))
|
||||
|
||||
// 保存系统信息
|
||||
sysResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.SERVICE,
|
||||
Target: ip,
|
||||
Status: "identified",
|
||||
Details: map[string]interface{}{
|
||||
"port": "445",
|
||||
"service": "smb",
|
||||
"os": os,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(sysResult)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -16,8 +16,9 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
totalUsers := len(Common.Userdict["mssql"])
|
||||
totalPass := len(Common.Passwords)
|
||||
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||
@ -61,8 +62,24 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
Common.LogSuccess(fmt.Sprintf("MSSQL %v:%v %v %v",
|
||||
info.Host, info.Ports, user, pass))
|
||||
successMsg := fmt.Sprintf("MSSQL %s %v %v", target, user, pass)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "mssql",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
@ -70,20 +87,18 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("MSSQL %v:%v %v %v %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
errlog := fmt.Sprintf("MSSQL %s %v %v %v", target, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -120,8 +135,5 @@ func MssqlConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 连接成功
|
||||
result := fmt.Sprintf("MSSQL %v:%v:%v %v", host, port, username, password)
|
||||
Common.LogSuccess(result)
|
||||
return true, nil
|
||||
}
|
||||
|
@ -33,15 +33,27 @@ func MemcachedScan(info *Common.HostInfo) error {
|
||||
rev := make([]byte, 1024)
|
||||
n, err := client.Read(rev)
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("Memcached %v:%v %v", info.Host, info.Ports, err)
|
||||
Common.LogError(errlog)
|
||||
Common.LogError(fmt.Sprintf("Memcached %v:%v %v", info.Host, info.Ports, err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 检查响应内容
|
||||
if strings.Contains(string(rev[:n]), "STAT") {
|
||||
result := fmt.Sprintf("Memcached %s 未授权访问", realhost)
|
||||
Common.LogSuccess(result)
|
||||
// 保存结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "memcached",
|
||||
"type": "unauthorized-access",
|
||||
"description": "Memcached unauthorized access",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
Common.LogSuccess(fmt.Sprintf("Memcached %s 未授权访问", realhost))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -41,14 +41,30 @@ func ModbusScan(info *Common.HostInfo) error {
|
||||
|
||||
// 验证响应
|
||||
if isValidModbusResponse(response[:n]) {
|
||||
result := fmt.Sprintf("Modbus服务 %v:%v 无认证访问", host, port)
|
||||
Common.LogSuccess(result)
|
||||
|
||||
// 尝试读取更多设备信息
|
||||
// 获取设备信息
|
||||
deviceInfo := parseModbusResponse(response[:n])
|
||||
|
||||
// 保存扫描结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": port,
|
||||
"service": "modbus",
|
||||
"type": "unauthorized-access",
|
||||
"device_id": deviceInfo,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
|
||||
// 控制台输出
|
||||
Common.LogSuccess(fmt.Sprintf("Modbus服务 %v:%v 无认证访问", host, port))
|
||||
if deviceInfo != "" {
|
||||
Common.LogSuccess(fmt.Sprintf("设备信息: %s", deviceInfo))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -13,17 +13,37 @@ func MongodbScan(info *Common.HostInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := MongodbUnauth(info)
|
||||
target := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
||||
isUnauth, err := MongodbUnauth(info)
|
||||
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("MongoDB %v:%v %v", info.Host, info.Ports, err)
|
||||
errlog := fmt.Sprintf("MongoDB %v %v", target, err)
|
||||
Common.LogError(errlog)
|
||||
} else if isUnauth {
|
||||
// 记录控制台输出
|
||||
Common.LogSuccess(fmt.Sprintf("MongoDB %v 未授权访问", target))
|
||||
|
||||
// 保存未授权访问结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "mongodb",
|
||||
"type": "unauthorized-access",
|
||||
"protocol": "mongodb",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// MongodbUnauth 检测MongoDB未授权访问
|
||||
func MongodbUnauth(info *Common.HostInfo) (bool, error) {
|
||||
// MongoDB查询数据包
|
||||
msgPacket := createOpMsgPacket()
|
||||
queryPacket := createOpQueryPacket()
|
||||
|
||||
@ -41,8 +61,6 @@ func MongodbUnauth(info *Common.HostInfo) (bool, error) {
|
||||
|
||||
// 检查响应结果
|
||||
if strings.Contains(reply, "totalLinesWritten") {
|
||||
result := fmt.Sprintf("MongoDB %v 未授权访问", realhost)
|
||||
Common.LogSuccess(result)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,9 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
totalUsers := len(Common.Userdict["mysql"])
|
||||
totalPass := len(Common.Passwords)
|
||||
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||
@ -38,7 +39,6 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行MySQL连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -55,33 +55,43 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
successLog := fmt.Sprintf("MySQL %v:%v %v %v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
Common.LogSuccess(successLog)
|
||||
successMsg := fmt.Sprintf("MySQL %s %v %v", target, user, pass)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "mysql",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("MySQL %v:%v %v %v %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
errMsg := fmt.Sprintf("MySQL %s %v %v %v", target, user, pass, err)
|
||||
Common.LogError(errMsg)
|
||||
|
||||
// 特殊处理认证失败的情况
|
||||
if strings.Contains(err.Error(), "Access denied") {
|
||||
break // 跳出重试循环,继续下一个密码
|
||||
break // 认证失败,尝试下一个密码
|
||||
}
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
tmperr = err
|
||||
@ -89,9 +99,9 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,9 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
|
||||
// 首先测试无认证访问和默认凭证
|
||||
initialChecks := []struct {
|
||||
@ -31,6 +32,44 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
|
||||
Common.LogDebug(fmt.Sprintf("尝试: %s:%s", check.user, check.pass))
|
||||
flag, err := Neo4jConn(info, check.user, check.pass)
|
||||
if flag && err == nil {
|
||||
var msg string
|
||||
if check.user == "" {
|
||||
msg = fmt.Sprintf("Neo4j服务 %s 无需认证即可访问", target)
|
||||
Common.LogSuccess(msg)
|
||||
|
||||
// 保存结果 - 无认证访问
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "neo4j",
|
||||
"type": "unauthorized-access",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
} else {
|
||||
msg = fmt.Sprintf("Neo4j服务 %s 默认凭证可用 用户名: %s 密码: %s", target, check.user, check.pass)
|
||||
Common.LogSuccess(msg)
|
||||
|
||||
// 保存结果 - 默认凭证
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "neo4j",
|
||||
"type": "default-credentials",
|
||||
"username": check.user,
|
||||
"password": check.pass,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -55,7 +94,6 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行Neo4j连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -72,33 +110,47 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
msg := fmt.Sprintf("Neo4j服务 %s 爆破成功 用户名: %s 密码: %s", target, user, pass)
|
||||
Common.LogSuccess(msg)
|
||||
|
||||
// 保存结果 - 成功爆破
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "neo4j",
|
||||
"type": "weak-password",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("Neo4j服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
errlog := fmt.Sprintf("Neo4j服务 %s 尝试失败 用户名: %s 密码: %s 错误: %v", target, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -143,13 +195,5 @@ func Neo4jConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 连接成功
|
||||
result := fmt.Sprintf("Neo4j服务 %v:%v ", host, port)
|
||||
if user != "" {
|
||||
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
|
||||
} else {
|
||||
result += "无需认证即可访问"
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
return true, nil
|
||||
}
|
||||
|
@ -20,6 +20,47 @@ func NetBIOS(info *Common.HostInfo) error {
|
||||
if len(output) > 0 {
|
||||
result := fmt.Sprintf("NetBios %-15s %s", info.Host, output)
|
||||
Common.LogSuccess(result)
|
||||
|
||||
// 保存结果
|
||||
details := map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
}
|
||||
|
||||
// 添加有效的 NetBIOS 信息
|
||||
if netbios.ComputerName != "" {
|
||||
details["computer_name"] = netbios.ComputerName
|
||||
}
|
||||
if netbios.DomainName != "" {
|
||||
details["domain_name"] = netbios.DomainName
|
||||
}
|
||||
if netbios.NetDomainName != "" {
|
||||
details["netbios_domain"] = netbios.NetDomainName
|
||||
}
|
||||
if netbios.NetComputerName != "" {
|
||||
details["netbios_computer"] = netbios.NetComputerName
|
||||
}
|
||||
if netbios.WorkstationService != "" {
|
||||
details["workstation_service"] = netbios.WorkstationService
|
||||
}
|
||||
if netbios.ServerService != "" {
|
||||
details["server_service"] = netbios.ServerService
|
||||
}
|
||||
if netbios.DomainControllers != "" {
|
||||
details["domain_controllers"] = netbios.DomainControllers
|
||||
}
|
||||
if netbios.OsVersion != "" {
|
||||
details["os_version"] = netbios.OsVersion
|
||||
}
|
||||
|
||||
scanResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.SERVICE,
|
||||
Target: info.Host,
|
||||
Status: "identified",
|
||||
Details: details,
|
||||
}
|
||||
|
||||
Common.SaveResult(scanResult)
|
||||
return nil
|
||||
}
|
||||
return errNetBIOS
|
||||
|
@ -15,8 +15,9 @@ func OracleScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
totalUsers := len(Common.Userdict["oracle"])
|
||||
totalPass := len(Common.Passwords)
|
||||
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||
@ -60,9 +61,24 @@ func OracleScan(info *Common.HostInfo) (tmperr error) {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
successLog := fmt.Sprintf("Oracle %v:%v %v %v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
Common.LogSuccess(successLog)
|
||||
successMsg := fmt.Sprintf("Oracle %s 成功爆破 用户名: %v 密码: %v", target, user, pass)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "oracle",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
@ -71,19 +87,17 @@ func OracleScan(info *Common.HostInfo) (tmperr error) {
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("Oracle %v:%v %v %v %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
errMsg := fmt.Sprintf("Oracle %s 尝试失败 用户名: %v 密码: %v 错误: %v", target, user, pass, err)
|
||||
Common.LogError(errMsg)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -118,8 +132,5 @@ func OracleConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 连接成功
|
||||
result := fmt.Sprintf("Oracle %v:%v:%v %v", host, port, username, password)
|
||||
Common.LogSuccess(result)
|
||||
return true, nil
|
||||
}
|
||||
|
@ -16,8 +16,9 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
totalUsers := len(Common.Userdict["pop3"])
|
||||
totalPass := len(Common.Passwords)
|
||||
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||
@ -38,53 +39,70 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行POP3连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
isTLS bool
|
||||
}, 1)
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := POP3Conn(info, user, pass)
|
||||
success, isTLS, err := POP3Conn(info, user, pass)
|
||||
select {
|
||||
case done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}:
|
||||
isTLS bool
|
||||
}{success, err, isTLS}:
|
||||
default:
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
successLog := fmt.Sprintf("POP3服务 %v:%v 用户名: %v 密码: %v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
Common.LogSuccess(successLog)
|
||||
successMsg := fmt.Sprintf("POP3服务 %s 用户名: %v 密码: %v", target, user, pass)
|
||||
if result.isTLS {
|
||||
successMsg += " (TLS)"
|
||||
}
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "pop3",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
"tls": result.isTLS,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("POP3服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
errMsg := fmt.Sprintf("POP3服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
target, user, pass, err)
|
||||
Common.LogError(errMsg)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,16 +111,15 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
func POP3Conn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
host, port := info.Host, info.Ports
|
||||
func POP3Conn(info *Common.HostInfo, user string, pass string) (success bool, isTLS bool, err error) {
|
||||
timeout := time.Duration(Common.Timeout) * time.Second
|
||||
addr := fmt.Sprintf("%s:%s", host, port)
|
||||
addr := fmt.Sprintf("%s:%s", info.Host, info.Ports)
|
||||
|
||||
// 首先尝试普通连接
|
||||
conn, err := net.DialTimeout("tcp", addr, timeout)
|
||||
if err == nil {
|
||||
if flag, err := tryPOP3Auth(conn, host, port, user, pass, timeout, false); err == nil {
|
||||
return flag, nil
|
||||
if flag, err := tryPOP3Auth(conn, user, pass, timeout); err == nil {
|
||||
return flag, false, nil
|
||||
}
|
||||
conn.Close()
|
||||
}
|
||||
@ -113,14 +130,15 @@ func POP3Conn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
}
|
||||
conn, err = tls.DialWithDialer(&net.Dialer{Timeout: timeout}, "tcp", addr, tlsConfig)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("连接失败: %v", err)
|
||||
return false, false, fmt.Errorf("连接失败: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
return tryPOP3Auth(conn, host, port, user, pass, timeout, true)
|
||||
success, err = tryPOP3Auth(conn, user, pass, timeout)
|
||||
return success, true, err
|
||||
}
|
||||
|
||||
func tryPOP3Auth(conn net.Conn, host string, port string, user string, pass string, timeout time.Duration, isTLS bool) (bool, error) {
|
||||
func tryPOP3Auth(conn net.Conn, user string, pass string, timeout time.Duration) (bool, error) {
|
||||
reader := bufio.NewReader(conn)
|
||||
conn.SetDeadline(time.Now().Add(timeout))
|
||||
|
||||
@ -162,11 +180,6 @@ func tryPOP3Auth(conn net.Conn, host string, port string, user string, pass stri
|
||||
}
|
||||
|
||||
if strings.Contains(response, "+OK") {
|
||||
result := fmt.Sprintf("POP3服务 %v:%v 爆破成功 用户名: %v 密码: %v", host, port, user, pass)
|
||||
if isTLS {
|
||||
result += " (TLS)"
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,10 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
maxRetries := Common.MaxRetries
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
totalUsers := len(Common.Userdict["postgresql"])
|
||||
totalPass := len(Common.Passwords)
|
||||
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||
@ -25,20 +26,17 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
|
||||
tried := 0
|
||||
total := totalUsers * totalPass
|
||||
|
||||
// 遍历所有用户名密码组合
|
||||
for _, user := range Common.Userdict["postgresql"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
tried++
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
if retryCount > 0 {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行PostgreSQL连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -55,36 +53,47 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
successLog := fmt.Sprintf("PostgreSQL %v:%v %v %v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
Common.LogSuccess(successLog)
|
||||
successMsg := fmt.Sprintf("PostgreSQL服务 %s 成功爆破 用户名: %v 密码: %v", target, user, pass)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "postgresql",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("PostgreSQL %v:%v %v %v %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
errMsg := fmt.Sprintf("PostgreSQL服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v", target, user, pass, err)
|
||||
Common.LogError(errMsg)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,13 +104,12 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
|
||||
|
||||
// PostgresConn 尝试PostgreSQL连接
|
||||
func PostgresConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
host, port, username, password := info.Host, info.Ports, user, pass
|
||||
timeout := time.Duration(Common.Timeout) * time.Second
|
||||
|
||||
// 构造连接字符串
|
||||
connStr := fmt.Sprintf(
|
||||
"postgres://%v:%v@%v:%v/postgres?sslmode=disable",
|
||||
username, password, host, port,
|
||||
user, pass, info.Host, info.Ports,
|
||||
)
|
||||
|
||||
// 建立数据库连接
|
||||
@ -119,8 +127,5 @@ func PostgresConn(info *Common.HostInfo, user string, pass string) (bool, error)
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 连接成功
|
||||
result := fmt.Sprintf("PostgreSQL %v:%v:%v %v", host, port, username, password)
|
||||
Common.LogSuccess(result)
|
||||
return true, nil
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ func RdpScan(info *Common.HostInfo) (tmperr error) {
|
||||
port, _ := strconv.Atoi(info.Ports)
|
||||
total := len(Common.Userdict["rdp"]) * len(Common.Passwords)
|
||||
num := 0
|
||||
target := fmt.Sprintf("%v:%v", info.Host, port)
|
||||
|
||||
// 遍历用户名密码组合
|
||||
for _, user := range Common.Userdict["rdp"] {
|
||||
@ -54,16 +55,39 @@ func RdpScan(info *Common.HostInfo) (tmperr error) {
|
||||
// 连接成功
|
||||
var result string
|
||||
if Common.Domain != "" {
|
||||
result = fmt.Sprintf("RDP %v:%v:%v\\%v %v", info.Host, port, Common.Domain, user, pass)
|
||||
result = fmt.Sprintf("RDP %v Domain: %v\\%v Password: %v", target, Common.Domain, user, pass)
|
||||
} else {
|
||||
result = fmt.Sprintf("RDP %v:%v:%v %v", info.Host, port, user, pass)
|
||||
result = fmt.Sprintf("RDP %v Username: %v Password: %v", target, user, pass)
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
|
||||
// 保存结果
|
||||
details := map[string]interface{}{
|
||||
"port": port,
|
||||
"service": "rdp",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
}
|
||||
if Common.Domain != "" {
|
||||
details["domain"] = Common.Domain
|
||||
}
|
||||
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: details,
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 连接失败
|
||||
errlog := fmt.Sprintf("(%v/%v) RDP %v:%v %v %v %v", num, total, info.Host, port, user, pass, err)
|
||||
errlog := fmt.Sprintf("(%v/%v) RDP %v Username: %v Password: %v Error: %v",
|
||||
num, total, target, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,9 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
Common.LogDebug("尝试默认账号 guest/guest")
|
||||
|
||||
// 先测试默认账号 guest/guest
|
||||
@ -27,7 +28,6 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试默认账号: guest/guest", retryCount+1))
|
||||
}
|
||||
|
||||
// 执行RabbitMQ连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -44,15 +44,29 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}()
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
result := fmt.Sprintf("RabbitMQ服务 %v:%v 连接成功 用户名: %v 密码: %v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
Common.LogSuccess(result)
|
||||
successMsg := fmt.Sprintf("RabbitMQ服务 %s 连接成功 用户名: %v 密码: %v", target, user, pass)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "rabbitmq",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
@ -60,8 +74,8 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("RabbitMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
errlog := fmt.Sprintf("RabbitMQ服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
target, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
@ -74,7 +88,6 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
break
|
||||
}
|
||||
|
||||
// 计算总尝试次数
|
||||
totalUsers := len(Common.Userdict["rabbitmq"])
|
||||
totalPass := len(Common.Passwords)
|
||||
total := totalUsers * totalPass
|
||||
@ -89,13 +102,11 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
if retryCount > 0 {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行RabbitMQ连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -112,15 +123,30 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
result := fmt.Sprintf("RabbitMQ服务 %v:%v 连接成功 用户名: %v 密码: %v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
Common.LogSuccess(result)
|
||||
successMsg := fmt.Sprintf("RabbitMQ服务 %s 连接成功 用户名: %v 密码: %v",
|
||||
target, user, pass)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "rabbitmq",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
@ -128,8 +154,8 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("RabbitMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
errlog := fmt.Sprintf("RabbitMQ服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
target, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
@ -144,7 +170,7 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried+1)) // +1 包含默认账号
|
||||
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried+1))
|
||||
return tmperr
|
||||
}
|
||||
|
||||
@ -172,8 +198,6 @@ func RabbitMQConn(info *Common.HostInfo, user string, pass string) (bool, error)
|
||||
|
||||
// 如果成功连接
|
||||
if conn != nil {
|
||||
result := fmt.Sprintf("RabbitMQ服务 %v:%v 爆破成功 用户名: %v 密码: %v", host, port, user, pass)
|
||||
Common.LogSuccess(result)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@ var (
|
||||
dir string // Redis数据库目录
|
||||
)
|
||||
|
||||
// RedisScan 执行Redis服务扫描
|
||||
func RedisScan(info *Common.HostInfo) error {
|
||||
Common.LogDebug(fmt.Sprintf("开始Redis扫描: %s:%v", info.Host, info.Ports))
|
||||
starttime := time.Now().Unix()
|
||||
@ -25,6 +24,20 @@ func RedisScan(info *Common.HostInfo) error {
|
||||
flag, err := RedisUnauth(info)
|
||||
if flag && err == nil {
|
||||
Common.LogSuccess(fmt.Sprintf("Redis无密码连接成功: %s:%v", info.Host, info.Ports))
|
||||
|
||||
// 保存未授权访问结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "redis",
|
||||
"type": "unauthorized",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -42,19 +55,15 @@ func RedisScan(info *Common.HostInfo) error {
|
||||
return fmt.Errorf(errMsg)
|
||||
}
|
||||
|
||||
// 替换密码模板
|
||||
pass = strings.Replace(pass, "{user}", "redis", -1)
|
||||
Common.LogDebug(fmt.Sprintf("尝试密码: %s", pass))
|
||||
|
||||
// 密码重试逻辑
|
||||
var lastErr error
|
||||
for retryCount := 0; retryCount < Common.MaxRetries; retryCount++ {
|
||||
// 如果不是第一次重试,添加重试日志
|
||||
if retryCount > 0 {
|
||||
Common.LogDebug(fmt.Sprintf("第 %d 次重试: %s", retryCount+1, pass))
|
||||
}
|
||||
|
||||
// 执行Redis连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -68,13 +77,27 @@ func RedisScan(info *Common.HostInfo) error {
|
||||
}{success, err}
|
||||
}()
|
||||
|
||||
// 等待结果或超时
|
||||
var connErr error
|
||||
select {
|
||||
case result := <-done:
|
||||
if result.success {
|
||||
Common.LogSuccess(fmt.Sprintf("Redis登录成功 %s:%v [%s]",
|
||||
info.Host, info.Ports, pass))
|
||||
|
||||
// 保存弱密码结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "redis",
|
||||
"type": "weak-password",
|
||||
"password": pass,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
connErr = result.err
|
||||
@ -82,27 +105,23 @@ func RedisScan(info *Common.HostInfo) error {
|
||||
connErr = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if connErr != nil {
|
||||
lastErr = connErr
|
||||
errMsg := fmt.Sprintf("Redis尝试失败 %s:%v [%s] %v",
|
||||
info.Host, info.Ports, pass, connErr)
|
||||
Common.LogError(errMsg)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(connErr); retryErr != nil {
|
||||
if retryCount == Common.MaxRetries-1 {
|
||||
Common.LogDebug(fmt.Sprintf("达到最大重试次数: %s", pass))
|
||||
break
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
|
||||
// 如果最后一次尝试遇到需要重试的错误,返回该错误
|
||||
if lastErr != nil && Common.CheckErrs(lastErr) != nil {
|
||||
Common.LogDebug(fmt.Sprintf("Redis扫描中断: %v", lastErr))
|
||||
return lastErr
|
||||
|
@ -8,15 +8,15 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// RsyncScan 执行 Rsync 服务扫描
|
||||
func RsyncScan(info *Common.HostInfo) (tmperr error) {
|
||||
if Common.DisableBrute {
|
||||
return
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
Common.LogDebug("尝试匿名访问...")
|
||||
|
||||
// 首先测试匿名访问
|
||||
@ -27,14 +27,26 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
|
||||
|
||||
flag, err := RsyncConn(info, "", "")
|
||||
if flag && err == nil {
|
||||
Common.LogSuccess(fmt.Sprintf("Rsync服务 %v:%v 匿名访问成功", info.Host, info.Ports))
|
||||
Common.LogSuccess(fmt.Sprintf("Rsync服务 %s 匿名访问成功", target))
|
||||
|
||||
// 保存匿名访问结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "rsync",
|
||||
"type": "anonymous-access",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
return err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("Rsync服务 %v:%v 匿名访问失败: %v", info.Host, info.Ports, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
Common.LogError(fmt.Sprintf("Rsync服务 %s 匿名访问失败: %v", target, err))
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
return err
|
||||
@ -52,20 +64,17 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
|
||||
tried := 0
|
||||
total := totalUsers * totalPass
|
||||
|
||||
// 遍历所有用户名密码组合
|
||||
for _, user := range Common.Userdict["rsync"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
tried++
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
|
||||
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
if retryCount > 0 {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行Rsync连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -82,37 +91,46 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success {
|
||||
successLog := fmt.Sprintf("Rsync服务 %v:%v 爆破成功 用户名: %v 密码: %v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
Common.LogSuccess(successLog)
|
||||
Common.LogSuccess(fmt.Sprintf("Rsync服务 %s 爆破成功 用户名: %v 密码: %v",
|
||||
target, user, pass))
|
||||
|
||||
// 保存爆破成功结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "rsync",
|
||||
"type": "weak-password",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("Rsync服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
Common.LogError(fmt.Sprintf("Rsync服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
target, user, pass, err))
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ func SmbScan(info *Common.HostInfo) (tmperr error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
|
||||
|
||||
// 遍历所有用户
|
||||
for _, user := range Common.Userdict["smb"] {
|
||||
// 遍历该用户的所有密码
|
||||
@ -21,19 +23,41 @@ func SmbScan(info *Common.HostInfo) (tmperr error) {
|
||||
|
||||
success, err := doWithTimeOut(info, user, pass)
|
||||
if success {
|
||||
if Common.Domain != "" {
|
||||
Common.LogSuccess(fmt.Sprintf("SMB认证成功 %s:%s %s\\%s:%s",
|
||||
info.Host, info.Ports, Common.Domain, user, pass))
|
||||
} else {
|
||||
Common.LogSuccess(fmt.Sprintf("SMB认证成功 %s:%s %s:%s",
|
||||
info.Host, info.Ports, user, pass))
|
||||
// 构建结果消息
|
||||
var successMsg string
|
||||
details := map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "smb",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
}
|
||||
|
||||
if Common.Domain != "" {
|
||||
successMsg = fmt.Sprintf("SMB认证成功 %s %s\\%s:%s", target, Common.Domain, user, pass)
|
||||
details["domain"] = Common.Domain
|
||||
} else {
|
||||
successMsg = fmt.Sprintf("SMB认证成功 %s %s:%s", target, user, pass)
|
||||
}
|
||||
|
||||
// 记录成功日志
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: details,
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
Common.LogError(fmt.Sprintf("SMB认证失败 %s:%s %s:%s %v",
|
||||
info.Host, info.Ports, user, pass, err))
|
||||
errMsg := fmt.Sprintf("SMB认证失败 %s %s:%s %v", target, user, pass, err)
|
||||
Common.LogError(errMsg)
|
||||
|
||||
// 等待失败日志打印完成
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
@ -68,9 +92,6 @@ func SmblConn(info *Common.HostInfo, user string, pass string, signal chan struc
|
||||
return false, fmt.Errorf("认证失败")
|
||||
}
|
||||
|
||||
// 添加 debug 输出原始错误信息
|
||||
Common.LogDebug(fmt.Sprintf("SMB original error: %v", err))
|
||||
|
||||
// 清理错误信息中的换行符和多余空格
|
||||
errMsg := strings.TrimSpace(strings.ReplaceAll(err.Error(), "\n", " "))
|
||||
if strings.Contains(errMsg, "NT Status Error") {
|
||||
|
@ -145,21 +145,43 @@ func smbHashScan(info *Common.HostInfo) error {
|
||||
|
||||
// logSuccessfulAuth 记录成功的认证
|
||||
func logSuccessfulAuth(info *Common.HostInfo, user, pass string, hash []byte) {
|
||||
var result string
|
||||
credential := pass
|
||||
if len(hash) > 0 {
|
||||
credential = Common.HashValue
|
||||
}
|
||||
|
||||
// 保存认证成功结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "success",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "smb2",
|
||||
"username": user,
|
||||
"domain": Common.Domain,
|
||||
"type": "weak-auth",
|
||||
"credential": credential,
|
||||
"auth_type": map[bool]string{true: "hash", false: "password"}[len(hash) > 0],
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
|
||||
// 控制台输出
|
||||
var msg string
|
||||
if Common.Domain != "" {
|
||||
result = fmt.Sprintf("SMB2认证成功 %s:%s %s\\%s",
|
||||
info.Host, info.Ports, Common.Domain, user)
|
||||
msg = fmt.Sprintf("SMB2认证成功 %s:%s %s\\%s", info.Host, info.Ports, Common.Domain, user)
|
||||
} else {
|
||||
result = fmt.Sprintf("SMB2认证成功 %s:%s %s",
|
||||
info.Host, info.Ports, user)
|
||||
msg = fmt.Sprintf("SMB2认证成功 %s:%s %s", info.Host, info.Ports, user)
|
||||
}
|
||||
|
||||
if len(hash) > 0 {
|
||||
result += fmt.Sprintf(" Hash:%s", Common.HashValue)
|
||||
msg += fmt.Sprintf(" Hash:%s", Common.HashValue)
|
||||
} else {
|
||||
result += fmt.Sprintf(" Pass:%s", pass)
|
||||
msg += fmt.Sprintf(" Pass:%s", pass)
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
Common.LogSuccess(msg)
|
||||
}
|
||||
|
||||
// logFailedAuth 记录失败的认证
|
||||
@ -241,21 +263,42 @@ func Smb2Con(info *Common.HostInfo, user string, pass string, hash []byte, haspr
|
||||
|
||||
// logShareInfo 记录SMB共享信息
|
||||
func logShareInfo(info *Common.HostInfo, user string, pass string, hash []byte, shares []string) {
|
||||
var result string
|
||||
credential := pass
|
||||
if len(hash) > 0 {
|
||||
credential = Common.HashValue
|
||||
}
|
||||
|
||||
// 保存共享信息结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "shares-found",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "smb2",
|
||||
"username": user,
|
||||
"domain": Common.Domain,
|
||||
"shares": shares,
|
||||
"credential": credential,
|
||||
"auth_type": map[bool]string{true: "hash", false: "password"}[len(hash) > 0],
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
|
||||
// 控制台输出
|
||||
var msg string
|
||||
if Common.Domain != "" {
|
||||
result = fmt.Sprintf("SMB2共享信息 %s:%s %s\\%s",
|
||||
info.Host, info.Ports, Common.Domain, user)
|
||||
msg = fmt.Sprintf("SMB2共享信息 %s:%s %s\\%s", info.Host, info.Ports, Common.Domain, user)
|
||||
} else {
|
||||
result = fmt.Sprintf("SMB2共享信息 %s:%s %s",
|
||||
info.Host, info.Ports, user)
|
||||
msg = fmt.Sprintf("SMB2共享信息 %s:%s %s", info.Host, info.Ports, user)
|
||||
}
|
||||
|
||||
if len(hash) > 0 {
|
||||
result += fmt.Sprintf(" Hash:%s", Common.HashValue)
|
||||
msg += fmt.Sprintf(" Hash:%s", Common.HashValue)
|
||||
} else {
|
||||
result += fmt.Sprintf(" Pass:%s", pass)
|
||||
msg += fmt.Sprintf(" Pass:%s", pass)
|
||||
}
|
||||
|
||||
result += fmt.Sprintf(" 共享:%v", shares)
|
||||
Common.LogInfo(result)
|
||||
msg += fmt.Sprintf(" 共享:%v", shares)
|
||||
Common.LogInfo(msg)
|
||||
}
|
||||
|
@ -16,19 +16,36 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
Common.LogDebug("尝试匿名访问...")
|
||||
|
||||
// 先测试匿名访问
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
flag, err := SmtpConn(info, "", "")
|
||||
if flag && err == nil {
|
||||
Common.LogSuccess("匿名访问成功!")
|
||||
msg := fmt.Sprintf("SMTP服务 %s 允许匿名访问", target)
|
||||
Common.LogSuccess(msg)
|
||||
|
||||
// 保存匿名访问结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "smtp",
|
||||
"type": "anonymous-access",
|
||||
"anonymous": true,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("smtp %v:%v anonymous %v", info.Host, info.Ports, err)
|
||||
errlog := fmt.Sprintf("smtp %s anonymous %v", target, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
@ -61,7 +78,6 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行SMTP连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -78,34 +94,48 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
msg := fmt.Sprintf("SMTP服务 %s 爆破成功 用户名: %v 密码: %v", target, user, pass)
|
||||
Common.LogSuccess(msg)
|
||||
|
||||
// 保存成功爆破结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "smtp",
|
||||
"type": "weak-password",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("SMTP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
errlog := fmt.Sprintf("SMTP服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
target, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -118,25 +148,20 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
|
||||
func SmtpConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
host, port := info.Host, info.Ports
|
||||
timeout := time.Duration(Common.Timeout) * time.Second
|
||||
|
||||
// 构造地址
|
||||
addr := fmt.Sprintf("%s:%s", host, port)
|
||||
|
||||
// 创建带超时的连接
|
||||
conn, err := net.DialTimeout("tcp", addr, timeout)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// 创建SMTP客户端
|
||||
client, err := smtp.NewClient(conn, host)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// 如果提供了认证信息
|
||||
if user != "" {
|
||||
auth := smtp.PlainAuth("", user, pass, host)
|
||||
err = client.Auth(auth)
|
||||
@ -145,20 +170,10 @@ func SmtpConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// 验证是否可以发送邮件
|
||||
err = client.Mail("test@test.com")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 如果成功
|
||||
result := fmt.Sprintf("SMTP服务 %v:%v ", host, port)
|
||||
if user != "" {
|
||||
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
|
||||
} else {
|
||||
result += "允许匿名访问"
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
@ -19,73 +19,86 @@ func SNMPScan(info *Common.HostInfo) (tmperr error) {
|
||||
portNum, _ := strconv.Atoi(info.Ports)
|
||||
defaultCommunities := []string{"public", "private", "cisco", "community"}
|
||||
timeout := time.Duration(Common.Timeout) * time.Second
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
Common.LogDebug(fmt.Sprintf("尝试默认 community 列表 (总数: %d)", len(defaultCommunities)))
|
||||
|
||||
tried := 0
|
||||
total := len(defaultCommunities)
|
||||
|
||||
// 遍历所有 community
|
||||
for _, community := range defaultCommunities {
|
||||
tried++
|
||||
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试 community: %s", tried, total, community))
|
||||
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
if retryCount > 0 {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: community: %s", retryCount+1, community))
|
||||
}
|
||||
|
||||
// 执行SNMP连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
sysDesc string
|
||||
err error
|
||||
}, 1)
|
||||
|
||||
go func(community string) {
|
||||
success, err := SNMPConnect(info, community, portNum)
|
||||
success, sysDesc, err := SNMPConnect(info, community, portNum)
|
||||
select {
|
||||
case done <- struct {
|
||||
success bool
|
||||
sysDesc string
|
||||
err error
|
||||
}{success, err}:
|
||||
}{success, sysDesc, err}:
|
||||
default:
|
||||
}
|
||||
}(community)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
// 连接成功
|
||||
successLog := fmt.Sprintf("SNMP服务 %v:%v community: %v 连接成功",
|
||||
info.Host, info.Ports, community)
|
||||
Common.LogSuccess(successLog)
|
||||
successMsg := fmt.Sprintf("SNMP服务 %s community: %v 连接成功", target, community)
|
||||
if result.sysDesc != "" {
|
||||
successMsg += fmt.Sprintf(" System: %v", result.sysDesc)
|
||||
}
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "snmp",
|
||||
"community": community,
|
||||
"type": "weak-community",
|
||||
"system": result.sysDesc,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(timeout):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("SNMP服务 %v:%v 尝试失败 community: %v 错误: %v",
|
||||
info.Host, info.Ports, community, err)
|
||||
errlog := fmt.Sprintf("SNMP服务 %s 尝试失败 community: %v 错误: %v",
|
||||
target, community, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,7 +107,7 @@ func SNMPScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
// SNMPConnect 尝试SNMP连接
|
||||
func SNMPConnect(info *Common.HostInfo, community string, portNum int) (bool, error) {
|
||||
func SNMPConnect(info *Common.HostInfo, community string, portNum int) (bool, string, error) {
|
||||
host := info.Host
|
||||
timeout := time.Duration(Common.Timeout) * time.Second
|
||||
|
||||
@ -109,28 +122,23 @@ func SNMPConnect(info *Common.HostInfo, community string, portNum int) (bool, er
|
||||
|
||||
err := snmp.Connect()
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, "", err
|
||||
}
|
||||
defer snmp.Conn.Close()
|
||||
|
||||
oids := []string{"1.3.6.1.2.1.1.1.0"}
|
||||
result, err := snmp.Get(oids)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, "", err
|
||||
}
|
||||
|
||||
if len(result.Variables) > 0 {
|
||||
success := fmt.Sprintf("SNMP服务 %v:%v community: %v",
|
||||
host, portNum, community) // 使用portNum替换port
|
||||
|
||||
var sysDesc string
|
||||
if result.Variables[0].Type != gosnmp.NoSuchObject {
|
||||
sysDesc := strings.TrimSpace(string(result.Variables[0].Value.([]byte)))
|
||||
success += fmt.Sprintf(" System: %v", sysDesc)
|
||||
sysDesc = strings.TrimSpace(string(result.Variables[0].Value.([]byte)))
|
||||
}
|
||||
return true, sysDesc, nil
|
||||
}
|
||||
|
||||
Common.LogSuccess(success)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, fmt.Errorf("认证失败")
|
||||
return false, "", fmt.Errorf("认证失败")
|
||||
}
|
||||
|
@ -17,8 +17,9 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
totalUsers := len(Common.Userdict["ssh"])
|
||||
totalPass := len(Common.Passwords)
|
||||
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||
@ -61,9 +62,39 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success {
|
||||
successLog := fmt.Sprintf("SSH认证成功 %v:%v User:%v Pass:%v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
Common.LogSuccess(successLog)
|
||||
successMsg := fmt.Sprintf("SSH认证成功 %s User:%v Pass:%v", target, user, pass)
|
||||
Common.LogSuccess(successMsg)
|
||||
|
||||
// 保存结果
|
||||
details := map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "ssh",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
}
|
||||
|
||||
// 如果使用了密钥认证,添加密钥信息
|
||||
if Common.SshKeyPath != "" {
|
||||
details["auth_type"] = "key"
|
||||
details["key_path"] = Common.SshKeyPath
|
||||
details["password"] = nil
|
||||
}
|
||||
|
||||
// 如果执行了命令,添加命令信息
|
||||
if Common.Command != "" {
|
||||
details["command"] = Common.Command
|
||||
}
|
||||
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: details,
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
cancel()
|
||||
return nil
|
||||
@ -75,9 +106,9 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
||||
cancel()
|
||||
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("SSH认证失败 %v:%v User:%v Pass:%v Err:%v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
errMsg := fmt.Sprintf("SSH认证失败 %s User:%v Pass:%v Err:%v",
|
||||
target, user, pass, err)
|
||||
Common.LogError(errMsg)
|
||||
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
|
@ -18,8 +18,9 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
totalUsers := len(Common.Userdict["telnet"])
|
||||
totalPass := len(Common.Passwords)
|
||||
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
|
||||
@ -40,7 +41,6 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
|
||||
}
|
||||
|
||||
// 执行Telnet连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
noAuth bool
|
||||
@ -59,43 +59,69 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(user, pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.noAuth {
|
||||
// 无需认证
|
||||
result := fmt.Sprintf("Telnet服务 %v:%v 无需认证",
|
||||
info.Host, info.Ports)
|
||||
Common.LogSuccess(result)
|
||||
msg := fmt.Sprintf("Telnet服务 %s 无需认证", target)
|
||||
Common.LogSuccess(msg)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "telnet",
|
||||
"type": "unauthorized-access",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
|
||||
} else if result.success {
|
||||
// 成功爆破
|
||||
result := fmt.Sprintf("Telnet服务 %v:%v 用户名:%v 密码:%v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
Common.LogSuccess(result)
|
||||
msg := fmt.Sprintf("Telnet服务 %s 用户名:%v 密码:%v", target, user, pass)
|
||||
Common.LogSuccess(msg)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "telnet",
|
||||
"type": "weak-password",
|
||||
"username": user,
|
||||
"password": pass,
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("Telnet连接失败 %v:%v 用户名:%v 密码:%v 错误:%v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
errlog := fmt.Sprintf("Telnet连接失败 %s 用户名:%v 密码:%v 错误:%v",
|
||||
target, user, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -106,28 +132,21 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
|
||||
|
||||
// telnetConn 尝试建立Telnet连接并进行身份验证
|
||||
func telnetConn(info *Common.HostInfo, user, pass string) (flag bool, err error) {
|
||||
// 创建telnet客户端
|
||||
client := NewTelnet(info.Host, info.Ports)
|
||||
|
||||
// 建立连接
|
||||
if err = client.Connect(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// 设置认证信息
|
||||
client.UserName = user
|
||||
client.Password = pass
|
||||
|
||||
// 检测服务器类型
|
||||
client.ServerType = client.MakeServerType()
|
||||
|
||||
// 如果是无需认证的服务器,直接返回成功
|
||||
if client.ServerType == UnauthorizedAccess {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// 尝试登录认证
|
||||
err = client.Login()
|
||||
return false, err
|
||||
}
|
||||
|
@ -15,8 +15,9 @@ func VncScan(info *Common.HostInfo) (tmperr error) {
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
modename := "vnc"
|
||||
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports))
|
||||
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
|
||||
totalPass := len(Common.Passwords)
|
||||
Common.LogDebug(fmt.Sprintf("开始尝试密码组合 (总密码数: %d)", totalPass))
|
||||
|
||||
@ -33,7 +34,6 @@ func VncScan(info *Common.HostInfo) (tmperr error) {
|
||||
Common.LogDebug(fmt.Sprintf("第%d次重试密码: %s", retryCount+1, pass))
|
||||
}
|
||||
|
||||
// 执行VNC连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
@ -50,37 +50,48 @@ func VncScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}(pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
// 连接成功
|
||||
successLog := fmt.Sprintf("%s://%v:%v 密码: %v",
|
||||
modename, info.Host, info.Ports, pass)
|
||||
successLog := fmt.Sprintf("%s://%s 密码: %v", modename, target, pass)
|
||||
Common.LogSuccess(successLog)
|
||||
|
||||
// 保存结果
|
||||
vulnResult := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.VULN,
|
||||
Target: info.Host,
|
||||
Status: "vulnerable",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "vnc",
|
||||
"password": pass,
|
||||
"type": "weak-password",
|
||||
},
|
||||
}
|
||||
Common.SaveResult(vulnResult)
|
||||
return nil
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("%s://%v:%v 尝试密码: %v 错误: %v",
|
||||
modename, info.Host, info.Ports, pass, err)
|
||||
errlog := fmt.Sprintf("%s://%s 尝试密码: %v 错误: %v",
|
||||
modename, target, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否是需要重试的错误
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
continue // 继续重试
|
||||
continue
|
||||
}
|
||||
}
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +198,6 @@ func geturl(info *Common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
|
||||
if flag != 2 {
|
||||
// 处理编码
|
||||
if !utf8.Valid(body) {
|
||||
Common.LogDebug("检测到非UTF8编码,尝试GBK解码")
|
||||
body, _ = simplifiedchinese.GBK.NewDecoder().Bytes(body)
|
||||
}
|
||||
|
||||
@ -208,22 +207,53 @@ func geturl(info *Common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
|
||||
if length == "" {
|
||||
length = fmt.Sprintf("%v", len(body))
|
||||
}
|
||||
Common.LogDebug(fmt.Sprintf("提取的标题: %s, 内容长度: %s", title, length))
|
||||
|
||||
// 处理重定向
|
||||
// 收集服务器信息
|
||||
serverInfo := make(map[string]interface{})
|
||||
serverInfo["title"] = title
|
||||
serverInfo["length"] = length
|
||||
serverInfo["status_code"] = resp.StatusCode
|
||||
|
||||
// 收集响应头信息
|
||||
for k, v := range resp.Header {
|
||||
if len(v) > 0 {
|
||||
serverInfo[strings.ToLower(k)] = v[0]
|
||||
}
|
||||
}
|
||||
|
||||
// 检查重定向
|
||||
redirURL, err1 := resp.Location()
|
||||
if err1 == nil {
|
||||
reurl = redirURL.String()
|
||||
Common.LogDebug(fmt.Sprintf("检测到重定向URL: %s", reurl))
|
||||
serverInfo["redirect_url"] = reurl
|
||||
}
|
||||
|
||||
// 输出结果
|
||||
result := fmt.Sprintf("网站标题 %-25v 状态码:%-3v 长度:%-6v 标题:%v",
|
||||
// 保存扫描结果
|
||||
result := &Common.ScanResult{
|
||||
Time: time.Now(),
|
||||
Type: Common.SERVICE,
|
||||
Target: info.Host,
|
||||
Status: "identified",
|
||||
Details: map[string]interface{}{
|
||||
"port": info.Ports,
|
||||
"service": "http",
|
||||
"title": title,
|
||||
"url": resp.Request.URL.String(),
|
||||
"status_code": resp.StatusCode,
|
||||
"length": length,
|
||||
"server_info": serverInfo,
|
||||
"fingerprints": info.Infostr, // 指纹信息
|
||||
},
|
||||
}
|
||||
Common.SaveResult(result)
|
||||
|
||||
// 输出控制台日志
|
||||
logMsg := fmt.Sprintf("网站标题 %-25v 状态码:%-3v 长度:%-6v 标题:%v",
|
||||
resp.Request.URL, resp.StatusCode, length, title)
|
||||
if reurl != "" {
|
||||
result += fmt.Sprintf(" 重定向地址: %s", reurl)
|
||||
logMsg += fmt.Sprintf(" 重定向地址: %s", reurl)
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
Common.LogSuccess(logMsg)
|
||||
}
|
||||
|
||||
// 返回结果
|
||||
|
10
main.go
10
main.go
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"github.com/shadow1ng/fscan/Core"
|
||||
"os"
|
||||
@ -8,12 +9,17 @@ import (
|
||||
|
||||
func main() {
|
||||
Common.InitLogger()
|
||||
defer Common.CloseLogger() // 确保程序退出时关闭日志文件
|
||||
|
||||
var Info Common.HostInfo
|
||||
Common.Flag(&Info)
|
||||
if err := Common.Parse(&Info); err != nil {
|
||||
os.Exit(1) // 直接退出即可,日志已经同步写入
|
||||
os.Exit(1)
|
||||
}
|
||||
// 初始化输出系统,如果失败则直接退出
|
||||
if err := Common.InitOutput(); err != nil {
|
||||
Common.LogError(fmt.Sprintf("初始化输出系统失败: %v", err))
|
||||
os.Exit(1) // 关键修改:初始化失败时直接退出
|
||||
}
|
||||
defer Common.CloseOutput()
|
||||
Core.Scan(Info)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user