mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-07-13 21:02:44 +08:00
refactor: 全部优化为多线程
This commit is contained in:
parent
ed69e41001
commit
c004762a8c
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@ result.txt
|
|||||||
main
|
main
|
||||||
.idea
|
.idea
|
||||||
fscan.exe
|
fscan.exe
|
||||||
|
fscan
|
||||||
|
@ -26,7 +26,7 @@ var Userdict = map[string][]string{
|
|||||||
"neo4j": {"neo4j", "admin", "root", "test"},
|
"neo4j": {"neo4j", "admin", "root", "test"},
|
||||||
}
|
}
|
||||||
|
|
||||||
var Passwords = []string{"123456", "admin", "admin123", "root", "", "pass123", "pass@123", "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 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 = "result.txt"
|
||||||
var IsSave = true
|
var IsSave = true
|
||||||
@ -92,6 +92,7 @@ var (
|
|||||||
// 爆破配置
|
// 爆破配置
|
||||||
DisableBrute bool // 原IsBrute
|
DisableBrute bool // 原IsBrute
|
||||||
BruteThreads int // 原BruteThread
|
BruteThreads int // 原BruteThread
|
||||||
|
MaxRetries int // 最大重试次数
|
||||||
|
|
||||||
// 其他配置
|
// 其他配置
|
||||||
RemotePath string // 原Path
|
RemotePath string // 原Path
|
||||||
|
@ -114,6 +114,7 @@ func Flag(Info *HostInfo) {
|
|||||||
// 暴力破解配置
|
// 暴力破解配置
|
||||||
flag.BoolVar(&DisableBrute, "nobr", false, "禁用密码暴力破解")
|
flag.BoolVar(&DisableBrute, "nobr", false, "禁用密码暴力破解")
|
||||||
flag.IntVar(&BruteThreads, "br", 1, "设置密码破解线程数")
|
flag.IntVar(&BruteThreads, "br", 1, "设置密码破解线程数")
|
||||||
|
flag.IntVar(&MaxRetries, "retry", 3, "设置最大重试次数")
|
||||||
|
|
||||||
// 其他配置
|
// 其他配置
|
||||||
flag.StringVar(&RemotePath, "path", "", "指定FCG/SMB远程文件路径")
|
flag.StringVar(&RemotePath, "path", "", "指定FCG/SMB远程文件路径")
|
||||||
|
@ -137,13 +137,13 @@ func LogError(errinfo interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckErrs 检查是否为已知错误
|
// CheckErrs 检查是否为需要重试的错误
|
||||||
func CheckErrs(err error) bool {
|
func CheckErrs(err error) error {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 已知错误列表
|
// 已知需要重试的错误列表
|
||||||
errs := []string{
|
errs := []string{
|
||||||
"closed by the remote host", "too many connections",
|
"closed by the remote host", "too many connections",
|
||||||
"EOF", "A connection attempt failed",
|
"EOF", "A connection attempt failed",
|
||||||
@ -159,9 +159,10 @@ func CheckErrs(err error) bool {
|
|||||||
errLower := strings.ToLower(err.Error())
|
errLower := strings.ToLower(err.Error())
|
||||||
for _, key := range errs {
|
for _, key := range errs {
|
||||||
if strings.Contains(errLower, strings.ToLower(key)) {
|
if strings.Contains(errLower, strings.ToLower(key)) {
|
||||||
return true
|
time.Sleep(3 * time.Second)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,39 +15,127 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 首先测试默认账户
|
// 首先测试默认账户
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
flag, err := ActiveMQConn(info, "admin", "admin")
|
flag, err := ActiveMQConn(info, "admin", "admin")
|
||||||
if flag {
|
if flag {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
tmperr = err
|
if err != nil {
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["activemq"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["activemq"] {
|
for _, user := range Common.Userdict["activemq"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
|
// 启动工作线程
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行连接测试
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
flag, err := ActiveMQConn(info, user, pass)
|
flag, err := ActiveMQConn(info, user, pass)
|
||||||
if flag {
|
done <- struct {
|
||||||
return nil
|
success bool
|
||||||
|
err error
|
||||||
|
}{flag, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
errlog := fmt.Sprintf("[-] ActiveMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
errlog := fmt.Sprintf("[-] ActiveMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||||
info.Host, info.Ports, user, pass, err)
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["activemq"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,37 +15,126 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
starttime := time.Now().Unix()
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
// 首先测试无认证访问
|
// 首先测试无认证访问
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
flag, err := CassandraConn(info, "", "")
|
flag, err := CassandraConn(info, "", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err != nil && Common.CheckErrs(err) != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["cassandra"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["cassandra"] {
|
for _, user := range Common.Userdict["cassandra"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := CassandraConn(info, user, pass)
|
// 启动工作线程
|
||||||
if flag && err == nil {
|
var wg sync.WaitGroup
|
||||||
return err
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
errlog := fmt.Sprintf("[-] Cassandra服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
// 执行连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := CassandraConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
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, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["cassandra"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,40 +17,127 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 首先测试无认证访问
|
// 首先测试无认证访问
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
flag, err := ElasticConn(info, "", "")
|
flag, err := ElasticConn(info, "", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err != nil && Common.CheckErrs(err) != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["elastic"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["elastic"] {
|
for _, user := range Common.Userdict["elastic"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
// 替换密码中的用户名占位符
|
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
|
// 启动工作线程
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行连接尝试
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
flag, err := ElasticConn(info, user, pass)
|
flag, err := ElasticConn(info, user, pass)
|
||||||
if flag && err == nil {
|
done <- struct {
|
||||||
return err
|
success bool
|
||||||
|
err error
|
||||||
|
}{flag, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录错误信息
|
// 处理错误情况
|
||||||
errlog := fmt.Sprintf("[-] Elasticsearch服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("[-] Elasticsearch服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||||
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 超时检查
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["elastic"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
123
Plugins/FTP.go
123
Plugins/FTP.go
@ -5,57 +5,140 @@ import (
|
|||||||
"github.com/jlaffaye/ftp"
|
"github.com/jlaffaye/ftp"
|
||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FtpScan 执行FTP服务扫描
|
// FtpScan 执行FTP服务扫描
|
||||||
func FtpScan(info *Common.HostInfo) (tmperr error) {
|
func FtpScan(info *Common.HostInfo) (tmperr error) {
|
||||||
// 如果已开启暴力破解则直接返回
|
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 尝试匿名登录
|
// 先尝试匿名登录
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
flag, err := FtpConn(info, "anonymous", "")
|
flag, err := FtpConn(info, "anonymous", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
// 匿名登录成功,不需要继续尝试其他密码
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v", info.Host, info.Ports, "anonymous", err)
|
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v", info.Host, info.Ports, "anonymous", err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
tmperr = err
|
|
||||||
if Common.CheckErrs(err) {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["ftp"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["ftp"] {
|
for _, user := range Common.Userdict["ftp"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
// 替换密码中的用户名占位符
|
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := FtpConn(info, user, pass)
|
// 启动工作线程
|
||||||
if flag && err == nil {
|
var wg sync.WaitGroup
|
||||||
return err
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录错误信息
|
// 执行FTP连接
|
||||||
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := FtpConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v %v",
|
||||||
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 超时检查
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["ftp"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
101
Plugins/IMAP.go
101
Plugins/IMAP.go
@ -8,6 +8,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,31 +17,107 @@ func IMAPScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["imap"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["imap"] {
|
for _, user := range Common.Userdict["imap"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := IMAPConn(info, user, pass)
|
var wg sync.WaitGroup
|
||||||
if flag && err == nil {
|
for i := 0; i < threads; i++ {
|
||||||
return err
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
errlog := fmt.Sprintf("[-] IMAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
// 执行IMAP连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := IMAPConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
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, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["imap"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
115
Plugins/Kafka.go
115
Plugins/Kafka.go
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/IBM/sarama"
|
"github.com/IBM/sarama"
|
||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,37 +15,127 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 首先测试无认证访问
|
// 首先测试无认证访问
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
flag, err := KafkaConn(info, "", "")
|
flag, err := KafkaConn(info, "", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil && Common.CheckErrs(err) != nil {
|
||||||
|
if retryCount < maxRetries-1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["kafka"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["kafka"] {
|
for _, user := range Common.Userdict["kafka"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := KafkaConn(info, user, pass)
|
// 启动工作线程
|
||||||
if flag && err == nil {
|
var wg sync.WaitGroup
|
||||||
return err
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
errlog := fmt.Sprintf("[-] Kafka服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
// 执行Kafka连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := KafkaConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
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, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["kafka"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
107
Plugins/LDAP.go
107
Plugins/LDAP.go
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/go-ldap/ldap/v3"
|
"github.com/go-ldap/ldap/v3"
|
||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,38 +15,118 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 尝试匿名访问
|
// 首先尝试匿名访问
|
||||||
flag, err := LDAPConn(info, "", "")
|
flag, err := LDAPConn(info, "", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["ldap"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["ldap"] {
|
for _, user := range Common.Userdict["ldap"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := LDAPConn(info, user, pass)
|
// 启动工作线程
|
||||||
if flag && err == nil {
|
var wg sync.WaitGroup
|
||||||
return err
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 执行LDAP连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := LDAPConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
errlog := fmt.Sprintf("[-] LDAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
errlog := fmt.Sprintf("[-] LDAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||||
info.Host, info.Ports, user, pass, err)
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["ldap"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
105
Plugins/MSSQL.go
105
Plugins/MSSQL.go
@ -6,6 +6,7 @@ import (
|
|||||||
_ "github.com/denisenkom/go-mssqldb"
|
_ "github.com/denisenkom/go-mssqldb"
|
||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,34 +16,108 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["mssql"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["mssql"] {
|
for _, user := range Common.Userdict["mssql"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
// 替换密码中的用户名占位符
|
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := MssqlConn(info, user, pass)
|
var wg sync.WaitGroup
|
||||||
if flag && err == nil {
|
for i := 0; i < threads; i++ {
|
||||||
return err
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录错误信息
|
// 执行MSSQL连接
|
||||||
errlog := fmt.Sprintf("[-] MSSQL %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := MssqlConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("[-] MSSQL %v:%v %v %v %v",
|
||||||
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 超时检查
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["mssql"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
139
Plugins/MySQL.go
139
Plugins/MySQL.go
@ -6,6 +6,7 @@ import (
|
|||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,34 +16,138 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
// 添加成功标志通道
|
||||||
|
successChan := make(chan struct{}, 1)
|
||||||
|
defer close(successChan)
|
||||||
|
|
||||||
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["mysql"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["mysql"] {
|
for _, user := range Common.Userdict["mysql"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
// 替换密码中的用户名占位符
|
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := MysqlConn(info, user, pass)
|
// 启动工作线程
|
||||||
if flag && err == nil {
|
var wg sync.WaitGroup
|
||||||
return err
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 检查是否已经成功
|
||||||
|
select {
|
||||||
|
case <-successChan:
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录错误信息
|
// 重试循环
|
||||||
errlog := fmt.Sprintf("[-] MySQL %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行MySQL连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := MysqlConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
// 连接成功
|
||||||
|
select {
|
||||||
|
case successChan <- struct{}{}: // 标记成功
|
||||||
|
successLog := fmt.Sprintf("[+] MySQL %v:%v %v %v",
|
||||||
|
info.Host, info.Ports, task.user, task.pass)
|
||||||
|
Common.LogSuccess(successLog)
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
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, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 特殊处理认证失败的情况
|
||||||
|
if strings.Contains(err.Error(), "Access denied") {
|
||||||
|
break // 跳出重试循环,继续下一个密码
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if !strings.Contains(err.Error(), "Access denied") {
|
||||||
if Common.CheckErrs(err) {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 超时检查
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["mysql"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,8 +179,6 @@ func MysqlConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 连接成功
|
// 连接成功,只返回结果,不打印日志
|
||||||
result := fmt.Sprintf("[+] MySQL %v:%v:%v %v", host, port, username, password)
|
|
||||||
Common.LogSuccess(result)
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
122
Plugins/Neo4j.go
122
Plugins/Neo4j.go
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/neo4j/neo4j-go-driver/v4/neo4j"
|
"github.com/neo4j/neo4j-go-driver/v4/neo4j"
|
||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,43 +15,128 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 首先测试无认证访问
|
// 首先测试无认证访问和默认凭证
|
||||||
flag, err := Neo4jConn(info, "", "")
|
initialChecks := []struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{
|
||||||
|
{"", ""}, // 无认证
|
||||||
|
{"neo4j", "neo4j"}, // 默认凭证
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, check := range initialChecks {
|
||||||
|
flag, err := Neo4jConn(info, check.user, check.pass)
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试默认凭证
|
|
||||||
flag, err = Neo4jConn(info, "neo4j", "neo4j")
|
|
||||||
if flag && err == nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试其他用户名密码组合
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["neo4j"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["neo4j"] {
|
for _, user := range Common.Userdict["neo4j"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
|
// 启动工作线程
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行Neo4j连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
flag, err := Neo4jConn(info, user, pass)
|
flag, err := Neo4jConn(info, user, pass)
|
||||||
if flag && err == nil {
|
done <- struct {
|
||||||
return err
|
success bool
|
||||||
|
err error
|
||||||
|
}{flag, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
}
|
}
|
||||||
|
|
||||||
errlog := fmt.Sprintf("[-] Neo4j服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("[-] Neo4j服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||||
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["neo4j"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
_ "github.com/sijms/go-ora/v2"
|
_ "github.com/sijms/go-ora/v2"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,34 +16,112 @@ func OracleScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["oracle"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["oracle"] {
|
for _, user := range Common.Userdict["oracle"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
// 替换密码中的用户名占位符
|
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := OracleConn(info, user, pass)
|
// 启动工作线程
|
||||||
if flag && err == nil {
|
var wg sync.WaitGroup
|
||||||
return err
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录错误信息
|
// 执行Oracle连接
|
||||||
errlog := fmt.Sprintf("[-] Oracle %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := OracleConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("[-] Oracle %v:%v %v %v %v",
|
||||||
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 超时检查
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["oracle"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
109
Plugins/POP3.go
109
Plugins/POP3.go
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,30 +16,116 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["pop3"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["pop3"] {
|
for _, user := range Common.Userdict["pop3"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := POP3Conn(info, user, pass)
|
// 启动工作线程
|
||||||
if flag && err == nil {
|
var wg sync.WaitGroup
|
||||||
return err
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
errlog := fmt.Sprintf("[-] POP3服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
// 执行POP3连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := POP3Conn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.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, task.user, task.pass)
|
||||||
|
Common.LogSuccess(successLog)
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
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, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["pop3"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,34 +16,112 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["postgresql"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["postgresql"] {
|
for _, user := range Common.Userdict["postgresql"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
// 替换密码中的用户名占位符
|
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := PostgresConn(info, user, pass)
|
// 启动工作线程
|
||||||
if flag && err == nil {
|
var wg sync.WaitGroup
|
||||||
return err
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录错误信息
|
// 执行PostgreSQL连接
|
||||||
errlog := fmt.Sprintf("[-] PostgreSQL %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := PostgresConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
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, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 超时检查
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["postgresql"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,37 +16,121 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 首先测试默认账户 guest/guest
|
// 创建任务通道
|
||||||
flag, err := RabbitMQConn(info, "guest", "guest")
|
taskChan := make(chan struct {
|
||||||
if flag && err == nil {
|
user string
|
||||||
return err
|
pass string
|
||||||
}
|
}, len(Common.Userdict["rabbitmq"])*len(Common.Passwords)+1) // +1 是为了加入guest账号
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 先加入默认账号guest/guest
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{"guest", "guest"}
|
||||||
|
|
||||||
|
// 生成其他用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["rabbitmq"] {
|
for _, user := range Common.Userdict["rabbitmq"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := RabbitMQConn(info, user, pass)
|
// 启动工作线程
|
||||||
if flag && err == nil {
|
var wg sync.WaitGroup
|
||||||
return err
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
errlog := fmt.Sprintf("[-] RabbitMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
// 执行RabbitMQ连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := RabbitMQConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.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, task.user, task.pass)
|
||||||
|
Common.LogSuccess(result)
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("[-] RabbitMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||||
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["rabbitmq"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
103
Plugins/Redis.go
103
Plugins/Redis.go
@ -8,6 +8,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,7 +21,7 @@ var (
|
|||||||
func RedisScan(info *Common.HostInfo) (tmperr error) {
|
func RedisScan(info *Common.HostInfo) (tmperr error) {
|
||||||
starttime := time.Now().Unix()
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
// 尝试无密码连接
|
// 先尝试无密码连接
|
||||||
flag, err := RedisUnauth(info)
|
flag, err := RedisUnauth(info)
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
return err
|
return err
|
||||||
@ -30,30 +31,102 @@ func RedisScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试密码暴力破解
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
|
// 创建任务通道
|
||||||
|
taskChan := make(chan string, len(Common.Passwords))
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有密码任务
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", "redis", -1)
|
pass = strings.Replace(pass, "{user}", "redis", -1)
|
||||||
|
taskChan <- pass
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := RedisConn(info, pass)
|
// 启动工作线程
|
||||||
if flag && err == nil {
|
var wg sync.WaitGroup
|
||||||
return err
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
for pass := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录错误信息
|
// 执行Redis连接
|
||||||
errlog := fmt.Sprintf("[-] Redis %v:%v %v %v", info.Host, info.Ports, pass, err)
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(pass string) {
|
||||||
|
success, err := RedisConn(info, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("[-] Redis %v:%v %v %v",
|
||||||
|
info.Host, info.Ports, pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 超时检查
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("[+] Redis扫描模块结束...")
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
115
Plugins/Rsync.go
115
Plugins/Rsync.go
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,38 +15,130 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 首先测试匿名访问
|
// 首先测试匿名访问
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
flag, err := RsyncConn(info, "", "")
|
flag, err := RsyncConn(info, "", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
if err != nil {
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["rsync"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["rsync"] {
|
for _, user := range Common.Userdict["rsync"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
|
// 启动工作线程
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行Rsync连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
flag, err := RsyncConn(info, user, pass)
|
flag, err := RsyncConn(info, user, pass)
|
||||||
if flag && err == nil {
|
done <- struct {
|
||||||
return err
|
success bool
|
||||||
|
err error
|
||||||
|
}{flag && err == nil, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
errlog := fmt.Sprintf("[-] Rsync服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
errlog := fmt.Sprintf("[-] Rsync服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||||
info.Host, info.Ports, user, pass, err)
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["rsync"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
139
Plugins/SMB.go
139
Plugins/SMB.go
@ -6,60 +6,133 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"github.com/stacktitan/smb/smb"
|
"github.com/stacktitan/smb/smb"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SmbScan 执行SMB服务的认证扫描
|
// SmbScan 执行SMB服务的认证扫描
|
||||||
func SmbScan(info *Common.HostInfo) (tmperr error) {
|
func SmbScan(info *Common.HostInfo) (tmperr error) {
|
||||||
// 如果未启用暴力破解则直接返回
|
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
startTime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 遍历用户名和密码字典进行认证尝试
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["smb"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["smb"] {
|
for _, user := range Common.Userdict["smb"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
// 替换密码中的用户名占位符
|
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
// 执行带超时的认证
|
user string
|
||||||
success, err := doWithTimeOut(info, user, pass)
|
pass string
|
||||||
|
}{user, pass}
|
||||||
if success && err == nil {
|
|
||||||
// 认证成功,记录结果
|
|
||||||
var result string
|
|
||||||
if Common.Domain != "" {
|
|
||||||
result = fmt.Sprintf("[✓] SMB认证成功 %v:%v Domain:%v\\%v Pass:%v",
|
|
||||||
info.Host, info.Ports, Common.Domain, user, pass)
|
|
||||||
} else {
|
|
||||||
result = fmt.Sprintf("[✓] SMB认证成功 %v:%v User:%v Pass:%v",
|
|
||||||
info.Host, info.Ports, user, pass)
|
|
||||||
}
|
}
|
||||||
Common.LogSuccess(result)
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
// 认证失败,记录错误
|
|
||||||
errorMsg := fmt.Sprintf("[x] SMB认证失败 %v:%v User:%v Pass:%v Err:%v",
|
|
||||||
info.Host, info.Ports, user, pass,
|
|
||||||
strings.ReplaceAll(err.Error(), "\n", ""))
|
|
||||||
Common.LogError(errorMsg)
|
|
||||||
tmperr = err
|
|
||||||
|
|
||||||
// 检查是否需要中断扫描
|
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
|
// 启动工作线程
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
startTime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
// 检查是否超时
|
// 检查是否超时
|
||||||
timeoutLimit := int64(len(Common.Userdict["smb"])*len(Common.Passwords)) * Common.Timeout
|
if time.Now().Unix()-startTime > int64(Common.Timeout) {
|
||||||
if time.Now().Unix()-startTime > timeoutLimit {
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行SMB认证
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := doWithTimeOut(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
// 认证成功
|
||||||
|
var successLog string
|
||||||
|
if Common.Domain != "" {
|
||||||
|
successLog = fmt.Sprintf("[✓] SMB认证成功 %v:%v Domain:%v\\%v Pass:%v",
|
||||||
|
info.Host, info.Ports, Common.Domain, task.user, task.pass)
|
||||||
|
} else {
|
||||||
|
successLog = fmt.Sprintf("[✓] SMB认证成功 %v:%v User:%v Pass:%v",
|
||||||
|
info.Host, info.Ports, task.user, task.pass)
|
||||||
|
}
|
||||||
|
Common.LogSuccess(successLog)
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("[x] SMB认证失败 %v:%v User:%v Pass:%v Err:%v",
|
||||||
|
info.Host, info.Ports, task.user, task.pass,
|
||||||
|
strings.ReplaceAll(err.Error(), "\n", ""))
|
||||||
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
260
Plugins/SMB2.go
260
Plugins/SMB2.go
@ -6,6 +6,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hirochachacha/go-smb2"
|
"github.com/hirochachacha/go-smb2"
|
||||||
@ -13,79 +14,269 @@ import (
|
|||||||
|
|
||||||
// SmbScan2 执行SMB2服务的认证扫描,支持密码和哈希两种认证方式
|
// SmbScan2 执行SMB2服务的认证扫描,支持密码和哈希两种认证方式
|
||||||
func SmbScan2(info *Common.HostInfo) (tmperr error) {
|
func SmbScan2(info *Common.HostInfo) (tmperr error) {
|
||||||
|
|
||||||
// 如果未启用暴力破解则直接返回
|
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
hasprint := false
|
|
||||||
startTime := time.Now().Unix()
|
|
||||||
|
|
||||||
// 使用哈希认证模式
|
// 使用哈希认证模式
|
||||||
if len(Common.HashBytes) > 0 {
|
if len(Common.HashBytes) > 0 {
|
||||||
return smbHashScan(info, hasprint, startTime)
|
return smbHashScan(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用密码认证模式
|
// 使用密码认证模式
|
||||||
return smbPasswordScan(info, hasprint, startTime)
|
return smbPasswordScan(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
// smbHashScan 使用哈希进行认证扫描
|
// smbHashScan 使用哈希进行认证扫描
|
||||||
func smbHashScan(info *Common.HostInfo, hasprint bool, startTime int64) error {
|
func smbHashScan(info *Common.HostInfo) error {
|
||||||
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
hasprint := false
|
||||||
|
|
||||||
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
hash []byte
|
||||||
|
}, len(Common.Userdict["smb"])*len(Common.HashBytes))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名和哈希组合任务
|
||||||
for _, user := range Common.Userdict["smb"] {
|
for _, user := range Common.Userdict["smb"] {
|
||||||
for _, hash := range Common.HashBytes {
|
for _, hash := range Common.HashBytes {
|
||||||
success, err, printed := Smb2Con(info, user, "", hash, hasprint)
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
hash []byte
|
||||||
|
}{user, hash}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
|
// 启动工作线程
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
var hasPrintMutex sync.Mutex
|
||||||
|
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
startTime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-startTime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行SMB2认证
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
printed bool
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user string, hash []byte) {
|
||||||
|
hasPrintMutex.Lock()
|
||||||
|
currentHasPrint := hasprint
|
||||||
|
hasPrintMutex.Unlock()
|
||||||
|
|
||||||
|
success, err, printed := Smb2Con(info, user, "", hash, currentHasPrint)
|
||||||
|
|
||||||
if printed {
|
if printed {
|
||||||
|
hasPrintMutex.Lock()
|
||||||
hasprint = true
|
hasprint = true
|
||||||
|
hasPrintMutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
if success {
|
done <- struct {
|
||||||
logSuccessfulAuth(info, user, "", hash)
|
success bool
|
||||||
return err
|
err error
|
||||||
|
printed bool
|
||||||
|
}{success, err, printed}
|
||||||
|
}(task.user, task.hash)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
if result.success {
|
||||||
|
logSuccessfulAuth(info, task.user, "", task.hash)
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logFailedAuth(info, user, "", hash, err)
|
if result.err != nil {
|
||||||
|
logFailedAuth(info, task.user, "", task.hash, result.err)
|
||||||
|
|
||||||
if shouldStopScan(err, startTime, len(Common.Userdict["smb"])*len(Common.HashBytes)) {
|
// 检查是否需要重试
|
||||||
return err
|
if retryErr := Common.CheckErrs(result.err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- result.err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
logFailedAuth(info, task.user, "", task.hash, fmt.Errorf("连接超时"))
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(Common.HashValue) > 0 {
|
if len(Common.HashValue) > 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// smbPasswordScan 使用密码进行认证扫描
|
// smbPasswordScan 使用密码进行认证扫描
|
||||||
func smbPasswordScan(info *Common.HostInfo, hasprint bool, startTime int64) error {
|
func smbPasswordScan(info *Common.HostInfo) error {
|
||||||
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
hasprint := false
|
||||||
|
|
||||||
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["smb"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["smb"] {
|
for _, user := range Common.Userdict["smb"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.ReplaceAll(pass, "{user}", user)
|
pass = strings.ReplaceAll(pass, "{user}", user)
|
||||||
success, err, printed := Smb2Con(info, user, pass, []byte{}, hasprint)
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
|
// 启动工作线程
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
var hasPrintMutex sync.Mutex
|
||||||
|
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
startTime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-startTime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行SMB2认证
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
printed bool
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
hasPrintMutex.Lock()
|
||||||
|
currentHasPrint := hasprint
|
||||||
|
hasPrintMutex.Unlock()
|
||||||
|
|
||||||
|
success, err, printed := Smb2Con(info, user, pass, []byte{}, currentHasPrint)
|
||||||
|
|
||||||
if printed {
|
if printed {
|
||||||
|
hasPrintMutex.Lock()
|
||||||
hasprint = true
|
hasprint = true
|
||||||
|
hasPrintMutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
if success {
|
done <- struct {
|
||||||
logSuccessfulAuth(info, user, pass, []byte{})
|
success bool
|
||||||
return err
|
err error
|
||||||
|
printed bool
|
||||||
|
}{success, err, printed}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
if result.success {
|
||||||
|
logSuccessfulAuth(info, task.user, task.pass, []byte{})
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logFailedAuth(info, user, pass, []byte{}, err)
|
if result.err != nil {
|
||||||
|
logFailedAuth(info, task.user, task.pass, []byte{}, result.err)
|
||||||
|
|
||||||
if shouldStopScan(err, startTime, len(Common.Userdict["smb"])*len(Common.Passwords)) {
|
// 检查是否需要重试
|
||||||
return err
|
if retryErr := Common.CheckErrs(result.err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- result.err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
logFailedAuth(info, task.user, task.pass, []byte{}, fmt.Errorf("连接超时"))
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(Common.HashValue) > 0 {
|
if len(Common.HashValue) > 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
fmt.Println("[+] Smb2扫描模块结束...")
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,10 +284,10 @@ func smbPasswordScan(info *Common.HostInfo, hasprint bool, startTime int64) erro
|
|||||||
func logSuccessfulAuth(info *Common.HostInfo, user, pass string, hash []byte) {
|
func logSuccessfulAuth(info *Common.HostInfo, user, pass string, hash []byte) {
|
||||||
var result string
|
var result string
|
||||||
if Common.Domain != "" {
|
if Common.Domain != "" {
|
||||||
result = fmt.Sprintf("[✓] SMB2认证成功 %v:%v Domain:%v\\%v ",
|
result = fmt.Sprintf("[+] SMB2认证成功 %v:%v Domain:%v\\%v ",
|
||||||
info.Host, info.Ports, Common.Domain, user)
|
info.Host, info.Ports, Common.Domain, user)
|
||||||
} else {
|
} else {
|
||||||
result = fmt.Sprintf("[✓] SMB2认证成功 %v:%v User:%v ",
|
result = fmt.Sprintf("[+] SMB2认证成功 %v:%v User:%v ",
|
||||||
info.Host, info.Ports, user)
|
info.Host, info.Ports, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,29 +303,16 @@ func logSuccessfulAuth(info *Common.HostInfo, user, pass string, hash []byte) {
|
|||||||
func logFailedAuth(info *Common.HostInfo, user, pass string, hash []byte, err error) {
|
func logFailedAuth(info *Common.HostInfo, user, pass string, hash []byte, err error) {
|
||||||
var errlog string
|
var errlog string
|
||||||
if len(hash) > 0 {
|
if len(hash) > 0 {
|
||||||
errlog = fmt.Sprintf("[x] SMB2认证失败 %v:%v User:%v HashValue:%v Err:%v",
|
errlog = fmt.Sprintf("[-] SMB2认证失败 %v:%v User:%v HashValue:%v Err:%v",
|
||||||
info.Host, info.Ports, user, Common.HashValue, err)
|
info.Host, info.Ports, user, Common.HashValue, err)
|
||||||
} else {
|
} else {
|
||||||
errlog = fmt.Sprintf("[x] SMB2认证失败 %v:%v User:%v Pass:%v Err:%v",
|
errlog = fmt.Sprintf("[-] SMB2认证失败 %v:%v User:%v Pass:%v Err:%v",
|
||||||
info.Host, info.Ports, user, pass, err)
|
info.Host, info.Ports, user, pass, err)
|
||||||
}
|
}
|
||||||
errlog = strings.ReplaceAll(errlog, "\n", " ")
|
errlog = strings.ReplaceAll(errlog, "\n", " ")
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldStopScan 检查是否应该停止扫描
|
|
||||||
func shouldStopScan(err error, startTime int64, totalAttempts int) bool {
|
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().Unix()-startTime > (int64(totalAttempts) * Common.Timeout) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smb2Con 尝试SMB2连接并进行认证,检查共享访问权限
|
// Smb2Con 尝试SMB2连接并进行认证,检查共享访问权限
|
||||||
func Smb2Con(info *Common.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, flag2 bool) {
|
func Smb2Con(info *Common.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, flag2 bool) {
|
||||||
// 建立TCP连接
|
// 建立TCP连接
|
||||||
|
117
Plugins/SMTP.go
117
Plugins/SMTP.go
@ -6,6 +6,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/smtp"
|
"net/smtp"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,39 +16,129 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 首先测试匿名访问
|
// 先测试匿名访问
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
flag, err := SmtpConn(info, "", "")
|
flag, err := SmtpConn(info, "", "")
|
||||||
if flag && err == nil {
|
if flag && err == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["smtp"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["smtp"] {
|
for _, user := range Common.Userdict["smtp"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
|
// 启动工作线程
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行SMTP连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
flag, err := SmtpConn(info, user, pass)
|
flag, err := SmtpConn(info, user, pass)
|
||||||
if flag && err == nil {
|
done <- struct {
|
||||||
return err
|
success bool
|
||||||
|
err error
|
||||||
|
}{flag, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
errlog := fmt.Sprintf("[-] SMTP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
errlog := fmt.Sprintf("[-] SMTP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||||
info.Host, info.Ports, user, pass, err)
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 超时检查
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["smtp"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
101
Plugins/SNMP.go
101
Plugins/SNMP.go
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,33 +16,109 @@ func SNMPScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
portNum, _ := strconv.Atoi(info.Ports) // 添加端口转换
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 首先尝试默认community strings
|
portNum, _ := strconv.Atoi(info.Ports)
|
||||||
defaultCommunities := []string{"public", "private", "cisco", "community"}
|
defaultCommunities := []string{"public", "private", "cisco", "community"}
|
||||||
|
|
||||||
|
// 创建任务通道
|
||||||
|
taskChan := make(chan string, len(defaultCommunities))
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有community任务
|
||||||
for _, community := range defaultCommunities {
|
for _, community := range defaultCommunities {
|
||||||
flag, err := SNMPConnect(info, community, portNum) // 传入转换后的端口
|
taskChan <- community
|
||||||
if flag && err == nil {
|
}
|
||||||
return err
|
close(taskChan)
|
||||||
|
|
||||||
|
// 启动工作线程
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for community := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
timeout := time.Duration(Common.Timeout) * time.Second
|
||||||
|
if time.Now().Unix()-starttime > int64(timeout.Seconds()) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if Common.CheckErrs(err) {
|
// 执行SNMP连接
|
||||||
return err
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(community string) {
|
||||||
|
success, err := SNMPConnect(info, community, portNum)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(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)
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(timeout):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
errlog := fmt.Sprintf("[-] SNMP服务 %v:%v 尝试失败 community: %v 错误: %v",
|
errlog := fmt.Sprintf("[-] SNMP服务 %v:%v 尝试失败 community: %v 错误: %v",
|
||||||
info.Host, info.Ports, community, err)
|
info.Host, info.Ports, community, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
tmperr = err
|
|
||||||
|
|
||||||
// 修正超时计算
|
// 检查是否需要重试
|
||||||
timeout := time.Duration(Common.Timeout) * time.Second
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if time.Now().Unix()-starttime > int64(timeout.Seconds())*int64(len(defaultCommunities)) {
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,13 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
threads := Common.BruteThreads // 使用 BruteThreads 来控制线程数
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
taskChan := make(chan struct {
|
taskChan := make(chan struct {
|
||||||
user string
|
user string
|
||||||
pass string
|
pass string
|
||||||
}, len(Common.Userdict["ssh"])*len(Common.Passwords))
|
}, len(Common.Userdict["ssh"])*len(Common.Passwords))
|
||||||
|
|
||||||
// 创建结果通道
|
|
||||||
resultChan := make(chan error, threads)
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
// 生成所有任务
|
// 生成所有任务
|
||||||
@ -37,20 +37,19 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}
|
}
|
||||||
close(taskChan)
|
close(taskChan)
|
||||||
|
|
||||||
// 启动工作线程
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
for i := 0; i < threads; i++ {
|
for i := 0; i < threads; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for task := range taskChan {
|
for task := range taskChan {
|
||||||
// 为每个任务创建结果通道
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
done := make(chan struct {
|
done := make(chan struct {
|
||||||
success bool
|
success bool
|
||||||
err error
|
err error
|
||||||
})
|
})
|
||||||
|
|
||||||
// 执行SSH连接
|
|
||||||
go func(user, pass string) {
|
go func(user, pass string) {
|
||||||
success, err := SshConn(info, user, pass)
|
success, err := SshConn(info, user, pass)
|
||||||
done <- struct {
|
done <- struct {
|
||||||
@ -59,7 +58,6 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
}{success, err}
|
}{success, err}
|
||||||
}(task.user, task.pass)
|
}(task.user, task.pass)
|
||||||
|
|
||||||
// 等待结果或超时
|
|
||||||
var err error
|
var err error
|
||||||
select {
|
select {
|
||||||
case result := <-done:
|
case result := <-done:
|
||||||
@ -77,22 +75,28 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
info.Host, info.Ports, task.user, task.pass, err)
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
if Common.CheckErrs(err) {
|
// 检查是否是已知错误,如果是则等待3秒后重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
resultChan <- err
|
resultChan <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if Common.SshKeyPath != "" {
|
if Common.SshKeyPath != "" {
|
||||||
resultChan <- err
|
resultChan <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resultChan <- nil
|
resultChan <- nil
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待所有线程完成
|
|
||||||
go func() {
|
go func() {
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
close(resultChan)
|
close(resultChan)
|
||||||
@ -102,7 +106,7 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
for err := range resultChan {
|
for err := range resultChan {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
if Common.CheckErrs(err) {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,54 +8,131 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TelnetScan 执行Telnet服务扫描和密码爆破
|
// TelnetScan 执行Telnet服务扫描和密码爆破
|
||||||
func TelnetScan(info *Common.HostInfo) (tmperr error) {
|
func TelnetScan(info *Common.HostInfo) (tmperr error) {
|
||||||
// 检查是否禁用暴力破解
|
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 遍历用户名密码字典进行尝试
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["telnet"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["telnet"] {
|
for _, user := range Common.Userdict["telnet"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
// 替换密码中的用户名占位符
|
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
// 尝试Telnet连接
|
// 启动工作线程
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行Telnet连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
noAuth bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
flag, err := telnetConn(info, user, pass)
|
flag, err := telnetConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
noAuth bool
|
||||||
|
err error
|
||||||
|
}{err == nil, flag, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
// 处理连接结果
|
// 等待结果或超时
|
||||||
if flag {
|
var err error
|
||||||
// 无需认证的情况
|
select {
|
||||||
result := fmt.Sprintf("[+] Telnet服务 %v:%v 无需认证", info.Host, info.Ports)
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.noAuth {
|
||||||
|
// 无需认证
|
||||||
|
result := fmt.Sprintf("[+] Telnet服务 %v:%v 无需认证",
|
||||||
|
info.Host, info.Ports)
|
||||||
Common.LogSuccess(result)
|
Common.LogSuccess(result)
|
||||||
return nil
|
resultChan <- nil
|
||||||
} else if err == nil {
|
return
|
||||||
// 成功爆破到密码
|
} else if result.success {
|
||||||
result := fmt.Sprintf("[+] Telnet服务 %v:%v 用户名:%v 密码:%v", info.Host, info.Ports, user, pass)
|
// 成功爆破
|
||||||
|
result := fmt.Sprintf("[+] Telnet服务 %v:%v 用户名:%v 密码:%v",
|
||||||
|
info.Host, info.Ports, task.user, task.pass)
|
||||||
Common.LogSuccess(result)
|
Common.LogSuccess(result)
|
||||||
return nil
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理错误情况
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
errlog := fmt.Sprintf("[-] Telnet连接失败 %v:%v 用户名:%v 密码:%v 错误:%v",
|
errlog := fmt.Sprintf("[-] Telnet连接失败 %v:%v 用户名:%v 密码:%v 错误:%v",
|
||||||
info.Host, info.Ports, user, pass, err)
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
tmperr = err
|
|
||||||
|
|
||||||
// 检查是否存在严重错误需要中断
|
// 检查是否需要重试
|
||||||
if Common.CheckErrs(err) {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
return err
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否超时
|
break // 如果不需要重试,跳出重试循环
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["telnet"])*len(Common.Passwords)) * Common.Timeout) {
|
}
|
||||||
return fmt.Errorf("扫描超时")
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,31 +17,112 @@ func TomcatScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["tomcat"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["tomcat"] {
|
for _, user := range Common.Userdict["tomcat"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := TomcatConn(info, user, pass)
|
// 启动工作线程
|
||||||
if flag && err == nil {
|
var wg sync.WaitGroup
|
||||||
return err
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
errlog := fmt.Sprintf("[-] Tomcat Manager %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
// 执行Tomcat连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := TomcatConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("[-] Tomcat Manager %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||||
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["tomcat"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
109
Plugins/VNC.go
109
Plugins/VNC.go
@ -5,46 +5,117 @@ import (
|
|||||||
"github.com/mitchellh/go-vnc"
|
"github.com/mitchellh/go-vnc"
|
||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"net"
|
"net"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VncScan 执行VNC服务扫描及密码尝试
|
// VncScan 执行VNC服务扫描及密码尝试
|
||||||
func VncScan(info *Common.HostInfo) (tmperr error) {
|
func VncScan(info *Common.HostInfo) (tmperr error) {
|
||||||
// 如果已开启暴力破解则直接返回
|
|
||||||
if Common.DisableBrute {
|
if Common.DisableBrute {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
modename := "vnc"
|
modename := "vnc"
|
||||||
|
|
||||||
|
// 创建任务通道
|
||||||
|
taskChan := make(chan string, len(Common.Passwords))
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有密码任务
|
||||||
|
for _, pass := range Common.Passwords {
|
||||||
|
taskChan <- pass
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
|
// 启动工作线程
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
starttime := time.Now().Unix()
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
// 遍历密码字典尝试连接
|
for pass := range taskChan {
|
||||||
for _, pass := range Common.Passwords {
|
// 重试循环
|
||||||
flag, err := VncConn(info, pass)
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
if flag && err == nil {
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
// 连接成功,记录结果
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
result := fmt.Sprintf("[+] %s://%v:%v 密码: %v", modename, info.Host, info.Ports, pass)
|
return
|
||||||
Common.LogSuccess(result)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 连接失败,记录错误信息
|
// 执行VNC连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(pass string) {
|
||||||
|
success, err := VncConn(info, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(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)
|
||||||
|
Common.LogSuccess(successLog)
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
errlog := fmt.Sprintf("[-] %s://%v:%v 尝试密码: %v 错误: %v",
|
errlog := fmt.Sprintf("[-] %s://%v:%v 尝试密码: %v 错误: %v",
|
||||||
modename, info.Host, info.Ports, pass, err)
|
modename, info.Host, info.Ports, pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
tmperr = err
|
|
||||||
|
|
||||||
// 检查是否需要中断扫描
|
// 检查是否是需要重试的错误
|
||||||
if Common.CheckErrs(err) {
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 检查是否超时
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return fmt.Errorf("扫描超时")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,49 +33,132 @@ func WmiExec(info *Common.HostInfo) (tmperr error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["smb"])*len(Common.Passwords))
|
||||||
|
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["smb"] {
|
for _, user := range Common.Userdict["smb"] {
|
||||||
PASS:
|
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
// 如果是32位hash值,只尝试一次密码
|
||||||
|
if len(Common.HashValue) == 32 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := Wmiexec(info, user, pass, Common.HashValue)
|
// 启动工作线程
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
errlog := fmt.Sprintf("[-] WmiExec %v:%v %v %v %v", info.Host, 445, user, pass, err)
|
for task := range taskChan {
|
||||||
errlog = strings.Replace(errlog, "\n", "", -1)
|
// 重试循环
|
||||||
Common.LogError(errlog)
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if flag {
|
// 执行WMI连接
|
||||||
var result string
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := Wmiexec(info, user, pass, Common.HashValue)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success {
|
||||||
|
// 成功连接
|
||||||
|
var successLog string
|
||||||
if Common.Domain != "" {
|
if Common.Domain != "" {
|
||||||
result = fmt.Sprintf("[+] WmiExec %v:%v:%v\\%v ", info.Host, info.Ports, Common.Domain, user)
|
successLog = fmt.Sprintf("[+] WmiExec %v:%v:%v\\%v ",
|
||||||
|
info.Host, info.Ports, Common.Domain, task.user)
|
||||||
} else {
|
} else {
|
||||||
result = fmt.Sprintf("[+] WmiExec %v:%v:%v ", info.Host, info.Ports, user)
|
successLog = fmt.Sprintf("[+] WmiExec %v:%v:%v ",
|
||||||
|
info.Host, info.Ports, task.user)
|
||||||
}
|
}
|
||||||
|
|
||||||
if Common.HashValue != "" {
|
if Common.HashValue != "" {
|
||||||
result += "hash: " + Common.HashValue
|
successLog += "hash: " + Common.HashValue
|
||||||
} else {
|
} else {
|
||||||
result += pass
|
successLog += task.pass
|
||||||
}
|
}
|
||||||
Common.LogSuccess(result)
|
Common.LogSuccess(successLog)
|
||||||
return err
|
resultChan <- nil
|
||||||
} else {
|
return
|
||||||
tmperr = err
|
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["smb"])*len(Common.Passwords)) * Common.Timeout) {
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
return err
|
err = fmt.Errorf("连接超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("[-] WmiExec %v:%v %v %v %v",
|
||||||
|
info.Host, 445, task.user, task.pass, err)
|
||||||
|
errlog = strings.Replace(errlog, "\n", "", -1)
|
||||||
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(Common.HashValue) == 32 {
|
break // 如果不需要重试,跳出重试循环
|
||||||
break PASS
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/shadow1ng/fscan/Common"
|
"github.com/shadow1ng/fscan/Common"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,37 +17,134 @@ func ZabbixScan(info *Common.HostInfo) (tmperr error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
starttime := time.Now().Unix()
|
maxRetries := Common.MaxRetries
|
||||||
|
threads := Common.BruteThreads
|
||||||
|
|
||||||
// 首先测试默认账户
|
// 先测试默认账号
|
||||||
flag, err := ZabbixConn(info, "Admin", "zabbix")
|
defaultDone := make(chan struct {
|
||||||
if flag && err == nil {
|
success bool
|
||||||
return err
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
success, err := ZabbixConn(info, "Admin", "zabbix")
|
||||||
|
defaultDone <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case result := <-defaultDone:
|
||||||
|
if result.success && result.err == nil {
|
||||||
|
return result.err
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
Common.LogError(fmt.Sprintf("[-] Zabbix默认账号连接超时 %v:%v", info.Host, info.Ports))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试用户名密码组合
|
// 创建任务通道
|
||||||
|
taskChan := make(chan struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}, len(Common.Userdict["zabbix"])*len(Common.Passwords))
|
||||||
|
resultChan := make(chan error, threads)
|
||||||
|
|
||||||
|
// 生成所有用户名密码组合任务
|
||||||
for _, user := range Common.Userdict["zabbix"] {
|
for _, user := range Common.Userdict["zabbix"] {
|
||||||
for _, pass := range Common.Passwords {
|
for _, pass := range Common.Passwords {
|
||||||
pass = strings.Replace(pass, "{user}", user, -1)
|
pass = strings.Replace(pass, "{user}", user, -1)
|
||||||
|
taskChan <- struct {
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
}{user, pass}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(taskChan)
|
||||||
|
|
||||||
flag, err := ZabbixConn(info, user, pass)
|
// 启动工作线程
|
||||||
if flag && err == nil {
|
var wg sync.WaitGroup
|
||||||
return err
|
for i := 0; i < threads; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
starttime := time.Now().Unix()
|
||||||
|
|
||||||
|
for task := range taskChan {
|
||||||
|
// 重试循环
|
||||||
|
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||||
|
// 检查是否超时
|
||||||
|
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||||
|
resultChan <- fmt.Errorf("扫描超时")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
errlog := fmt.Sprintf("[-] Zabbix服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
// 执行Zabbix连接
|
||||||
|
done := make(chan struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
})
|
||||||
|
|
||||||
|
go func(user, pass string) {
|
||||||
|
success, err := ZabbixConn(info, user, pass)
|
||||||
|
done <- struct {
|
||||||
|
success bool
|
||||||
|
err error
|
||||||
|
}{success, err}
|
||||||
|
}(task.user, task.pass)
|
||||||
|
|
||||||
|
// 等待结果或超时
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case result := <-done:
|
||||||
|
err = result.err
|
||||||
|
if result.success && err == nil {
|
||||||
|
resultChan <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||||
|
err = fmt.Errorf("连接超时")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理错误情况
|
||||||
|
if err != nil {
|
||||||
|
errlog := fmt.Sprintf("[-] Zabbix服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||||
|
info.Host, info.Ports, task.user, task.pass, err)
|
||||||
Common.LogError(errlog)
|
Common.LogError(errlog)
|
||||||
|
|
||||||
|
// 检查是否需要重试
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
|
if retryCount == maxRetries-1 {
|
||||||
|
resultChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
continue // 继续重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break // 如果不需要重试,跳出重试循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有线程完成
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(resultChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
for err := range resultChan {
|
||||||
|
if err != nil {
|
||||||
tmperr = err
|
tmperr = err
|
||||||
|
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||||
if Common.CheckErrs(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["zabbix"])*len(Common.Passwords)) * Common.Timeout) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmperr
|
return tmperr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
FROM mysql:latest
|
FROM mysql:latest
|
||||||
|
|
||||||
# 设置环境变量
|
# 设置环境变量
|
||||||
ENV MYSQL_ROOT_PASSWORD=123456
|
ENV MYSQL_ROOT_PASSWORD=Password
|
||||||
ENV MYSQL_DATABASE=mydb
|
ENV MYSQL_DATABASE=mydb
|
||||||
|
|
||||||
# 开放3306端口
|
# 开放3306端口
|
||||||
|
@ -1,5 +1,2 @@
|
|||||||
docker build -t mysql-server .
|
docker build -t mysql-server .
|
||||||
docker run -d \
|
docker run -d -p 3306:3306 --name mysql-container mysql-server
|
||||||
-p 3306:3306 \
|
|
||||||
--name mysql-container \
|
|
||||||
mysql-server
|
|
Loading…
Reference in New Issue
Block a user