sudo - Is SetGID/SetUID on a Go[lang] binary safe? -


i've written simple program using yaml , mysql drivers intention of providing simple utility update database without exposing username , password credentials user executing program.

(i'm aware write in python or other scripting language , manage permissions delegations using i'd try different approach here, own edification).

after building program i've used chgrp sys dbcreds.yaml && chmod 0640 dbcreds.yaml , chgrp sys ./myprog && chmod g+s ./myprog (as root) ... , seems work. (i tested access denied, should be, prior setgid step).

i tested strace results in permission denied (as should be). (for fun ran ltrace -s on it; under linux. expected did not see many normal libc function calls ... through surprised have seen few pthread_....() , 1 malloc() calls in listing. guess go runtime link system library functions after all).

my question: safe? there known way cause go program, such (below) core dump or expose memory after has read these private credentials? there way drop sgid privs after i've read credentials? there examples of suid/sgid exploits on go binaries? there better way this?

one other note: find gopkg.in/yaml.v2 semantics bit disconcerting. in yaml file have like:

--- user me pw mypassword 

but in code have use user , pw (capitalized) rather using lower case have expected. presume implementation decision authors of goyaml. so?

#!go package main  import (     "fmt"     "database/sql"     _ "github.com/go-sql-driver/mysql"     "gopkg.in/yaml.v2"     "io/ioutil"     "os"     "strconv" )  type creds struct {     user string     pw   string }  func main() {      filename := "./dbcreds.yaml"     var creds creds     conf, err := ioutil.readfile(filename)     if err != nil {         panic(err)     }     err = yaml.unmarshal(conf, &creds)     if err != nil {         panic(err)     }      var arg1 int     arg1, err = strconv.atoi(os.args[1])     if err != nil {         panic(err.error()) // example purpose. should use proper error handling instead of panic     }      fmt.println("arg1: ", arg1, "\n")     dsn := fmt.sprintf("%s:%s@/mydatabase", creds.user, creds.pw)     db, err := sql.open("mysql", dsn)     if err != nil {         panic(err.error())     }     defer db.close()      err = db.ping()     if err != nil {         panic(err.error())     }      stmtout, err := db.prepare("select quant c id >= ?")     if err != nil {         panic(err.error())     }     defer stmtout.close()      rows, err := stmtout.query(arg1)     if err != nil {         panic(err.error())     }     defer rows.close()      rows.next() {         var quant int         err = rows.scan(&quant)         if err != nil {             panic(err.error())         }         fmt.println(quant)     } } 

a setuid/setgid go program reasonably safe, 1 major caveat. go setuid/setgid programs in general no more, , no less, secure c/c++ setuid/setgid programs.

it's true can force go program dump core running environment variable gotraceback=crash , sending signal. however, ok purposes because go program (try to) create core dump sending sigabrt signal. kernel not generate core dump setuid/setgid program killed signal.

the major caveat go on gnu/linux systems can not drop original user id. because of how setuid (and setgid, setgroups, setreuid, setregid, setresuid, , setresgid) implemented multi-threaded programs on gnu/linux. details @ http://golang.org/issue/1435 .

on final note uw , pw need capitalized because standard reflect package not permit writing unexported fields.


Comments

Popular posts from this blog

node.js - Using Node without global install -

How to access a php class file from PHPFox framework into javascript code written in simple HTML file? -

java - Null response to php query in android, even though php works properly -