You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
3.7 KiB
Go
146 lines
3.7 KiB
Go
7 months ago
|
package net
|
||
|
|
||
|
import (
|
||
|
"b612.me/starcrypto"
|
||
|
"b612.me/starlog"
|
||
|
"b612.me/starnet"
|
||
|
"crypto/elliptic"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"github.com/spf13/cobra"
|
||
|
"golang.org/x/crypto/ssh"
|
||
|
"net"
|
||
|
"os"
|
||
|
"os/signal"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
listenAddr string
|
||
|
keyFile string
|
||
|
KeyPasswd string
|
||
|
outpath string
|
||
|
curlUrl string
|
||
|
curlArg []string
|
||
|
)
|
||
|
|
||
|
func init() {
|
||
|
cmdSSHJar.Flags().StringVarP(&listenAddr, "listen", "l", "0.0.0.0:22", "监听地址")
|
||
|
cmdSSHJar.Flags().StringVarP(&keyFile, "key", "k", "", "私钥文件")
|
||
|
cmdSSHJar.Flags().StringVarP(&KeyPasswd, "passwd", "p", "", "私钥密码")
|
||
|
cmdSSHJar.Flags().StringVarP(&outpath, "output", "o", "", "输出文件")
|
||
|
}
|
||
|
|
||
|
var cmdSSHJar = &cobra.Command{
|
||
|
Use: "sshjar",
|
||
|
Short: "SSH蜜罐",
|
||
|
Long: "SSH蜜罐",
|
||
|
Run: func(cmd *cobra.Command, args []string) {
|
||
|
runSSHHoneyJar(listenAddr, keyFile, KeyPasswd, outpath)
|
||
|
},
|
||
|
}
|
||
|
|
||
|
func runSSHHoneyJar(listenAddr, keyFile, KeyPasswd, outpath string) {
|
||
|
var f *os.File
|
||
|
var err error
|
||
|
if outpath != "" {
|
||
|
f, err = os.OpenFile(outpath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
|
||
|
if err != nil {
|
||
|
starlog.Errorf("Failed to open file %s (%s)", outpath, err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
defer f.Close()
|
||
|
config := &ssh.ServerConfig{
|
||
|
// 密码验证回调函数
|
||
|
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
|
||
|
starlog.Infof("Login attempt from %s with %s %s\n", c.RemoteAddr(), c.User(), string(pass))
|
||
|
data := []string{c.RemoteAddr().String(), c.User(), string(pass)}
|
||
|
bts, _ := json.Marshal(data)
|
||
|
if f != nil {
|
||
|
f.Write(bts)
|
||
|
f.Write([]byte("\n"))
|
||
|
}
|
||
|
if curlUrl != "" {
|
||
|
go func() {
|
||
|
data := map[string]string{
|
||
|
"ip": c.RemoteAddr().String(),
|
||
|
"user": c.User(),
|
||
|
"passwd": string(pass),
|
||
|
}
|
||
|
if curlArg != nil && len(curlArg) > 0 {
|
||
|
for _, v := range curlArg {
|
||
|
args := strings.SplitN(v, ":", 2)
|
||
|
if len(args) == 2 {
|
||
|
data[args[0]] = args[1]
|
||
|
}
|
||
|
}
|
||
|
starnet.Curl(starnet.NewRequests(curlUrl, []byte(starnet.BuildQuery(data)), "POST"))
|
||
|
}
|
||
|
}()
|
||
|
}
|
||
|
return nil, fmt.Errorf("password rejected for %q", c.User())
|
||
|
},
|
||
|
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
|
||
|
return nil, fmt.Errorf("public key rejected for %q", conn.User())
|
||
|
},
|
||
|
}
|
||
|
if keyFile == "" {
|
||
|
secKey, _, err := starcrypto.GenerateEcdsaKey(elliptic.P256())
|
||
|
if err != nil {
|
||
|
starlog.Errorf("Failed to generate ECDSA key (%s)", err)
|
||
|
return
|
||
|
}
|
||
|
key, err := ssh.NewSignerFromKey(secKey)
|
||
|
if err != nil {
|
||
|
starlog.Errorf("Failed to generate signer from key (%s)", err)
|
||
|
return
|
||
|
}
|
||
|
config.AddHostKey(key)
|
||
|
} else {
|
||
|
keyByte, err := os.ReadFile(keyFile)
|
||
|
if err != nil {
|
||
|
starlog.Errorf("Failed to read private key from %s (%s)", keyFile, err)
|
||
|
return
|
||
|
}
|
||
|
var key ssh.Signer
|
||
|
if KeyPasswd != "" {
|
||
|
key, err = ssh.ParsePrivateKeyWithPassphrase(keyByte, []byte(KeyPasswd))
|
||
|
} else {
|
||
|
key, err = ssh.ParsePrivateKey(keyByte)
|
||
|
}
|
||
|
if err != nil {
|
||
|
starlog.Errorf("Failed to load private key from %s (%s)", keyFile, err)
|
||
|
return
|
||
|
}
|
||
|
config.AddHostKey(key)
|
||
|
}
|
||
|
listener, err := net.Listen("tcp", listenAddr)
|
||
|
if err != nil {
|
||
|
starlog.Errorf("Failed to listen on %s (%s)", listenAddr, err)
|
||
|
return
|
||
|
}
|
||
|
starlog.Noticeln("SSH HoneyJar is listening on", listenAddr)
|
||
|
sig := make(chan os.Signal, 1)
|
||
|
signal.Notify(sig, os.Interrupt, os.Kill)
|
||
|
for {
|
||
|
select {
|
||
|
case <-sig:
|
||
|
starlog.Noticef("SSH HoneyJar is shutting down")
|
||
|
listener.Close()
|
||
|
return
|
||
|
default:
|
||
|
}
|
||
|
conn, err := listener.Accept()
|
||
|
if err != nil {
|
||
|
continue
|
||
|
}
|
||
|
starlog.Infof("New connection from %s\n", conn.RemoteAddr())
|
||
|
go func(conn net.Conn) {
|
||
|
ssh.NewServerConn(conn, config)
|
||
|
conn.Close()
|
||
|
}(conn)
|
||
|
}
|
||
|
|
||
|
}
|