From d78e94cc46afd4888df844301bce2472af8cacc1 Mon Sep 17 00:00:00 2001 From: SaiRson <74412075+sairson@users.noreply.github.com> Date: Tue, 8 Mar 2022 08:50:57 +0800 Subject: [PATCH] Add files via upload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复redis在认证连接时出现抛出异常的bug --- cmd/brute.go | 514 +++++++++++++++++++++++++-------------------------- cmd/redis.go | 18 +- cmd/ssh.go | 388 +++++++++++++++++++------------------- 3 files changed, 460 insertions(+), 460 deletions(-) diff --git a/cmd/brute.go b/cmd/brute.go index 7f3326e..629c02e 100644 --- a/cmd/brute.go +++ b/cmd/brute.go @@ -1,257 +1,257 @@ -package cmd - -import ( - "Yasso/config" - "bufio" - "fmt" - "github.com/panjf2000/ants/v2" - "github.com/spf13/cobra" - "io" - "log" - "math" - "os" - "reflect" - "strings" - "sync" - "time" -) - -// 爆破模块 - -const ( - Clearln = "\r\x1b[2K" -) - -var BruteCmd = &cobra.Command{ - Use: "crack", - Short: "crack module and extend tool", - Run: func(cmd *cobra.Command, args []string) { - cmd.DisableFlagsInUseLine = true - _ = cmd.Help() - }, -} - -func init() { - // 添加全局变量 - BruteCmd.PersistentFlags().StringVarP(&Hosts, "hosts", "H", "", "to crack hosts address or ips.txt path (crack Must)") - BruteCmd.PersistentFlags().IntVar(&BrutePort, "port", 0, "to crack hosts port (if not set use default)") - BruteCmd.PersistentFlags().IntVar(&Runtime, "runtime", 100, "set crack thread number") - BruteCmd.PersistentFlags().BoolVarP(&BruteFlag, "crack", "", false, "make sure to use crack") - BruteCmd.PersistentFlags().DurationVar(&TimeDuration, "timeout", 1*time.Second, "crack module timeout(.eg) 1s (ns,ms,s,m,h)") - BruteCmd.PersistentFlags().StringVar(&PassDic, "pd", "", "pass dic path (.eg) pass.txt") - BruteCmd.PersistentFlags().StringVar(&UserDic, "ud", "", "user dic path (.eg) user.txt") - BruteCmd.PersistentFlags().StringVar(&ProxyHost, "proxy", "", "set socks5 proxy address") - BruteCmd.AddCommand(SshCmd) - BruteCmd.AddCommand(WinRMCmd) - BruteCmd.AddCommand(SmbCmd) - BruteCmd.AddCommand(Log4jCmd) - BruteCmd.AddCommand(RedisCmd) - BruteCmd.AddCommand(RdpCmd) - BruteCmd.AddCommand(MysqlCmd) - BruteCmd.AddCommand(MssqlCmd) - BruteCmd.AddCommand(FtpCmd) - BruteCmd.AddCommand(PostgreCmd) - BruteCmd.AddCommand(MongoCmd) - rootCmd.AddCommand(BruteCmd) -} - -var BurpModule = map[string]interface{}{ - "ssh": SshConnByUser, - "mysql": MySQLConn, - "mssql": MssqlConn, - "redis": RedisAuthConn, - "unredis": RedisUnAuthConn, // redis 未授权 - "postgres": PostgreConn, - "smb": SmbConn, - "ftp": FtpConn, - "rdp": RdpConn, - "winrm": WinRMAuth, - "mongodb": MongoAuth, - "unmongodb": MongoUnAuth, // mongodb 未授权 -} - -func BurpCall(EncryptMap map[string]interface{}, name string, params ...interface{}) []reflect.Value { - f := reflect.ValueOf(EncryptMap[name]) // 获取map键位name的值 - if len(params) != f.Type().NumIn() { // 如果参数的值不等于函数所需要的值 - log.Println(fmt.Sprintf("[ERROR] Burp Call Func key name %s is failed", name)) - os.Exit(1) - } - args := make([]reflect.Value, len(params)) - for k, param := range params { - if param == "" || param == 0 { - continue - } - //Println()(param) - args[k] = reflect.ValueOf(param) - } - //Println()(args) - //fmt.Println(args) - return f.Call(args) // 调用函数并返回结果 -} - -func SwitchBurp(service string, users []string, pass []string, hosts []string, port int, thread int, timeout time.Duration, Domain string) { - // 传入的参数均为3个 - // 调用方式 - var tunnel = make(chan string, 20) - var wg sync.WaitGroup - go func() { - for _, ip := range hosts { - tunnel <- ip - } - }() - for i := 0; i < len(hosts); i++ { - wg.Add(1) - _ = ants.Submit(func() { - ip := <-tunnel - burpTask(ip, service, users, pass, port, thread, timeout, Domain, true, false, nil) - wg.Done() - }) - } - wg.Wait() - Println(fmt.Sprintf(Clearln+"[*] brute %s done", service)) - - //Println()(service,users,pass,hosts,port,thread,BurpModule) -} - -/*** -* 从新计算爆破方式,之前的爆破是采用分割user进行的,但是发现,user数量会远少于password,所以按照password进行分割 - */ - -func burpTask(host, service string, users []string, pass []string, port int, thread int, timeout time.Duration, Domain string, run bool, jsonbool bool, out *JsonOut) { - var t int - var wg sync.WaitGroup - if len(pass) <= thread { - t = len(pass) - } else { - // 计算user数量 - t = thread // 协程数量 - } - - num := int(math.Ceil(float64(len(pass)) / float64(thread))) // 每个协程的user数量 - // 分割用户名 - all := map[int][]string{} - for i := 1; i <= t; i++ { - for j := 0; j < num; j++ { - tmp := (i-1)*num + j - if tmp < len(pass) { - all[i] = append(all[i], pass[tmp]) - } - } - } - if run { - go func() { - for { - for _, r := range `-\|/` { - fmt.Printf("\r%c brute: wating ... %c", r, r) - time.Sleep(200 * time.Millisecond) - } - } - }() - } - if service == "redis" && run == true { - BurpCall(BurpModule, "unredis", config.HostIn{Host: host, Port: BrutePort, TimeOut: TimeDuration}, "test", "test") - } - if service == "mongodb" && run == true { - BurpCall(BurpModule, "unmongodb", config.HostIn{Host: host, Port: BrutePort, TimeOut: TimeDuration}, "test", "test") - } - //Println()(all,num,t) - for i := 1; i <= t; i++ { - wg.Add(1) - tmp := all[i] - _ = ants.Submit(func() { - for _, p := range tmp { - for _, u := range users { - if strings.Contains(p, "{user}") { - p = strings.ReplaceAll(p, "{user}", p) - } - if u == "" || p == "" { - continue - } else { - result := BurpCall(BurpModule, service, config.HostIn{Host: host, Port: port, TimeOut: time.Duration(timeout), Domain: Domain}, u, p) - burpStatus(result, service, host, Domain, u, p, jsonbool, out) - } - } - } - wg.Done() - }) - } - wg.Wait() -} - -func burpStatus(result []reflect.Value, service, host, domain, user, pass string, jsonbool bool, out *JsonOut) { - var lock sync.Mutex - // 这里是判断类型并返回结果的函数 - if len(result) > 0 { - for _, v := range result { - switch v.Kind() { - case reflect.Bool: - if v.Bool() == true { - if domain != "" { - domain = domain + "\\" - } - if jsonbool == true { - // 加锁 - lock.Lock() - out.WeakPass = append(out.WeakPass, map[string]map[string]string{service: {user: pass}}) - lock.Unlock() - } - Println(fmt.Sprintf(Clearln+`[+] %s brute %s success [%v%s:%s]`, host, service, domain, user, pass)) - } - } - } - } -} - -func Readiness(file *os.File) []string { - var readiness []string /*定义一个空切片用于存储遍历后的数据*/ - buf := bufio.NewReader(file) /*建立一个缓冲区,将文本内容写入缓冲区*/ - for { - data, errR := buf.ReadBytes('\n') /*读取到\n截至*/ - if errR != nil { - if errR == io.EOF { - break - } - return readiness - } - str := strings.TrimSpace(string(data)) - // 修复读取时出现空的导致抛出panic - if str == "" { - continue - } - - readiness = append(readiness, str) /*将去除换行符的字符串写入切片*/ - } - return readiness -} - -func ReadTextToDic(service, user, pass string) ([]string, []string) { - var ( - userdic = config.Userdict[service] - passdic = config.Passwords - ) - // 入过不包含.txt的话,按照用户名和密码来算。其中 - if user != "" && !strings.Contains(user, ".txt") { - userdic = strings.Split(user, ",") - } - if pass != "" && !strings.Contains(pass, ".txt") { - passdic = strings.Split(pass, ",") - } - - if user != "" && strings.Contains(user, ".txt") { - userive, err := os.Open(user) - if err != nil { - Println(fmt.Sprintf(Clearln+"[ERROR] Open %s is failed,please check your user dic path", UserDic)) - return []string{}, []string{} - } - userdic = Readiness(userive) - } - if pass != "" && strings.Contains(pass, ".txt") { - passive, err := os.Open(pass) - if err != nil { - Println(fmt.Sprintf(Clearln+"[ERROR] Open %s is failed,please check your pass dic path", PassDic)) - return []string{}, []string{} - } - passdic = Readiness(passive) - } - return userdic, passdic -} +package cmd + +import ( + "Yasso/config" + "bufio" + "fmt" + "github.com/panjf2000/ants/v2" + "github.com/spf13/cobra" + "io" + "log" + "math" + "os" + "reflect" + "strings" + "sync" + "time" +) + +// 爆破模块 + +const ( + Clearln = "\r\x1b[2K" +) + +var BruteCmd = &cobra.Command{ + Use: "crack", + Short: "crack module and extend tool", + Run: func(cmd *cobra.Command, args []string) { + cmd.DisableFlagsInUseLine = true + _ = cmd.Help() + }, +} + +func init() { + // 添加全局变量 + BruteCmd.PersistentFlags().StringVarP(&Hosts, "hosts", "H", "", "to crack hosts address or ips.txt path (crack Must)") + BruteCmd.PersistentFlags().IntVar(&BrutePort, "port", 0, "to crack hosts port (if not set use default)") + BruteCmd.PersistentFlags().IntVar(&Runtime, "runtime", 100, "set crack thread number") + BruteCmd.PersistentFlags().BoolVarP(&BruteFlag, "crack", "", false, "make sure to use crack") + BruteCmd.PersistentFlags().DurationVar(&TimeDuration, "timeout", 1*time.Second, "crack module timeout(.eg) 1s (ns,ms,s,m,h)") + BruteCmd.PersistentFlags().StringVar(&PassDic, "pd", "", "pass dic path (.eg) pass.txt") + BruteCmd.PersistentFlags().StringVar(&UserDic, "ud", "", "user dic path (.eg) user.txt") + BruteCmd.PersistentFlags().StringVar(&ProxyHost, "proxy", "", "set socks5 proxy address") + BruteCmd.AddCommand(SshCmd) + BruteCmd.AddCommand(WinRMCmd) + BruteCmd.AddCommand(SmbCmd) + BruteCmd.AddCommand(Log4jCmd) + BruteCmd.AddCommand(RedisCmd) + BruteCmd.AddCommand(RdpCmd) + BruteCmd.AddCommand(MysqlCmd) + BruteCmd.AddCommand(MssqlCmd) + BruteCmd.AddCommand(FtpCmd) + BruteCmd.AddCommand(PostgreCmd) + BruteCmd.AddCommand(MongoCmd) + rootCmd.AddCommand(BruteCmd) +} + +var BurpModule = map[string]interface{}{ + "ssh": SshConnByUser, + "mysql": MySQLConn, + "mssql": MssqlConn, + "redis": RedisAuthConn, + "unredis": RedisUnAuthConn, // redis 未授权 + "postgres": PostgreConn, + "smb": SmbConn, + "ftp": FtpConn, + "rdp": RdpConn, + "winrm": WinRMAuth, + "mongodb": MongoAuth, + "unmongodb": MongoUnAuth, // mongodb 未授权 +} + +func BurpCall(EncryptMap map[string]interface{}, name string, params ...interface{}) []reflect.Value { + f := reflect.ValueOf(EncryptMap[name]) // 获取map键位name的值 + if len(params) != f.Type().NumIn() { // 如果参数的值不等于函数所需要的值 + log.Println(fmt.Sprintf("[ERROR] Burp Call Func key name %s is failed", name)) + os.Exit(1) + } + args := make([]reflect.Value, len(params)) + for k, param := range params { + if param == "" || param == 0 { + continue + } + //Println()(param) + args[k] = reflect.ValueOf(param) + } + //Println()(args) + //fmt.Println(args) + return f.Call(args) // 调用函数并返回结果 +} + +func SwitchBurp(service string, users []string, pass []string, hosts []string, port int, thread int, timeout time.Duration, Domain string) { + // 传入的参数均为3个 + // 调用方式 + var tunnel = make(chan string, 20) + var wg sync.WaitGroup + go func() { + for _, ip := range hosts { + tunnel <- ip + } + }() + for i := 0; i < len(hosts); i++ { + wg.Add(1) + _ = ants.Submit(func() { + ip := <-tunnel + burpTask(ip, service, users, pass, port, thread, timeout, Domain, true, false, nil) + wg.Done() + }) + } + wg.Wait() + Println(fmt.Sprintf(Clearln+"[*] brute %s done", service)) + + //Println()(service,users,pass,hosts,port,thread,BurpModule) +} + +/*** +* 从新计算爆破方式,之前的爆破是采用分割user进行的,但是发现,user数量会远少于password,所以按照password进行分割 + */ + +func burpTask(host, service string, users []string, pass []string, port int, thread int, timeout time.Duration, Domain string, run bool, jsonbool bool, out *JsonOut) { + var t int + var wg sync.WaitGroup + if len(pass) <= thread { + t = len(pass) + } else { + // 计算user数量 + t = thread // 协程数量 + } + + num := int(math.Ceil(float64(len(pass)) / float64(thread))) // 每个协程的user数量 + // 分割用户名 + all := map[int][]string{} + for i := 1; i <= t; i++ { + for j := 0; j < num; j++ { + tmp := (i-1)*num + j + if tmp < len(pass) { + all[i] = append(all[i], pass[tmp]) + } + } + } + if run { + go func() { + for { + for _, r := range `-\|/` { + fmt.Printf("\r%c brute: wating ... %c", r, r) + time.Sleep(200 * time.Millisecond) + } + } + }() + } + if service == "redis" && run == true { + BurpCall(BurpModule, "unredis", config.HostIn{Host: host, Port: BrutePort, TimeOut: TimeDuration}, "test", "test") + } + if service == "mongodb" && run == true { + BurpCall(BurpModule, "unmongodb", config.HostIn{Host: host, Port: BrutePort, TimeOut: TimeDuration}, "test", "test") + } + //Println()(all,num,t) + for i := 1; i <= t; i++ { + wg.Add(1) + tmp := all[i] + _ = ants.Submit(func() { + for _, p := range tmp { + for _, u := range users { + if strings.Contains(p, "{user}") { + p = strings.ReplaceAll(p, "{user}", p) + } + if u == "" || p == "" { + continue + } else { + result := BurpCall(BurpModule, service, config.HostIn{Host: host, Port: port, TimeOut: time.Duration(timeout), Domain: Domain}, u, p) + burpStatus(result, service, host, Domain, u, p, jsonbool, out) + } + } + } + wg.Done() + }) + } + wg.Wait() +} + +func burpStatus(result []reflect.Value, service, host, domain, user, pass string, jsonbool bool, out *JsonOut) { + var lock sync.Mutex + // 这里是判断类型并返回结果的函数 + if len(result) > 0 { + for _, v := range result { + switch v.Kind() { + case reflect.Bool: + if v.Bool() == true { + if domain != "" { + domain = domain + "\\" + } + if jsonbool == true { + // 加锁 + lock.Lock() + out.WeakPass = append(out.WeakPass, map[string]map[string]string{service: {user: pass}}) + lock.Unlock() + } + Println(fmt.Sprintf(Clearln+`[+] %s brute %s success [%v%s:%s]`, host, service, domain, user, pass)) + } + } + } + } +} + +func Readiness(file *os.File) []string { + var readiness []string /*定义一个空切片用于存储遍历后的数据*/ + buf := bufio.NewReader(file) /*建立一个缓冲区,将文本内容写入缓冲区*/ + for { + data, errR := buf.ReadBytes('\n') /*读取到\n截至*/ + if errR != nil { + if errR == io.EOF { + break + } + return readiness + } + str := strings.TrimSpace(string(data)) + // 修复读取时出现空的导致抛出panic + if str == "" { + continue + } + + readiness = append(readiness, str) /*将去除换行符的字符串写入切片*/ + } + return readiness +} + +func ReadTextToDic(service, user, pass string) ([]string, []string) { + var ( + userdic = config.Userdict[service] + passdic = config.Passwords + ) + // 入过不包含.txt的话,按照用户名和密码来算。其中 + if user != "" && !strings.Contains(user, ".txt") { + userdic = strings.Split(user, ",") + } + if pass != "" && !strings.Contains(pass, ".txt") { + passdic = strings.Split(pass, ",") + } + + if user != "" && strings.Contains(user, ".txt") { + userive, err := os.Open(user) + if err != nil { + Println(fmt.Sprintf(Clearln+"[ERROR] Open %s is failed,please check your user dic path", UserDic)) + return []string{}, []string{} + } + userdic = Readiness(userive) + } + if pass != "" && strings.Contains(pass, ".txt") { + passive, err := os.Open(pass) + if err != nil { + Println(fmt.Sprintf(Clearln+"[ERROR] Open %s is failed,please check your pass dic path", PassDic)) + return []string{}, []string{} + } + passdic = Readiness(passive) + } + return userdic, passdic +} diff --git a/cmd/redis.go b/cmd/redis.go index 0fd49d6..064d7f7 100644 --- a/cmd/redis.go +++ b/cmd/redis.go @@ -147,7 +147,7 @@ func RedisUnAuthConn(info config.HostIn, user, pass string) (net.Conn, bool, err if strings.Contains(reply, "redis_version") { flag = true conf := RedisInfo(conn, reply) - Println(fmt.Sprintf(Clearln+"[+] Redis %s:%v unauthorized\n[+] os:[%v] path:[%v] dbfilename:[%v] pid:[%v]", info.Host, info.Port, conf.OS, conf.ConfigPath, conf.DbFileName, conf.PID)) + Println(fmt.Sprintf("%v[+] Redis %s:%v unauthorized dbfilename:[%v] ", Clearln, info.Host, info.Port, conf.DbFileName)) } return conn, flag, nil } @@ -176,10 +176,10 @@ func RedisReply(conn net.Conn) (string, error) { func RedisInfo(conn net.Conn, reply string) RedisConfig { var ( // 第0个是#Server - version = strings.Split(strings.Split(reply, "\r\n")[2], ":")[1] // redis version - os = strings.Split(strings.Split(reply, "\r\n")[7], ":")[1] // os - pid = strings.Split(strings.Split(reply, "\r\n")[11], ":")[1] // redis pid - install = strings.Split(strings.Split(reply, "\r\n")[18], ":")[1] + //version = strings.Split(strings.Split(reply, "\r\n")[2], ":")[1] // redis version + //os = strings.Split(strings.Split(reply, "\r\n")[7], ":")[1] // os + //pid = strings.Split(strings.Split(reply, "\r\n")[11], ":")[1] // redis pid + //install = strings.Split(strings.Split(reply, "\r\n")[18], ":")[1] dbfilename string ) // 读取filename @@ -199,10 +199,10 @@ func RedisInfo(conn net.Conn, reply string) RedisConfig { } var redisConfig = RedisConfig{ - Version: version, - OS: os, - PID: pid, - ConfigPath: install, + //Version: version, + //OS: os, + //PID: pid, + //ConfigPath: install, DbFileName: dbfilename, } //Println()(redisConfig) diff --git a/cmd/ssh.go b/cmd/ssh.go index d3f4761..f0f151f 100644 --- a/cmd/ssh.go +++ b/cmd/ssh.go @@ -1,194 +1,194 @@ -package cmd - -import ( - "Yasso/config" - "fmt" - "github.com/spf13/cobra" - "golang.org/x/crypto/ssh" - "golang.org/x/crypto/ssh/terminal" - "io/ioutil" - "os" - "path" -) - -/* -模块完成时间2021年12月28日,主要用于ssh爆破,连接,扫描22端口 -*/ - -var SshCmd = &cobra.Command{ - Use: "ssh", - Short: "SSH burst and SSH extend tools (support proxy)", - Run: func(cmd *cobra.Command, args []string) { - if Hosts == "" && ConnHost == "" { - _ = cmd.Help() - } else { - BruteSshByUser() - } - }, -} - -func init() { - SshCmd.Flags().StringVar(&ConnHost, "hostname", "", "Open an interactive SSH at that address(brute param need false)") - SshCmd.Flags().StringVar(&LoginUser, "user", "", "Login ssh username") - SshCmd.Flags().StringVar(&LoginPass, "pass", "", "Login ssh password") - SshCmd.Flags().StringVar(&LoginPublicKey, "key", "", "ssh public key path") -} - -func BruteSshByUser() { - if BrutePort == 0 { - BrutePort = 22 - } - var ips []string - var err error - if Hosts != "" && ConnHost == "" { - ips, err = ResolveIPS(Hosts) - if err != nil { - Println(fmt.Sprintf("resolve hosts address failed %v", err)) - return - } - if BruteFlag == true { - users, pass := ReadTextToDic("ssh", UserDic, PassDic) - //fmt.Println(users, pass) - Println(Clearln + "[*] Brute Module [ssh]") - Println(fmt.Sprintf(Clearln+"[*] Have [user:%v] [pass:%v] [request:%v]", len(users), len(pass), len(users)*len(pass)*len(ips))) - SwitchBurp("ssh", users, pass, ips, BrutePort, Runtime, TimeDuration, "") - } else { - Println(Clearln + "[*] May be you want to brute? try to add --crack") - } - } - if ConnHost != "" && Hosts == "" && (LoginUser != "" && (LoginPass != "" || LoginPublicKey != "")) && BruteFlag != true { - if LoginUser != "" && LoginPass != "" { - client, status, err := SshConnByUser(config.HostIn{Host: ConnHost, Port: BrutePort, TimeOut: TimeDuration}, LoginUser, LoginPass) - if err != nil { - Println(fmt.Sprintf(Clearln+"[-] Login ssh failed %v", err)) - return - } - if status == true { - //认证成功 - SshLogin(client) - } else { - Println(Clearln + "[-] The username or password is incorrect") - return - } - } - if LoginPublicKey != "" && LoginUser != "" { - client, status, err := sshConnByKey(config.HostIn{Host: ConnHost, Port: BrutePort, TimeOut: TimeDuration, PublicKey: LoginPublicKey}, LoginUser) - if err != nil { - Println(fmt.Sprintf(Clearln+"[-] Login ssh failed %v", err)) - return - } - if status == true { - //认证成功 - SshLogin(client) - return - } else { - Println(Clearln + "[-] The username or password is incorrect") - return - } - } - } - if Hosts == "" && ConnHost != "" && BruteFlag == false && (LoginUser == "" || LoginPublicKey == "") { - Println(Clearln + "[*] May be you want login ssh? try to add user and (user' key) or (user' pass)") - return - } -} - -func SshConnByUser(info config.HostIn, user, pass string) (*ssh.Client, bool, error) { - // 走socks5代理的ssh连接 - sshConfig := &ssh.ClientConfig{User: user, Auth: []ssh.AuthMethod{ssh.Password(pass)}, HostKeyCallback: ssh.InsecureIgnoreHostKey(), Timeout: info.TimeOut} - con, err := GetConn(fmt.Sprintf("%v:%v", info.Host, info.Port), info.TimeOut) - if err != nil { - return nil, false, err - } - c, ch, re, err := ssh.NewClientConn(con, fmt.Sprintf("%v:%v", info.Host, info.Port), sshConfig) - if err != nil { - return nil, false, err - } - return ssh.NewClient(c, ch, re), true, err -} - -func sshConnByKey(info config.HostIn, user string) (*ssh.Client, bool, error) { - var ( - err error - HomePath string - key []byte - ) - switch { - case info.PublicKey == "": - HomePath, err = os.UserHomeDir() - if err != nil { - return nil, false, err - } - key, err = ioutil.ReadFile(path.Join(HomePath, ".ssh", "id_rsa")) - if err != nil { - return nil, false, err - } - case info.PublicKey != "": - key, err = ioutil.ReadFile(info.PublicKey) - if err != nil { - return nil, false, err - } - } - signer, err := ssh.ParsePrivateKey(key) - if err != nil { - return nil, false, err - } - sshConfig := &ssh.ClientConfig{ - User: user, - Auth: []ssh.AuthMethod{ - ssh.PublicKeys(signer), - }, - Timeout: info.TimeOut, - HostKeyCallback: ssh.InsecureIgnoreHostKey(), - } - con, err := GetConn(fmt.Sprintf("%v:%v", info.Host, info.Port), info.TimeOut) - if err != nil { - return nil, false, err - } - - c, ch, re, err := ssh.NewClientConn(con, fmt.Sprintf("%v:%v", info.Host, info.Port), sshConfig) - if err != nil { - return nil, false, err - } - return ssh.NewClient(c, ch, re), true, err -} - -// ssh 完全交互式登陆 - -func SshLogin(client *ssh.Client) { - defer client.Close() - session, err := client.NewSession() - if err != nil { - Println(fmt.Sprintf("new ssh session failed %v", err)) - return - } - defer session.Close() - session.Stdout = os.Stdout - session.Stderr = os.Stderr - session.Stdin = os.Stdin - modes := ssh.TerminalModes{ - ssh.ECHO: 1, - ssh.TTY_OP_ISPEED: 14400, - ssh.TTY_OP_OSPEED: 14400, - ssh.VSTATUS: 1, - } - fd := int(os.Stdin.Fd()) - oldState, err := terminal.MakeRaw(fd) - if err != nil { - Println(fmt.Sprintf("terminal failed %v", err)) - } - defer terminal.Restore(fd, oldState) - w, h, err := terminal.GetSize(fd) - if err = session.RequestPty("xterm-256color", h, w, modes); err != nil { - Println(fmt.Sprintf("Session Request new xterm failed %v", err)) - return - } - if err = session.Shell(); err != nil { - Println(fmt.Sprintf("Session start shell failed %v", err)) - return - } - if err = session.Wait(); err != nil { - Println(fmt.Sprintf("Session wait failed %v", err)) - return - } -} +package cmd + +import ( + "Yasso/config" + "fmt" + "github.com/spf13/cobra" + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/terminal" + "io/ioutil" + "os" + "path" +) + +/* +模块完成时间2021年12月28日,主要用于ssh爆破,连接,扫描22端口 +*/ + +var SshCmd = &cobra.Command{ + Use: "ssh", + Short: "SSH burst and SSH extend tools (support proxy)", + Run: func(cmd *cobra.Command, args []string) { + if Hosts == "" && ConnHost == "" { + _ = cmd.Help() + } else { + BruteSshByUser() + } + }, +} + +func init() { + SshCmd.Flags().StringVar(&ConnHost, "hostname", "", "Open an interactive SSH at that address(brute param need false)") + SshCmd.Flags().StringVar(&LoginUser, "user", "", "Login ssh username") + SshCmd.Flags().StringVar(&LoginPass, "pass", "", "Login ssh password") + SshCmd.Flags().StringVar(&LoginPublicKey, "key", "", "ssh public key path") +} + +func BruteSshByUser() { + if BrutePort == 0 { + BrutePort = 22 + } + var ips []string + var err error + if Hosts != "" && ConnHost == "" { + ips, err = ResolveIPS(Hosts) + if err != nil { + Println(fmt.Sprintf("resolve hosts address failed %v", err)) + return + } + if BruteFlag == true { + users, pass := ReadTextToDic("ssh", UserDic, PassDic) + //fmt.Println(users, pass) + Println(Clearln + "[*] Brute Module [ssh]") + Println(fmt.Sprintf(Clearln+"[*] Have [user:%v] [pass:%v] [request:%v]", len(users), len(pass), len(users)*len(pass)*len(ips))) + SwitchBurp("ssh", users, pass, ips, BrutePort, Runtime, TimeDuration, "") + } else { + Println(Clearln + "[*] May be you want to brute? try to add --crack") + } + } + if ConnHost != "" && Hosts == "" && (LoginUser != "" && (LoginPass != "" || LoginPublicKey != "")) && BruteFlag != true { + if LoginUser != "" && LoginPass != "" { + client, status, err := SshConnByUser(config.HostIn{Host: ConnHost, Port: BrutePort, TimeOut: TimeDuration}, LoginUser, LoginPass) + if err != nil { + Println(fmt.Sprintf(Clearln+"[-] Login ssh failed %v", err)) + return + } + if status == true { + //认证成功 + SshLogin(client) + } else { + Println(Clearln + "[-] The username or password is incorrect") + return + } + } + if LoginPublicKey != "" && LoginUser != "" { + client, status, err := sshConnByKey(config.HostIn{Host: ConnHost, Port: BrutePort, TimeOut: TimeDuration, PublicKey: LoginPublicKey}, LoginUser) + if err != nil { + Println(fmt.Sprintf(Clearln+"[-] Login ssh failed %v", err)) + return + } + if status == true { + //认证成功 + SshLogin(client) + return + } else { + Println(Clearln + "[-] The username or password is incorrect") + return + } + } + } + if Hosts == "" && ConnHost != "" && BruteFlag == false && (LoginUser == "" || LoginPublicKey == "") { + Println(Clearln + "[*] May be you want login ssh? try to add user and (user' key) or (user' pass)") + return + } +} + +func SshConnByUser(info config.HostIn, user, pass string) (*ssh.Client, bool, error) { + // 走socks5代理的ssh连接 + sshConfig := &ssh.ClientConfig{User: user, Auth: []ssh.AuthMethod{ssh.Password(pass)}, HostKeyCallback: ssh.InsecureIgnoreHostKey(), Timeout: info.TimeOut} + con, err := GetConn(fmt.Sprintf("%v:%v", info.Host, info.Port), info.TimeOut) + if err != nil { + return nil, false, err + } + c, ch, re, err := ssh.NewClientConn(con, fmt.Sprintf("%v:%v", info.Host, info.Port), sshConfig) + if err != nil { + return nil, false, err + } + return ssh.NewClient(c, ch, re), true, err +} + +func sshConnByKey(info config.HostIn, user string) (*ssh.Client, bool, error) { + var ( + err error + HomePath string + key []byte + ) + switch { + case info.PublicKey == "": + HomePath, err = os.UserHomeDir() + if err != nil { + return nil, false, err + } + key, err = ioutil.ReadFile(path.Join(HomePath, ".ssh", "id_rsa")) + if err != nil { + return nil, false, err + } + case info.PublicKey != "": + key, err = ioutil.ReadFile(info.PublicKey) + if err != nil { + return nil, false, err + } + } + signer, err := ssh.ParsePrivateKey(key) + if err != nil { + return nil, false, err + } + sshConfig := &ssh.ClientConfig{ + User: user, + Auth: []ssh.AuthMethod{ + ssh.PublicKeys(signer), + }, + Timeout: info.TimeOut, + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + } + con, err := GetConn(fmt.Sprintf("%v:%v", info.Host, info.Port), info.TimeOut) + if err != nil { + return nil, false, err + } + + c, ch, re, err := ssh.NewClientConn(con, fmt.Sprintf("%v:%v", info.Host, info.Port), sshConfig) + if err != nil { + return nil, false, err + } + return ssh.NewClient(c, ch, re), true, err +} + +// ssh 完全交互式登陆 + +func SshLogin(client *ssh.Client) { + defer client.Close() + session, err := client.NewSession() + if err != nil { + Println(fmt.Sprintf("new ssh session failed %v", err)) + return + } + defer session.Close() + session.Stdout = os.Stdout + session.Stderr = os.Stderr + session.Stdin = os.Stdin + modes := ssh.TerminalModes{ + ssh.ECHO: 1, + ssh.TTY_OP_ISPEED: 14400, + ssh.TTY_OP_OSPEED: 14400, + ssh.VSTATUS: 1, + } + fd := int(os.Stdin.Fd()) + oldState, err := terminal.MakeRaw(fd) + if err != nil { + Println(fmt.Sprintf("terminal failed %v", err)) + } + defer terminal.Restore(fd, oldState) + w, h, err := terminal.GetSize(fd) + if err = session.RequestPty("xterm-256color", h, w, modes); err != nil { + Println(fmt.Sprintf("Session Request new xterm failed %v", err)) + return + } + if err = session.Shell(); err != nil { + Println(fmt.Sprintf("Session start shell failed %v", err)) + return + } + if err = session.Wait(); err != nil { + Println(fmt.Sprintf("Session wait failed %v", err)) + return + } +}