175 lines
6.2 KiB
Diff
175 lines
6.2 KiB
Diff
diff -Naur httpd-2.4.39/support/suexec.c.orig httpd-2.4.39/support/suexec.c
|
|
--- httpd-2.4.39/support/suexec.c.orig 2018-05-31 01:09:00.000000000 +0600
|
|
+++ httpd-2.4.39/support/suexec.c 2019-06-13 16:58:19.943661521 +0600
|
|
@@ -269,14 +269,36 @@
|
|
environ = cleanenv;
|
|
}
|
|
|
|
+static int is_group_member( const char *uname, gid_t gid ) {
|
|
+ struct group *g;
|
|
+ char **members;
|
|
+
|
|
+ g = getgrgid( gid );
|
|
+ if ( g == NULL ) {
|
|
+ log_err("crit: cannot get membership of group %d\n", gid);
|
|
+ exit(109);
|
|
+ }
|
|
+
|
|
+ members = g->gr_mem;
|
|
+ while ( *members != NULL ) {
|
|
+ if ( strcmp( *members, uname ) == 0 ) {
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int userdir = 0; /* ~userdir flag */
|
|
uid_t uid; /* user information */
|
|
+ uid_t httpuid; /* http user */
|
|
gid_t gid; /* target group placeholder */
|
|
+ gid_t httpgid; /* http group */
|
|
char *target_uname; /* target user name */
|
|
char *target_gname; /* target group name */
|
|
char *target_homedir; /* target home directory */
|
|
+ gid_t default_gid; /* Default GID for target UID*/
|
|
char *actual_uname; /* actual user name */
|
|
char *actual_gname; /* actual group name */
|
|
char *cmd; /* command to be executed */
|
|
@@ -296,7 +318,8 @@
|
|
* Check existence/validity of the UID of the user
|
|
* running this program. Error out if invalid.
|
|
*/
|
|
- uid = getuid();
|
|
+ uid = httpuid = getuid();
|
|
+ httpgid = getgid();
|
|
if ((pw = getpwuid(uid)) == NULL) {
|
|
log_err("crit: invalid uid: (%lu)\n", (unsigned long)uid);
|
|
exit(102);
|
|
@@ -465,6 +488,7 @@
|
|
uid = pw->pw_uid;
|
|
actual_uname = strdup(pw->pw_name);
|
|
target_homedir = strdup(pw->pw_dir);
|
|
+ default_gid = pw->pw_gid;
|
|
if (actual_uname == NULL || target_homedir == NULL) {
|
|
log_err("failed to alloc memory\n");
|
|
exit(126);
|
|
@@ -498,6 +522,14 @@
|
|
}
|
|
|
|
/*
|
|
+ * Error out if user UID is not a member of group GID.
|
|
+ */
|
|
+ if ((gid != default_gid) && !is_group_member(actual_uname, gid)) {
|
|
+ log_err("crit: user does not belong to group (%s/%d/%s)\n", actual_uname, gid, cmd);
|
|
+ exit(108);
|
|
+ }
|
|
+
|
|
+ /*
|
|
* Change UID/GID here so that the following tests work over NFS.
|
|
*
|
|
* Initialize the group access list for the target user,
|
|
@@ -548,8 +580,10 @@
|
|
}
|
|
|
|
if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {
|
|
- log_err("command not in docroot (%s/%s)\n", cwd, cmd);
|
|
- exit(114);
|
|
+ if (strncmp(cwd, SUEXEC_TRUSTED_DIR, strlen(SUEXEC_TRUSTED_DIR)) != 0) {
|
|
+ log_err("command not in docroot and not in trustred directory (%s/%s)\n", cwd, cmd);
|
|
+ exit(114);
|
|
+ }
|
|
}
|
|
|
|
/*
|
|
@@ -597,16 +631,41 @@
|
|
* the name/group of the cwd or the program.
|
|
*/
|
|
if ((uid != dir_info.st_uid) ||
|
|
- (gid != dir_info.st_gid) ||
|
|
+ ((gid != dir_info.st_gid) && (dir_info.st_gid != httpgid)) ||
|
|
(uid != prg_info.st_uid) ||
|
|
- (gid != prg_info.st_gid)) {
|
|
- log_err("target uid/gid (%lu/%lu) mismatch "
|
|
- "with directory (%lu/%lu) or program (%lu/%lu)\n",
|
|
- (unsigned long)uid, (unsigned long)gid,
|
|
- (unsigned long)dir_info.st_uid, (unsigned long)dir_info.st_gid,
|
|
- (unsigned long)prg_info.st_uid, (unsigned long)prg_info.st_gid);
|
|
- exit(120);
|
|
- }
|
|
+ ((gid != prg_info.st_gid) && (prg_info.st_gid != httpgid))) {
|
|
+ /* <--- begin changed code ap1 suexec_standard.patch --->
|
|
+ *
|
|
+ * This patch adds a possibility to use "shared" scripts on a
|
|
+ * shared webhosting box.
|
|
+ */
|
|
+#ifdef TRUSTED_USERS_SCRIPTS
|
|
+ if ((atoi(SUEXEC_TRUSTED_USER) != prg_info.st_uid) ||
|
|
+ (atoi(SUEXEC_TRUSTED_GROUP) != prg_info.st_gid)) {
|
|
+ if (strncmp(cwd, SUEXEC_TRUSTED_DIR, 15) != 0) {
|
|
+// (strncmp(cwd, "/etc/httpd/php-bin", 25) != 0)) {
|
|
+
|
|
+ log_err("error: target uid/gid (%ld/%ld) mismatch "
|
|
+ "with directory (%ld/%ld) or program (%ld/%ld) or trusted user (%d/%d)\n",
|
|
+ uid, gid,
|
|
+ dir_info.st_uid, dir_info.st_gid,
|
|
+ prg_info.st_uid, prg_info.st_gid, atoi(SUEXEC_TRUSTED_USER), atoi(SUEXEC_TRUSTED_GROUP));
|
|
+ exit(120);
|
|
+ }
|
|
+ }
|
|
+#else
|
|
+ log_err("target uid/gid (%lu/%lu) mismatch "
|
|
+ "with directory (%lu/%lu) or program (%lu/%lu)\n",
|
|
+ (unsigned long)uid, (unsigned long)gid,
|
|
+ (unsigned long)dir_info.st_uid, (unsigned long)dir_info.st_gid,
|
|
+ (unsigned long)prg_info.st_uid, (unsigned long)prg_info.st_gid);
|
|
+ exit(120);
|
|
+#endif
|
|
+ /*
|
|
+ * end changed code
|
|
+ */
|
|
+ }
|
|
+
|
|
/*
|
|
* Error out if the program is not executable for the user.
|
|
* Otherwise, she won't find any error in the logs except for
|
|
diff -Naur httpd-2.4.39/support/suexec.h.orig httpd-2.4.39/support/suexec.h
|
|
--- httpd-2.4.39/support/suexec.h.orig 2011-09-23 19:38:09.000000000 +0600
|
|
+++ httpd-2.4.39/support/suexec.h 2019-06-12 14:52:18.491988334 +0600
|
|
@@ -40,6 +40,33 @@
|
|
#endif
|
|
|
|
/*
|
|
+ * READ THIS BEFORE CONTINUING!!
|
|
+ *
|
|
+ * The patch below adds a feature which makes it possible to run "shared"
|
|
+ * scripts. Suppose you are a systems admin for $large hosting provider and
|
|
+ * you want to offer your customers some standard scripts. These scripts would
|
|
+ * cause a security violation based on the uid owner of the script.
|
|
+ *
|
|
+ * This patch makes it possible to "trust" a certain user/group. Look below to
|
|
+ * define the user/group ID.
|
|
+ *
|
|
+ * Uncomment the define to make it actually happen.
|
|
+ *
|
|
+ * patch added as ap1 suexec_standard.patch clone
|
|
+ */
|
|
+
|
|
+#define TRUSTED_USERS_SCRIPTS
|
|
+
|
|
+#ifdef TRUSTED_USERS_SCRIPTS
|
|
+#define SUEXEC_TRUSTED_USER "0"
|
|
+#define SUEXEC_TRUSTED_GROUP "10"
|
|
+#endif
|
|
+
|
|
+#ifndef SUEXEC_TRUSTED_DIR
|
|
+#define SUEXEC_TRUSTED_DIR "/etc/httpd/sys-bin"
|
|
+#endif
|
|
+
|
|
+/*
|
|
* UID_MIN -- Define this as the lowest UID allowed to be a target user
|
|
* for suEXEC. For most systems, 500 or 100 is common.
|
|
*/
|