From 33b6e2876b3c96d2842c359d4af098f7bb8a6dc2 Mon Sep 17 00:00:00 2001 From: SleepingBag945 <100852628+SleepingBag945@users.noreply.github.com> Date: Fri, 7 Jun 2024 19:17:14 +0800 Subject: [PATCH] v2.0.2 --- common/callnuclei/callnuclei.go | 63 +++++++++++++++++---------------- common/flag.go | 11 ++++-- common/portscan.go | 23 +++++++++--- common/uncover/hunter.go | 1 + gopocs/ftp.go | 3 ++ gopocs/mssql.go | 3 ++ gopocs/mysql.go | 3 ++ gopocs/oracle.go | 3 ++ gopocs/postgres.go | 3 ++ gopocs/rdp.go | 3 ++ gopocs/redis.go | 4 +++ gopocs/scanner.go | 9 +++++ gopocs/smb.go | 3 ++ gopocs/ssh.go | 4 +++ gopocs/telnet.go | 4 +++ main.go | 49 +++++++++++++++++-------- structs/type.go | 4 +++ 17 files changed, 141 insertions(+), 52 deletions(-) diff --git a/common/callnuclei/callnuclei.go b/common/callnuclei/callnuclei.go index 04ec5b2..6fcae42 100755 --- a/common/callnuclei/callnuclei.go +++ b/common/callnuclei/callnuclei.go @@ -28,23 +28,29 @@ var ( options = &types.Options{} ) -func CallNuclei(TargetAndPocsName map[string][]string, - proxy string, - callBack func(result output.ResultEvent), - nameForSearch string, - NoInteractsh bool, - fs embed.FS, - np string, - excludeTags []string, - severities []string) []output.ResultEvent { +type NucleiParams struct { + TargetAndPocsName map[string][]string + Proxy string + CallBack func(result output.ResultEvent) + NameForSearch string + NoInteractsh bool + Fs embed.FS + NP string + ExcludeTags []string + Severities []string + InteractshServer string + InteractshToken string +} + +func CallNuclei(param NucleiParams) []output.ResultEvent { // 设置结果回调 - output.AddResultCallback = callBack + output.AddResultCallback = param.CallBack if err := exportrunner.ExportRunnerConfigureOptions(); err != nil { gologger.Fatal().Msgf("Could not initialize options: %s\n", err) } - readConfig(TargetAndPocsName, proxy, nameForSearch, NoInteractsh, np, excludeTags) + readConfig(param) // configPath, _ := flagSet.GetConfigFilePath() if options.ListDslSignatures { @@ -81,8 +87,8 @@ func CallNuclei(TargetAndPocsName map[string][]string, return []output.ResultEvent{} } - nucleiRunner.EmbedPocsFS = fs - nucleiRunner.EnableSeverities = severities + nucleiRunner.EmbedPocsFS = param.Fs + nucleiRunner.EnableSeverities = param.Severities // Setup graceful exits resumeFileName := types.DefaultResumeFilePath() @@ -97,7 +103,7 @@ func CallNuclei(TargetAndPocsName map[string][]string, } }() - if err := nucleiRunner.RunEnumeration(TargetAndPocsName); err != nil { + if err := nucleiRunner.RunEnumeration(param.TargetAndPocsName); err != nil { if options.Validate { gologger.Fatal().Msgf("Could not validate templates: %s\n", err) } else { @@ -112,19 +118,14 @@ func CallNuclei(TargetAndPocsName map[string][]string, return output.Results } -func readConfig(TargetAndPocsName map[string][]string, - proxy string, - nameForSearch string, - NoInteractsh bool, - np string, - excludeTags []string) { +func readConfig(param NucleiParams) { pwd, _ := os.Getwd() // target URLs/hosts to scan // 扫描目标 var targets []string - for k, _ := range TargetAndPocsName { + for k, _ := range param.TargetAndPocsName { targets = append(targets, k) } options.Targets = targets @@ -166,12 +167,12 @@ func readConfig(TargetAndPocsName map[string][]string, // 不嵌入可执行文件是为了方便增删poc。 // dddd v2.0开始默认支持内嵌,此文件夹内的pocs做补充处理 - if strings.HasPrefix(np, "/") || np[1] == ':' { + if strings.HasPrefix(param.NP, "/") || param.NP[1] == ':' { // unix绝对路径,windows绝对路径 - options.Templates = []string{np} + options.Templates = []string{param.NP} } else { // 相对路径转绝对路径 - options.Templates = []string{pwd + "/" + np} + options.Templates = []string{pwd + "/" + param.NP} } // list of template urls to run (comma-separated, file) @@ -216,7 +217,7 @@ func readConfig(TargetAndPocsName map[string][]string, // templates to exclude based on tags (comma-separated, file) // 排除执行带有标记的模板(逗号分隔,文件) - options.ExcludeTags = excludeTags + options.ExcludeTags = param.ExcludeTags // tags to be executed even if they are excluded either by default or configuration // 执行默认或者配置排除的标记模板 @@ -395,10 +396,10 @@ func readConfig(TargetAndPocsName map[string][]string, options.TlsImpersonate = false // 使用interactsh反连检测平台(默认为oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me) - options.InteractshURL = "" + options.InteractshURL = param.InteractshServer // 指定反连检测平台的身份凭证 - options.InteractshToken = "" + options.InteractshToken = param.InteractshToken // 指定保存在交互缓存中的请求数(默认:5000) options.InteractionsCacheSize = 5000 @@ -413,7 +414,7 @@ func readConfig(TargetAndPocsName map[string][]string, options.InteractionsCoolDownPeriod = 5 // 禁用反连检测平台,同时排除基于反连检测的模板 - options.NoInteractsh = NoInteractsh + options.NoInteractsh = param.NoInteractsh // overrides fuzzing type set in template (replace, prefix, postfix, infix) // 覆盖模板中设置的模糊类型(替换、前缀、后缀、中缀) @@ -497,10 +498,10 @@ func readConfig(TargetAndPocsName map[string][]string, // 显示所有响应 options.DebugResponse = false // 使用http/socks5代理(逗号分隔,文件) - if proxy == "" { + if param.Proxy == "" { options.Proxy = nil } else { - options.Proxy = []string{proxy} + options.Proxy = []string{param.Proxy} } // 代理所有请求 options.ProxyInternal = false @@ -557,7 +558,7 @@ func readConfig(TargetAndPocsName map[string][]string, options.SignTemplates = false - options.PocNameForSearch = nameForSearch + options.PocNameForSearch = param.NameForSearch gologger.DefaultLogger.SetTimestamp(options.Timestamp, levels.LevelDebug) diff --git a/common/flag.go b/common/flag.go index de52e15..e982c34 100755 --- a/common/flag.go +++ b/common/flag.go @@ -41,7 +41,7 @@ func GC() { debug.FreeOSMemory() } -var version = "2.0.1" +var version = "2.0.2" func showBanner() { banner := fmt.Sprintf(` @@ -575,6 +575,7 @@ func Flag() { flagSet.CreateGroup("portscan", "端口扫描", flagSet.StringVarP(&PortString, "port", "p", "", "端口设置。 默认扫描Top1000"), + flagSet.StringVarP(&structs.GlobalConfig.NoPortString, "no-port", "np", "", "禁止扫描的端口"), flagSet.StringVarP(&structs.GlobalConfig.PortScanType, "scan-type", "st", "tcp", "端口扫描方式 | \"-st tcp\"设置TCP扫描 | \"-st syn\"设置SYN扫描"), flagSet.IntVarP(&structs.GlobalConfig.TCPPortScanThreads, "tcp-scan-threads", "tst", 1000, "TCP扫描线程 | Windows/Mac默认1000线程 Linux默认4000"), flagSet.IntVarP(&structs.GlobalConfig.SYNPortScanThreads, "syn-scan-threads", "sst", 10000, "SYN扫描线程"), @@ -637,12 +638,18 @@ func Flag() { flagSet.CreateGroup("vuln-detect", "漏洞探测", flagSet.BoolVar(&structs.GlobalConfig.NoPoc, "npoc", false, "关闭漏洞探测,只进行信息收集"), flagSet.StringVarP(&structs.GlobalConfig.PocNameForSearch, "poc-name", "poc", "", "模糊匹配Poc名称"), - flagSet.BoolVarP(&structs.GlobalConfig.NoInteractsh, "no-interactsh", "ni", false, "禁用Interactsh服务器,排除反连模版"), flagSet.IntVarP(&structs.GlobalConfig.GoPocThreads, "golang-poc-threads", "gpt", 50, "GoPoc运行线程"), flagSet.BoolVarP(&structs.GlobalConfig.NoGolangPoc, "no-golang-poc", "ngp", false, "关闭Golang Poc探测"), flagSet.BoolVarP(&structs.GlobalConfig.DisableGeneralPoc, "disable-general-poc", "dgp", false, "禁用无视指纹的漏洞映射"), flagSet.StringVarP(&structs.GlobalConfig.ExcludeTags, "exclude-tags", "et", "", "通过tags排除模版 | 多个tags请用,连接"), flagSet.StringVarP(&structs.GlobalConfig.Severities, "severity", "s", "", "只允许指定严重程度的模板运行 | 多参数用,连接 | 允许的值: "+strings.ReplaceAll(severity.GetSupportedSeverities().String(), " ", "")), + flagSet.BoolVarP(&structs.GlobalConfig.NoServiceBruteForce, "no-brute", "nb", false, "禁用服务爆破 | 不包括Shiro Keys"), + ) + + flagSet.CreateGroup("interact-sh", "反连配置", + flagSet.BoolVarP(&structs.GlobalConfig.NoInteractsh, "no-interactsh", "ni", false, "禁用Interactsh服务器,排除反连模版"), + flagSet.StringVarP(&structs.GlobalConfig.InteractshURL, "interactsh-server", "iserver", "", "指定Interactsh服务器 | http://xxx.com | 默认使用Nuclei自带的服务"), + flagSet.StringVarP(&structs.GlobalConfig.InteractshToken, "interactsh-token", "itoken", "", "Interactsh Token"), ) flagSet.CreateGroup("config", "配置文件", diff --git a/common/portscan.go b/common/portscan.go index b24a8c2..89a9cd3 100644 --- a/common/portscan.go +++ b/common/portscan.go @@ -56,10 +56,25 @@ func ParsePort(ports string) (scanPorts []int) { var BackList map[string]struct{} var BackListLock sync.Mutex -func PortScanTCP(IPs []string, Ports string, timeout int) []string { +func PortScanTCP(IPs []string, Ports string, NoPorts string, timeout int) []string { var AliveAddress []string gologger.AuditTimeLogger("开始TCP端口扫描,端口设置: %s\nTCP端口扫描目标:%s", Ports, strings.Join(IPs, ",")) - probePorts := ParsePort(Ports) + ports := ParsePort(Ports) + noPorts := ParsePort(NoPorts) + + var probePorts []int + for _, port := range ports { + ok := false + for _, nport := range noPorts { + if nport == port { + ok = true + break + } + } + if !ok { + probePorts = append(probePorts, port) + } + } IPPortCount := make(map[string]int) BackList = make(map[string]struct{}) @@ -68,8 +83,8 @@ func PortScanTCP(IPs []string, Ports string, timeout int) []string { if workers > len(IPs)*len(probePorts) { workers = len(IPs) * len(probePorts) } - Addrs := make(chan Addr, len(IPs)*len(probePorts)) - results := make(chan string, len(IPs)*len(probePorts)) + Addrs := make(chan Addr, structs.GlobalConfig.TCPPortScanThreads) + results := make(chan string, structs.GlobalConfig.TCPPortScanThreads) var wg sync.WaitGroup //接收结果 diff --git a/common/uncover/hunter.go b/common/uncover/hunter.go index 46ee90a..71be6dc 100644 --- a/common/uncover/hunter.go +++ b/common/uncover/hunter.go @@ -144,6 +144,7 @@ func SearchHunterCore(keyword string, pageSize int, maxQueryPage int) ([]string, if responseJson.Data.Total == 0 { gologger.Error().Msgf("[Hunter] %s 无结果。", keyword) + time.Sleep(time.Second * 3) return results, ipResult } diff --git a/gopocs/ftp.go b/gopocs/ftp.go index 34bd6df..a1cb95f 100755 --- a/gopocs/ftp.go +++ b/gopocs/ftp.go @@ -14,6 +14,9 @@ import ( var ftpUserPasswdDict string func FtpScan(info *structs.HostInfo) (tmperr error) { + if structs.GlobalConfig.NoServiceBruteForce { + return + } starttime := time.Now().Unix() // 先检测匿名访问 diff --git a/gopocs/mssql.go b/gopocs/mssql.go index 53b0482..4c3fe40 100755 --- a/gopocs/mssql.go +++ b/gopocs/mssql.go @@ -15,6 +15,9 @@ import ( var mssqlUserPasswdDict string func MssqlScan(info *structs.HostInfo) (tmperr error) { + if structs.GlobalConfig.NoServiceBruteForce { + return + } starttime := time.Now().Unix() userPasswdList := sortUserPassword(info, mssqlUserPasswdDict, []string{"mssql", "sqlserver"}) diff --git a/gopocs/mysql.go b/gopocs/mysql.go index 45f6085..673f537 100755 --- a/gopocs/mysql.go +++ b/gopocs/mysql.go @@ -15,6 +15,9 @@ import ( var mysqlUserPasswdDict string func MysqlScan(info *structs.HostInfo) (tmperr error) { + if structs.GlobalConfig.NoServiceBruteForce { + return + } starttime := time.Now().Unix() userPasswdList := sortUserPassword(info, mysqlUserPasswdDict, []string{"mysql"}) diff --git a/gopocs/oracle.go b/gopocs/oracle.go index 8082f90..fa1a26e 100755 --- a/gopocs/oracle.go +++ b/gopocs/oracle.go @@ -15,6 +15,9 @@ import ( var oracleUserPasswdDict string func OracleScan(info *structs.HostInfo) (tmperr error) { + if structs.GlobalConfig.NoServiceBruteForce { + return + } starttime := time.Now().Unix() userPasswdList := sortUserPassword(info, oracleUserPasswdDict, []string{"oracle"}) diff --git a/gopocs/postgres.go b/gopocs/postgres.go index 1592d06..20db641 100755 --- a/gopocs/postgres.go +++ b/gopocs/postgres.go @@ -16,6 +16,9 @@ import ( var postgreSQLUserPasswdDict string func PostgresScan(info *structs.HostInfo) (tmperr error) { + if structs.GlobalConfig.NoServiceBruteForce { + return + } starttime := time.Now().Unix() defer gologger.AuditTimeLogger("[Go] [PostgreSQL] PostgresScan return! %s:%v", info.Host, info.Ports) diff --git a/gopocs/rdp.go b/gopocs/rdp.go index ddb29b5..74de905 100755 --- a/gopocs/rdp.go +++ b/gopocs/rdp.go @@ -33,6 +33,9 @@ type Brutelist struct { } func RdpScan(info *structs.HostInfo) (tmperr error) { + if structs.GlobalConfig.NoServiceBruteForce { + return + } userPasswdList := sortUserPassword(info, rdpUserPasswdDict, []string{}) gologger.AuditTimeLogger("[Go] [RDP-Brute] start try %s:%v", info.Host, info.Ports) defer gologger.AuditTimeLogger("[Go] [RDP-Brute] RdpScan return %s:%v", info.Host, info.Ports) diff --git a/gopocs/redis.go b/gopocs/redis.go index f9e1067..45ae5d2 100755 --- a/gopocs/redis.go +++ b/gopocs/redis.go @@ -25,6 +25,10 @@ func RedisScan(info *structs.HostInfo) (tmperr error) { return errA } + if structs.GlobalConfig.NoServiceBruteForce { + return errA + } + var upList []string if structs.GlobalConfig.Password != "" { diff --git a/gopocs/scanner.go b/gopocs/scanner.go index f1487e4..1e01470 100755 --- a/gopocs/scanner.go +++ b/gopocs/scanner.go @@ -36,6 +36,11 @@ func AddScan(scantype string, info structs.HostInfo, ch *chan struct{}, wg *sync } func ScanFunc(name *string, info *structs.HostInfo) { + defer func() { + if err := recover(); err != nil { + gologger.Error().Msgf("[-] %v:%v %v error: %v\n", info.Host, info.Ports, name, err) + } + }() f := reflect.ValueOf(PluginList[*name]) in := []reflect.Value{reflect.ValueOf(info)} f.Call(in) @@ -94,11 +99,15 @@ func GoPocsDispatcher(nucleiResults []output.ResultEvent) { &ch, &wg) } if protocol == "rdp" || port == "3389" { + if structs.GlobalConfig.NoServiceBruteForce { + continue + } AddScan("RDP-Crack", structs.HostInfo{Host: host, Ports: port}, &ch, &wg) } if protocol == "redis" || port == "6379" { + // 有未授权检测 AddScan("Redis-Crack", structs.HostInfo{Host: host, Ports: port}, &ch, &wg) diff --git a/gopocs/smb.go b/gopocs/smb.go index 235879c..30fba9a 100755 --- a/gopocs/smb.go +++ b/gopocs/smb.go @@ -16,6 +16,9 @@ import ( var smbUserPasswdDict string func SmbScan(info *structs.HostInfo) (tmperr error) { + if structs.GlobalConfig.NoServiceBruteForce { + return + } starttime := time.Now().Unix() gologger.AuditTimeLogger("[Go] [SMB-Brute] start try %s:%v", info.Host, info.Ports) defer gologger.AuditTimeLogger("[Go] [SMB-Brute] SmbScan return %s:%v", info.Host, info.Ports) diff --git a/gopocs/ssh.go b/gopocs/ssh.go index 896607c..4558e14 100755 --- a/gopocs/ssh.go +++ b/gopocs/ssh.go @@ -16,6 +16,10 @@ import ( var sshUserPasswdDict string func SshScan(info *structs.HostInfo) (tmperr error) { + if structs.GlobalConfig.NoServiceBruteForce { + return + } + starttime := time.Now().Unix() gologger.AuditTimeLogger("[Go] [SSH-Brute] start try %s:%v", info.Host, info.Ports) defer gologger.AuditTimeLogger("[Go] [SSH-Brute] SshScan return %s:%v", info.Host, info.Ports) diff --git a/gopocs/telnet.go b/gopocs/telnet.go index b6e4a61..2b596b7 100755 --- a/gopocs/telnet.go +++ b/gopocs/telnet.go @@ -73,6 +73,10 @@ func TelnetScan(info *structs.HostInfo) (tmperr error) { return tmperr } + + if structs.GlobalConfig.NoServiceBruteForce { + return + } var upList []string if structs.GlobalConfig.Password != "" { upList = append(upList, structs.GlobalConfig.Password) diff --git a/main.go b/main.go index 39a8de5..2a4c2aa 100644 --- a/main.go +++ b/main.go @@ -112,6 +112,7 @@ func workflow() { gologger.Info().Msg("TCP存活探测") common.PortScan = false tcpAliveIPPort := common.PortScanTCP(uncheck, "80,443,3389,445,22", + structs.GlobalConfig.NoPortString, structs.GlobalConfig.TCPPortScanTimeout) for _, tIPPort := range tcpAliveIPPort { t := strings.Split(tIPPort, ":") @@ -139,6 +140,7 @@ func workflow() { } else { common.PortScan = true tmpIPPort = common.PortScanTCP(ips, structs.GlobalConfig.Ports, + structs.GlobalConfig.NoPortString, structs.GlobalConfig.TCPPortScanTimeout) } @@ -163,9 +165,8 @@ func workflow() { // 获取http响应 for hostPort, service := range structs.GlobalIPPortMap { - if service == "http" { + if strings.Contains(service, "http") { urls = append(urls, "http://"+hostPort) - } else if service == "https" { urls = append(urls, "https://"+hostPort) } } @@ -195,13 +196,21 @@ func workflow() { TargetAndPocsName[url] = []string{} } report.GenerateHTMLReportHeader() - callnuclei.CallNuclei(TargetAndPocsName, - structs.GlobalConfig.HTTPProxy, - report.AddResultByResultEvent, - structs.GlobalConfig.PocNameForSearch, - structs.GlobalConfig.NoInteractsh, - structs.GlobalEmbedPocs, structs.GlobalConfig.NucleiTemplate, strings.Split(structs.GlobalConfig.ExcludeTags, ","), - strings.Split(structs.GlobalConfig.Severities, ",")) + + param := callnuclei.NucleiParams{ + TargetAndPocsName: TargetAndPocsName, + Proxy: structs.GlobalConfig.HTTPProxy, + CallBack: report.AddResultByResultEvent, + NameForSearch: structs.GlobalConfig.PocNameForSearch, + NoInteractsh: structs.GlobalConfig.NoInteractsh, + Fs: structs.GlobalEmbedPocs, + NP: structs.GlobalConfig.NucleiTemplate, + ExcludeTags: strings.Split(structs.GlobalConfig.ExcludeTags, ","), + Severities: strings.Split(structs.GlobalConfig.Severities, ","), + InteractshServer: structs.GlobalConfig.InteractshURL, + InteractshToken: structs.GlobalConfig.InteractshToken, + } + callnuclei.CallNuclei(param) utils.DeleteReportWithNoResult() return } @@ -244,12 +253,22 @@ func workflow() { var nucleiResults []output.ResultEvent TargetAndPocsName, count := http.GetPocs(structs.WorkFlowDB) if count > 0 { - nucleiResults = callnuclei.CallNuclei(TargetAndPocsName, - structs.GlobalConfig.HTTPProxy, - report.AddResultByResultEvent, - "", structs.GlobalConfig.NoInteractsh, structs.GlobalEmbedPocs, - structs.GlobalConfig.NucleiTemplate, strings.Split(structs.GlobalConfig.ExcludeTags, ","), - strings.Split(structs.GlobalConfig.Severities, ",")) + param := callnuclei.NucleiParams{ + TargetAndPocsName: TargetAndPocsName, + Proxy: structs.GlobalConfig.HTTPProxy, + CallBack: report.AddResultByResultEvent, + NameForSearch: "", + NoInteractsh: structs.GlobalConfig.NoInteractsh, + Fs: structs.GlobalEmbedPocs, + NP: structs.GlobalConfig.NucleiTemplate, + ExcludeTags: strings.Split(structs.GlobalConfig.ExcludeTags, ","), + Severities: strings.Split(structs.GlobalConfig.Severities, ","), + InteractshServer: structs.GlobalConfig.InteractshURL, + InteractshToken: structs.GlobalConfig.InteractshToken, + } + + nucleiResults = callnuclei.CallNuclei(param) + } // GoPoc引擎 diff --git a/structs/type.go b/structs/type.go index e8280ac..50ecb01 100644 --- a/structs/type.go +++ b/structs/type.go @@ -54,6 +54,7 @@ type Config struct { NucleiTemplate string ExcludeTags string Severities string + NoServiceBruteForce bool WorkflowYamlPath string ReportName string GoPocThreads int @@ -74,6 +75,9 @@ type Config struct { FingerConfigFilePath string PasswordFile string Password string + InteractshURL string + InteractshToken string + NoPortString string } type CDNResult struct {