From 06b2e18e90b6e216741eb04454fa32e04ad96fee Mon Sep 17 00:00:00 2001 From: "Scott R. Shinn" Date: Sun, 29 Dec 2024 14:47:36 -0500 Subject: [PATCH 1/2] Security enhancements - chroot support - privilege separation Signed-off-by: Scott R. Shinn --- src/addagent/validate.c | 2 +- src/os_auth/main-server.c | 120 +++++++++++++++++++------------------- 2 files changed, 62 insertions(+), 60 deletions(-) diff --git a/src/addagent/validate.c b/src/addagent/validate.c index 39ce6e8f8..f4f589e4e 100644 --- a/src/addagent/validate.c +++ b/src/addagent/validate.c @@ -109,7 +109,7 @@ char *OS_AddNewAgent(const char *name, const char *ip, const char *id) } char authentication_file[2048 + 1]; - snprintf(authentication_file, 2048, "%s%s", DEFAULTDIR, AUTH_FILE); + snprintf(authentication_file, 2048, "%s", AUTH_FILE); fp = fopen(authentication_file, "a"); if (!fp) { diff --git a/src/os_auth/main-server.c b/src/os_auth/main-server.c index f782f552f..c844bc3aa 100644 --- a/src/os_auth/main-server.c +++ b/src/os_auth/main-server.c @@ -22,18 +22,6 @@ * */ -#ifndef LIBOPENSSL_ENABLED - -#include -#include -int main() -{ - printf("ERROR: Not compiled. Missing OpenSSL support.\n"); - exit(0); -} - -#else - #include #include "auth.h" #include "os_crypto/md5/md5_op.h" @@ -161,11 +149,13 @@ int main(int argc, char **argv) int c = 0, test_config = 0, use_ip_address = 0, pid = 0, status, i = 0, active_processes = 0; int use_pass = 1; int run_foreground = 0; + gid_t uid; gid_t gid; int client_sock = 0, sock = 0, portnum, ret = 0; char *port = DEFAULT_PORT; char *ciphers = DEFAULT_CIPHERS; const char *dir = DEFAULTDIR; + const char *user = MAILUSER; const char *group = GROUPGLOBAL; const char *server_cert = NULL; const char *server_key = NULL; @@ -191,7 +181,7 @@ int main(int argc, char **argv) /* Set the name */ OS_SetName(ARGV0); - while ((c = getopt(argc, argv, "Vdhtfig:D:m:p:c:v:x:k:n")) != -1) { + while ((c = getopt(argc, argv, "Vdhtfiu:g:D:m:p:c:v:x:k:n")) != -1) { switch (c) { case 'V': print_version(); @@ -205,6 +195,12 @@ int main(int argc, char **argv) case 'i': use_ip_address = 1; break; + case 'u': + if (!optarg) { + ErrorExit("%s: -u needs an argument", ARGV0); + } + user = optarg; + break; case 'g': if (!optarg) { ErrorExit("%s: -g needs an argument", ARGV0); @@ -266,56 +262,52 @@ int main(int argc, char **argv) } } - /* Start daemon -- NB: need to double fork and setsid */ - debug1(STARTED_MSG, ARGV0); + if (chdir(dir) == -1) { + ErrorExit(CHDIR_ERROR, ARGV0, dir, errno, strerror(errno)); + } + + /* Exit here if test config is set */ + if (test_config) { + exit(0); + } + /* Check if the user/group given are valid */ + uid = Privsep_GetUser(user); gid = Privsep_GetGroup(group); - if (gid == (gid_t) - 1) { - ErrorExit(USER_ERROR, ARGV0, "", group); + if (uid == (uid_t) - 1 || gid == (gid_t) - 1) { + ErrorExit(USER_ERROR, ARGV0, user, group); } + if (!run_foreground) { nowDaemon(); goDaemon(); } - /* Create PID files */ - if (CreatePID(ARGV0, getpid()) < 0) { - ErrorExit(PID_ERROR, ARGV0); - } - /* Exit here if test config is set */ - if (test_config) { - exit(0); - } - - /* Privilege separation */ - if (Privsep_SetGroup(gid) < 0) { - ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno)); - } - - /* chroot -- TODO: this isn't a chroot. Should also close - * unneeded open file descriptors (like stdin/stdout) - */ - if (chdir(dir) == -1) { - ErrorExit(CHDIR_ERROR, ARGV0, dir, errno, strerror(errno)); - } /* Signal manipulation */ StartSIG(ARGV0); - /* Create PID files */ if (CreatePID(ARGV0, getpid()) < 0) { - ErrorExit(PID_ERROR, ARGV0); + ErrorExit(PID_ERROR, ARGV0); } atexit(cleanup); - /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); + + /* load keys */ + fp = fopen(KEYSFILE_PATH, "a"); + if (!fp) { + merror("%s: ERROR: Unable to open %s (key file)", ARGV0, KEYSFILE_PATH); + exit(1); + } + fclose(fp); + if (use_pass) { /* Checking if there is a custom password file */ @@ -345,16 +337,12 @@ int main(int argc, char **argv) verbose("Accepting connections. No password required (not recommended)"); } - /* Getting SSL cert. */ - fp = fopen(KEYSFILE_PATH, "a"); - if (!fp) { - merror("%s: ERROR: Unable to open %s (key file)", ARGV0, KEYSFILE_PATH); - exit(1); - } - fclose(fp); + /* Setup random */ + srandom_init(); /* Start SSL */ + /* Getting SSL cert. */ ctx = os_ssl_keys(1, dir, ciphers, server_cert, server_key, ca_cert); if (!ctx) { merror("%s: ERROR: SSL error. Exiting.", ARGV0); @@ -368,22 +356,35 @@ int main(int argc, char **argv) exit(1); } - /* initialize select() save area */ - fdsave = netinfo->fdset; - fdmax = netinfo->fdmax; /* value preset to max fd + 1 */ + /* Privilege separation */ + if (Privsep_SetGroup(gid) < 0) { + ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno)); + } - debug1("%s: DEBUG: Going into listening mode.", ARGV0); + /* Chroot to the specified directory */ + if (Privsep_Chroot(dir) < 0) { + ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno)); + } - /* Setup random */ - srandom_init(); + if (Privsep_SetUser(uid) < 0) { + ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno)); + } - /* Chroot */ -/* - if (Privsep_Chroot(dir) < 0) - ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno)); + /* Log that we are now in the chrooted environment */ nowChroot(); -*/ + + /* Change working directory to / within the chroot */ + if (chdir("/") < 0) { + ErrorExit(CHDIR_ERROR, ARGV0, "/", errno, strerror(errno)); + } + + + /* initialize select() save area */ + fdsave = netinfo->fdset; + fdmax = netinfo->fdmax; /* value preset to max fd + 1 */ + + debug1("%s: DEBUG: Going into listening mode.", ARGV0); while (1) { /* No need to completely pin the cpu, 100ms should be fast enough */ @@ -555,6 +556,8 @@ int main(int argc, char **argv) finalkey = OS_AddNewAgent(agentname, NULL, NULL); } if (!finalkey) { + merror("%s: ERROR: Unable to add agent: %s (internal error - debug check paths and files)", ARGV0, agentname); + merror("%s: ERROR: Unable to add agent: %s (internal error)", ARGV0, agentname); snprintf(response, 2048, "ERROR: Internal manager error adding agent: %s\n\n", agentname); SSL_write(ssl, response, strlen(response)); @@ -598,4 +601,3 @@ int main(int argc, char **argv) static void cleanup() { DeletePID(ARGV0); } -#endif /* LIBOPENSSL_ENABLED */ From 20aa756b4a40fd79f98cf7265d9aab239ac153b5 Mon Sep 17 00:00:00 2001 From: "Scott R. Shinn" Date: Sun, 29 Dec 2024 15:17:05 -0500 Subject: [PATCH 2/2] User management changes default to the ossec user Signed-off-by: Scott R. Shinn --- src/os_auth/main-server.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/os_auth/main-server.c b/src/os_auth/main-server.c index c844bc3aa..f3837c43b 100644 --- a/src/os_auth/main-server.c +++ b/src/os_auth/main-server.c @@ -155,7 +155,7 @@ int main(int argc, char **argv) char *port = DEFAULT_PORT; char *ciphers = DEFAULT_CIPHERS; const char *dir = DEFAULTDIR; - const char *user = MAILUSER; + const char *user = USER; const char *group = GROUPGLOBAL; const char *server_cert = NULL; const char *server_key = NULL; @@ -307,6 +307,18 @@ int main(int argc, char **argv) exit(1); } fclose(fp); + + /* Set ownership to ossec user and group */ + if (chown(KEYSFILE_PATH, uid, gid) < 0) { + merror("%s: ERROR: Unable to set ownership of %s to %d:%d (%s)", ARGV0, KEYSFILE_PATH, uid, gid, strerror(errno)); + exit(1); + } + + /* Set permissions to read/write for owner, read for group */ + if (chmod(KEYSFILE_PATH, 0640) < 0) { + merror("%s: ERROR: Unable to set permissions of %s to 0640 (%s)", ARGV0, KEYSFILE_PATH, strerror(errno)); + exit(1); + } if (use_pass) { @@ -556,8 +568,6 @@ int main(int argc, char **argv) finalkey = OS_AddNewAgent(agentname, NULL, NULL); } if (!finalkey) { - merror("%s: ERROR: Unable to add agent: %s (internal error - debug check paths and files)", ARGV0, agentname); - merror("%s: ERROR: Unable to add agent: %s (internal error)", ARGV0, agentname); snprintf(response, 2048, "ERROR: Internal manager error adding agent: %s\n\n", agentname); SSL_write(ssl, response, strlen(response));