1
1
Fork 0
mirror of https://tildegit.org/solderpunk/molly-brown synced 2024-04-28 00:35:00 +02:00

Drop privileges much more thoroughly, thanks nervuri! (see issue #16)

This commit is contained in:
Solderpunk 2023-02-19 13:17:24 +01:00
parent 182e58ffe3
commit 7fad754ff2
4 changed files with 90 additions and 26 deletions

16
main.go
View File

@ -7,7 +7,6 @@ import (
"log"
"os"
"os/signal"
"os/user"
"strconv"
"sync"
"syscall"
@ -44,18 +43,7 @@ func main() {
// If we are running as root, find the UID of the "nobody" user, before a
// chroot() possibly stops seeing /etc/passwd
uid := os.Getuid()
nobody_uid := -1
if uid == 0 {
nobody_user, err := user.Lookup(config.UnprivUsername)
if err != nil {
log.Fatal("Running as root but could not lookup UID for user " + config.UnprivUsername + ": " + err.Error())
}
nobody_uid, err = strconv.Atoi(nobody_user.Uid)
if err != nil {
log.Fatal("Running as root but could not lookup UID for user " + config.UnprivUsername + ": " + err.Error())
}
}
privInfo := getUserInfo(config)
// Chroot, if asked
if config.ChrootDir != "" {
@ -120,7 +108,7 @@ func main() {
}
// Apply security restrictions
enableSecurityRestrictions(config, nobody_uid, errorLog)
enableSecurityRestrictions(config, privInfo, errorLog)
// Create TLS listener
listener, err := tls.Listen("tcp", ":"+strconv.Itoa(config.Port), tlscfg)

View File

@ -5,21 +5,97 @@ package main
import (
"log"
"os"
"os/user"
"strconv"
"syscall"
)
func DropPrivs(config Config, nobody_uid int, errorLog *log.Logger) {
type userInfo struct {
uid int
euid int
gid int
egid int
supp_groups []int
is_setuid bool
is_setgid bool
root_user bool
root_prim_group bool
root_supp_group bool
need_drop bool
unpriv_uid int
unpriv_gid int
}
// Get our real and effective UIDs
uid := os.Getuid()
euid := os.Geteuid()
func getUserInfo(config Config) userInfo {
var ui userInfo
ui.uid = os.Getuid()
ui.euid = os.Geteuid()
ui.gid = os.Getgid()
ui.egid = os.Getegid()
supp_groups, err := os.Getgroups()
if err != nil {
log.Fatal("Could not get supplementary groups: ", err.Error())
}
ui.supp_groups = supp_groups
ui.unpriv_uid = -1
ui.unpriv_gid = -1
// Are we root or are we running as a setuid binary?
if uid == 0 || uid != euid {
err := syscall.Setuid(nobody_uid)
ui.is_setuid = ui.uid != ui.euid
ui.is_setgid = ui.gid != ui.egid
ui.root_user = ui.uid == 0 || ui.euid == 0
ui.root_prim_group = ui.gid == 0 || ui.egid == 0
for _, gid := range ui.supp_groups {
if gid == 0 {
ui.root_supp_group = true
break
}
}
ui.need_drop = ui.is_setuid || ui.is_setgid || ui.root_user || ui.root_prim_group || ui.root_supp_group
if ui.need_drop {
nobody_user, err := user.Lookup(config.UnprivUsername)
if err != nil {
errorLog.Println("Could not setuid to " + strconv.Itoa(uid) + ": " + err.Error())
log.Fatal("Running as root but could not lookup UID for user " + config.UnprivUsername + ": " + err.Error())
}
ui.unpriv_uid, err = strconv.Atoi(nobody_user.Uid)
ui.unpriv_gid, err = strconv.Atoi(nobody_user.Gid)
if err != nil {
log.Fatal("Running as root but could not lookup UID for user " + config.UnprivUsername + ": " + err.Error())
}
}
return ui
}
func DropPrivs(ui userInfo, errorLog *log.Logger) {
// If we're already unprivileged, all good
if !ui.need_drop {
return
}
// Drop supplementary groups
if ui.root_supp_group {
err := syscall.Setgroups([]int{})
if err != nil {
errorLog.Println("Could not unset supplementary groups: " + err.Error())
log.Fatal(err)
}
}
// Setguid()
if ui.root_prim_group {
err := syscall.Setgid(ui.unpriv_gid)
if err != nil {
errorLog.Println("Could not setgid to " + strconv.Itoa(ui.unpriv_gid) + ": " + err.Error())
log.Fatal(err)
}
}
// Setuid()
if ui.root_user {
err := syscall.Setuid(ui.unpriv_uid)
if err != nil {
errorLog.Println("Could not setuid to " + strconv.Itoa(ui.unpriv_uid) + ": " + err.Error())
log.Fatal(err)
}
}

View File

@ -11,10 +11,10 @@ import (
// operations available to the molly brown executable. Please note that (S)CGI
// processes that molly brown spawns or communicates with are unrestricted
// and should pledge their own restrictions and unveil their own files.
func enableSecurityRestrictions(config Config, nobody_uid int, errorLog *log.Logger) {
func enableSecurityRestrictions(config Config, ui userInfo, errorLog *log.Logger) {
// Setuid to an unprivileged user
DropPrivs(config, nobody_uid, errorLog)
DropPrivs(ui, errorLog)
// Unveil the configured document base as readable.
log.Println("Unveiling \"" + config.DocBase + "\" as readable.")

View File

@ -6,8 +6,8 @@ import (
"log"
)
func enableSecurityRestrictions(config Config, nobody_uid int, errorLog *log.Logger) {
func enableSecurityRestrictions(config Config, ui userInfo, errorLog *log.Logger) {
// Setuid to an unprivileged user
DropPrivs(config, nobody_uid, errorLog)
DropPrivs(ui, errorLog)
}