Compare commits

...

11 Commits

Author SHA1 Message Date
Go Compile c3316bb99e
Merge 311ddecd26 into 17c4eeb646 2024-05-02 17:14:49 +02:00
Eugene Burkov 17c4eeb646 Pull request 2214: 6744 Fix TLD subdomain
Updates #6744.

Squashed commit of the following:

commit 04894ca268
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu May 2 16:48:37 2024 +0300

    all: upd proxy finally

commit 0cb063ed57
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu May 2 15:26:17 2024 +0300

    all: upd again

commit 3deb71c08d
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu May 2 14:46:38 2024 +0300

    all: upd proxy
2024-05-02 17:47:24 +03:00
go-compile 311ddecd26
fix: change dir if \!CurrentDirAvaliable() 2024-02-20 18:10:55 +00:00
go-compile 16f809bb5e
fix: shadowed err 2024-02-20 17:41:49 +00:00
go-compile 9ce23a6488
fix: typos 2024-02-20 17:37:16 +00:00
go-compile 5acde57e11
fix: rename binarysecurity_other.go to plural others 2024-02-20 17:32:41 +00:00
go-compile 8afecf5a95
refactor: clean up and move binary security checks to aghos 2024-02-20 17:29:34 +00:00
go-compile 11a7ac2013
fix: use os.Executable instead of os.Args[0] to get prog dir 2024-02-20 13:35:31 +00:00
go-compile 2c4ebe71d9
fix: use os.Executable instead of os.Args[0] to get prog path 2024-02-20 13:32:19 +00:00
go-compile 60177cebf2
feat: if running as a service set workdir to /var/lib/AdGuardHome
Fixes issue where the service would write the data dir into /usr/bin if the binary was within /usr/bin
2024-02-18 17:09:16 +00:00
go-compile c0a5e389d9
fix: service binary overwrite privilege escalation vuln 2024-02-18 16:24:20 +00:00
6 changed files with 154 additions and 3 deletions

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/AdguardTeam/AdGuardHome
go 1.22.2
require (
github.com/AdguardTeam/dnsproxy v0.71.0
github.com/AdguardTeam/dnsproxy v0.71.1
github.com/AdguardTeam/golibs v0.23.2
github.com/AdguardTeam/urlfilter v0.18.0
github.com/NYTimes/gziphandler v1.1.1

4
go.sum
View File

@ -1,5 +1,5 @@
github.com/AdguardTeam/dnsproxy v0.71.0 h1:7epvSeTtjTdwbeifRJK6jTXldoJwqd3GWqAYDlSo7zQ=
github.com/AdguardTeam/dnsproxy v0.71.0/go.mod h1:rCaCL4m4n63sgwTOyUVdc7MC42PlUYBt11Fz/UjD+kM=
github.com/AdguardTeam/dnsproxy v0.71.1 h1:R8jKmoE9HwqdTt7bm8irpvrQEOSmD+iGdNXbOg/uM8Y=
github.com/AdguardTeam/dnsproxy v0.71.1/go.mod h1:rCaCL4m4n63sgwTOyUVdc7MC42PlUYBt11Fz/UjD+kM=
github.com/AdguardTeam/golibs v0.23.2 h1:rMjYantwtQ39e8G4zBQ6ZLlm4s3XH30Bc9VxhoOHwao=
github.com/AdguardTeam/golibs v0.23.2/go.mod h1:o9i55Sx6v7qogRQeqaBfmLbC/pZqeMBWi015U5PTDY0=
github.com/AdguardTeam/urlfilter v0.18.0 h1:ZZzwODC/ADpjJSODxySrrUnt/fvOCfGFaCW6j+wsGfQ=

View File

@ -0,0 +1,83 @@
//go:build !windows
package aghos
import (
"fmt"
"os"
"strings"
"github.com/AdguardTeam/golibs/errors"
)
// protectedDirectories are directories which contain other application binaries,
// as such AdGuard Home should never attempt store application data here, at risk of
// overwriting other files. Moreover, these directories are innapproriate for storage of
// config files or session storage.
var protectedDirectories = []string{
"/usr/bin",
"/usr/sbin",
"/user/bin",
}
// serviceInstallDir is a executable path in a directory which secure permissions
// which prevent the manipulation of the binary.
const serviceInstallDir = "/usr/bin/AdGuardHome"
// SecureBinary is used before service.Install(). This function protects AdGuardHome from
// privilege escalation vulnerabilities caused by writable files
func SecureBinary() error {
// Installalation can only be completed with root privileges, so check and handle if not
if os.Getuid() != 0 {
return errors.Error("permission denied. Root privileges required")
}
// Get current file path
binary, err := os.Executable()
if err != nil {
return fmt.Errorf("os.Executable(): %w", err)
}
// Change owner to root:root
err = os.Chown(binary, 0, 0)
if err != nil {
return fmt.Errorf("os.Chown() %q: %w", binary, err)
}
// Set permissions to root(read,write,exec), group(read,exec), public(read)
// This combined with changing the owner make the file undeletable without root privlages
// UNLESS THE PARENT FOLDER IS WRITABLE!
err = os.Chmod(binary, 0755)
if err != nil {
return fmt.Errorf("os.Chmod() %q: %w", binary, err)
}
// Move binary to the PATH in a folder which is read-only to non root users
// If already moved, this is a no-op
err = os.Rename(binary, serviceInstallDir)
if err != nil {
return fmt.Errorf("os.Rename() %q to %q: %w", binary, serviceInstallDir, err)
}
return nil
}
// CurrentDirAvaliable returns true if it is okay to use this directory to store application
// data.
func CurrentDirAvaliable() (bool, error) {
binary, err := os.Executable()
if err != nil {
return false, fmt.Errorf("os.Executable(): %w", err)
}
for i := 0; i < len(protectedDirectories); i++ {
// Check if binary is within a protected directory
if strings.HasPrefix(binary, protectedDirectories[i]) {
// The binary is within a protected directory
return false, nil
}
}
// The binary is outside of all checked protected directories
return true, nil
}

View File

@ -0,0 +1,47 @@
//go:build windows
package aghos
import (
"fmt"
"os"
"strings"
)
// securePrefixDirectories is a list of directories where a service binary
// has the appropriate permissions to mitigate a binary planting attack
var securePrefixDirectories = []string{
"C:\\Program Files",
"C:\\Program Files (x86)",
// Some Windows users place binaries within /Windows/System32 to add it to %PATH%
"C:\\Windows",
}
// SecureBinary is used before service.Install(). This function protects AdGuardHome from
// privilege escalation vulnerabilities caused by writable files
func SecureBinary() error {
// Get current file path
binary, err := os.Executable()
if err != nil {
return fmt.Errorf("os.Executable(): %w", err)
}
for i := 0; i < len(securePrefixDirectories); i++ {
// Check if binary is within a secure folder write protected folder
if strings.HasPrefix(binary, securePrefixDirectories[i]) {
// The binary is within a secure directory already
return nil
}
}
// No secure directories matched
return fmt.Errorf("insecure binary location for service instalation: %q. Please view: https://adguard-dns.io/kb/adguard-home/running-securely/", binary)
}
// CurrentDirAvaliable returns true if it is okay to use this directory to store application
// data.
func CurrentDirAvaliable() (bool, error) {
// We do not mind what directory is used on Windows
return true, nil
}

View File

@ -783,9 +783,25 @@ func initWorkingDir(opts options) (err error) {
return err
}
// Can we use the current directory to store application data?
pwdAvaliable, err := aghos.CurrentDirAvaliable()
if err != nil {
return err
}
if opts.workDir != "" {
// If there is a custom config file, use it's directory as our working dir
Context.workDir = opts.workDir
} else if !pwdAvaliable {
// If running as a service and from /usr/bin/ use /var/lib for working dir instead of
// /usr/bin/data
Context.workDir = "/var/lib/AdGuardHome"
// Create dir if it does not already exist
err := os.MkdirAll(Context.workDir, 0755)
if err != nil {
return fmt.Errorf("os.MkdirAll: %s: %w", Context.workDir, err)
}
} else {
Context.workDir = filepath.Dir(execPath)
}

View File

@ -308,6 +308,11 @@ func handleServiceStatusCommand(s service.Service) {
// handleServiceInstallCommand handles service "install" command.
func handleServiceInstallCommand(s service.Service) {
// Set the binary's permissions and move to /usr/bin (if on linux)
if err := aghos.SecureBinary(); err != nil {
log.Fatal(err)
}
err := svcAction(s, "install")
if err != nil {
log.Fatalf("service: executing action %q: %s", "install", err)