[exim-dev] [PATCH 2/6] Don't allow a configure file which is…

Top Page
Delete this message
Reply to this message
Author: David Woodhouse
Date:  
To: exim-dev
Old-Topics: [exim-dev] Candidate patches for privilege escalation
Subject: [exim-dev] [PATCH 2/6] Don't allow a configure file which is writeable by the Exim user or group
(Bug 1044, CVE-2010-4345)
---
 doc/doc-docbook/spec.xfpt |   16 ++++++++++------
 doc/doc-txt/ChangeLog     |    4 ++++
 src/src/EDITME            |    7 +++----
 src/src/config.h.defaults |    1 +
 src/src/globals.c         |    1 +
 src/src/globals.h         |    1 +
 src/src/readconf.c        |    5 ++---
 7 files changed, 22 insertions(+), 13 deletions(-)


diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 1ec4181..049b2b6 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -4501,17 +4501,21 @@ existing file in the list.
.cindex "configuration file" "ownership"
.cindex "ownership" "configuration file"
The run time configuration file must be owned by root or by the user that is
-specified at compile time by the EXIM_USER option, or by the user that is
specified at compile time by the CONFIGURE_OWNER option (if set). The
-configuration file must not be world-writeable or group-writeable, unless its
-group is the one specified at compile time by the EXIM_GROUP option or by the
+configuration file must not be world-writeable, or group-writeable unless its
+group is the root group or the one specified at compile time by the
CONFIGURE_GROUP option.

&*Warning*&: In a conventional configuration, where the Exim binary is setuid
to root, anybody who is able to edit the run time configuration file has an
-easy way to run commands as root. If you make your mail administrators members
-of the Exim group, but do not trust them with root, make sure that the run time
-configuration is not group writeable.
+easy way to run commands as root. If you specify a user or group in the
+CONFIGURE_OWNER or CONFIGURE_GROUP options, then that user and/or any users
+who are members of that group will trivially be able to obtain root privileges.
+
+Up to Exim version 4.72, the run time configuration file was also permitted to
+be writeable by the Exim user and/or group. That has been changed in Exim 4.73
+since it offered a simple privilege escalation for any attacker who managed to
+compromise the Exim user account.

 A default configuration file, which will work correctly in simple situations,
 is provided in the file &_src/configure.default_&. If CONFIGURE_FILE
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index ccc5d79..99a6f17 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -74,6 +74,10 @@ PP/20 Added a CONTRIBUTING file.  Fixed the documentation build to use http:
 DW/21 Added Valgrind hooks in store.c to help it capture out-of-bounds store
       access.


+DW/22 Bugzilla 1044: CVE-2010-4345 - partial fix: restrict default behaviour
+      of CONFIGURE_OWNER and CONFIGURE_GROUP options to no longer allow a
+      configuration file which is writeable by the Exim user or group.
+


Exim version 4.72
-----------------
diff --git a/src/src/EDITME b/src/src/EDITME
index 050d9ad..285e5b6 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -430,14 +430,13 @@ FIXED_NEVER_USERS=root


#------------------------------------------------------------------------------
-# By default, Exim insists that its configuration file be owned either by root
-# or by the Exim user. You can specify one additional permitted owner here.
+# By default, Exim insists that its configuration file be owned by root. You
+# can specify one additional permitted owner here.

# CONFIGURE_OWNER=

# If the configuration file is group-writeable, Exim insists by default that it
-# is owned by root or the Exim user. You can specify one additional permitted
-# group owner here.
+# is owned by root. You can specify one additional permitted group owner here.

# CONFIGURE_GROUP=

diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index c6895b6..9f0eba0 100644
--- a/src/src/config.h.defaults
+++ b/src/src/config.h.defaults
@@ -161,5 +161,6 @@ just in case. */
 #define DNS_MAXNAME                1024
 #define EXPAND_MAXN                  20
 #define ROOT_UID                      0
+#define ROOT_GID                      0


 /* End of config.h.defaults */
diff --git a/src/src/globals.c b/src/src/globals.c
index 645cdb1..9b77d87 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -946,6 +946,7 @@ int     rewrite_existflags     = 0;
 uschar *rfc1413_hosts          = US"*";
 int     rfc1413_query_timeout  = 5;
 /* BOOL    rfc821_domains         = FALSE;  <<< on the way out */
+uid_t   root_gid               = ROOT_GID;
 uid_t   root_uid               = ROOT_UID;


 router_instance  *routers  = NULL;
diff --git a/src/src/globals.h b/src/src/globals.h
index b036def..d66880e 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -610,6 +610,7 @@ extern int     rewrite_existflags;     /* Indicate which headers have rewrites *
 extern uschar *rfc1413_hosts;          /* RFC hosts */
 extern int     rfc1413_query_timeout;  /* Timeout on RFC 1413 calls */
 /* extern BOOL    rfc821_domains;  */       /* If set, syntax is 821, not 822 => being abolished */
+extern uid_t   root_gid;               /* The gid for root */
 extern uid_t   root_uid;               /* The uid for root */
 extern router_info routers_available[];/* Vector of available routers */
 extern router_instance *routers;       /* Chain of instantiated routers */
diff --git a/src/src/readconf.c b/src/src/readconf.c
index 954d546..0803058 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -2883,13 +2883,12 @@ if (!config_changed)
     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to stat configuration file %s",
       big_buffer);


-  if ((statbuf.st_uid != root_uid &&             /* owner not root */
-       statbuf.st_uid != exim_uid                /* owner not exim */
+  if ((statbuf.st_uid != root_uid                /* owner not root */
        #ifdef CONFIGURE_OWNER
        && statbuf.st_uid != config_uid           /* owner not the special one */
        #endif
          ) ||                                    /* or */
-      (statbuf.st_gid != exim_gid                /* group not exim & */
+      (statbuf.st_gid != root_gid                /* group not root & */
        #ifdef CONFIGURE_GROUP
        && statbuf.st_gid != config_gid           /* group not the special one */
        #endif
-- 
1.7.3.2