package main import "syscall" import "os" import "os/exec" import "strings" import "fmt" // This program is a workaround for CVE-2020-14342 for people who // cannot update their system // This Golang program can be built and just copied over a vulnerable // system as Golang binaries have minimal to no dependencies. // It acts as a wrapper around the mount.cifs binary and can safely // use the SETUID bit if necessary. // On normal inputs it just forwards the call to the original // mount.cifs. On problematic inputs using shell metacharacters it // stops and exits. // // Installation // ============ // // Build the wrapper program // $ go build mount.cifs.wrap.go // // Move the real binary to an alternative name (make sure it matches // the variable below) // # mv /sbin/{,real.}mount.cifs // // Clear setuid bit and group/other bits // # chmod 700 /sbin/real.mount.cifs // // Copy the wrapper over under the original name // # cp mount.cifs.wrap /sbin/mount.cifs // // Set ownership and bits back (setuid only if necessary) // # chown root:root /sbin/mount.cifs // # chmod 6755 /sbin/mount.cifs var origMountPath = "/sbin/real.mount.cifs" var badChars = "\\$\"`" var checkOpts = []string{"username=", "user="} func isBadOpts(arg string) bool { for _, opt := range checkOpts { start := 0 for start < len(arg) { i := strings.Index(arg[start:], opt) if i < 0 { break } i += len(opt) end := strings.Index(arg[start+i:], ",") if end < 0 { end = len(arg) } val := arg[start:end] if strings.ContainsAny(val, badChars) { return true } start = end } } return false } func main() { binary, lookErr := exec.LookPath(origMountPath) if lookErr != nil { panic(lookErr) } env := os.Environ() args := []string{"mount.cifs"} for _, s := range os.Args[1:] { if isBadOpts(s) { fmt.Println("mount.cifs: invalid username") os.Exit(1) } args = append(args, s) } execErr := syscall.Exec(binary, args, env) if execErr != nil { panic(execErr) } }