Skip to content

unauthenticated-public-key-exchange

Ensure for secure connections where the public key exchange is verified against a list of trusted entitities

Public key exchange is vulnerable to man-in-the-middle (MITM) attack without authentication. Authentication can be performed using a mutually trusted certificate authority (or using a known, authorized host key).

Examples

Insecure Example

package main
import (
    "bytes"
    "fmt"
    "golang.org/x/crypto/ssh"
    "log"
    "os"
    "strings"
)
func errorCheck(err error, msg string) {
    if err != nil {
        log.Fatal(msg)
    }
}
func insecureConfig(user, pass string) *ssh.ClientConfig {
    return &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.Password(pass),
        },
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }
}
func connect(config *ssh.ClientConfig, host string) {
    client, err := ssh.Dial("tcp", host, config)
    errorCheck(err, "Cannot dial")
    defer client.Close()

    session, err := client.NewSession()
    errorCheck(err, "Cannot establish session")
    defer session.Close()

    var b bytes.Buffer
    session.Stdout = &b
    err = session.Run("/usr/bin/whoami")
    errorCheck(err, "Cannot send command")

    banner := b.String()
    if strings.Contains(banner, config.User) {
        fmt.Println("It works!")
    } else {
        fmt.Println("Looks like it did not work!?")
    }
}
func main() {
    host, user, pass := os.Args[1], os.Args[2], os.Args[3]
    connect(insecureConfig(user, pass), host)
}

Secure Example

package main
import (
    "bytes"
    "fmt"
    "golang.org/x/crypto/ssh"
    "log"
    "os"
    "strings"
)
func errorCheck(err error, msg string) {
    if err != nil {
        log.Fatal(msg)
    }
}
func secureConfig(user, pass, hostKey string) *ssh.ClientConfig {
    pinnedHostKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(hostKey))
    errorCheck(err, "Cannot parse SSH host key")
    return &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.Password(pass),
        },
        HostKeyCallback: ssh.FixedHostKey(pinnedHostKey),
    }
}
func connect(config *ssh.ClientConfig, host string) {
    client, err := ssh.Dial("tcp", host, config)
    errorCheck(err, "Cannot dial")
    defer client.Close()

    session, err := client.NewSession()
    errorCheck(err, "Cannot establish session")
    defer session.Close()

    var b bytes.Buffer
    session.Stdout = &b
    err = session.Run("/usr/bin/whoami")
    errorCheck(err, "Cannot send command")

    banner := b.String()
    if strings.Contains(banner, config.User) {
        fmt.Println("It works!")
    } else {
        fmt.Println("Looks like it did not work!?")
    }
}
func main() {
    host, user, pass, hostKey := os.Args[1], os.Args[2], os.Args[3], os.Args[4]
    connect(secureConfig(user, pass, hostKey), host)
}