I want to tunnel a subcommand through a connection, listening on a port, launching a subcommand (to connect to this port), and then sending data through the connection:
package main import ( "fmt" "net" "os" "os/exec" ) func main() { ln, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: localhost}) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } defer ln.Close() port := ln.Addr().(*net.TCPAddr).Port cmd := exec.Command( "git", "clone", fmt.Sprintf("git://127.0.0.1:%d/project.git", port), ) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Start(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } defer cmd.Process.Kill() errs := make(chan error, 1) go func() { errs <- cmd.Wait() }() conns := make(chan net.Conn, 1) go func() { conn, err := ln.Accept() if err == nil { conns <- conn } else { fmt.Println(err) errs <- err } }() select { case err := <-errs: fmt.Fprintln(os.Stderr, err) os.Exit(1) case conn := <-conns: defer conn.Close()
However, there is a race between the time we begin to listen to and the time when the subcommand actually connects to the listener, where another process can connect to the listener. I believe that this race can be used by an attacker to communicate with the process at the other end of the connection and achieve results that would otherwise require privilege escalation (for example, attacks requiring special permissions replace the git command with a malicious program or simply reading the contents of the cloned directory in this case).
Should this be a problem? If so, can this be prevented? Although the question is asked using Go as an example, answers and comments in any language are welcome.
source share