CVE-2020-7221: Improper Link Resolution Before File Access ('Link Following') (CWE-59)
value: mysql_install_db in MariaDB 10.4.7 through 10.4.11 allows privilege escalation from the mysql user account to root because chown and chmod are performed unsafely, as demonstrated by a symlink attack on a chmod 04755 of auth_pam_tool_dir/auth_pam_tool. NOTE: this does not affect the Oracle MySQL product, which implements mysql_install_db differently.
CWE description: The product attempts to access a file based on the filename, but it does not properly prevent that filename from identifying a link or shortcut that resolves to an unintended resource.
CVSS v3 base score: 7.8
Published: 2020-02-04T17:15Z
Repository: https://github.com/MariaDB/server
Language: Shell
Files changed: debian/mariadb-server-10.4.postinst, debian/rules, scripts/mysql_install_db.sh, support-files/rpm/server-postin.sh
Commit date: 2020-01-17 18:14:43 +0100
Commit message: rpm/deb and auth_pam_tool_dir/auth_pam_tool

don't let mysql_install_db set SUID bit for auth_pam_tool in rpm/deb
packages - instead package files with correct permissions and
only fix the ownership of auth_pam_tool_dir (which can only be done
after mysql user is created, so in post-install).

keep old mysql_install_db behavior for bintars

Diff: diff --git a/debian/mariadb-server-10.4.postinst b/debian/mariadb-server-10.4.postinst
index fbb2584f2df..3db4d50ea08 100644
--- a/debian/mariadb-server-10.4.postinst
+++ b/debian/mariadb-server-10.4.postinst
@@ -92,10 +92,13 @@ EOF
     find $mysql_datadir ! -uid $(id -u mysql) -print0 | xargs -0 -r chown mysql
     chown -R mysql:adm $mysql_logdir
     chmod 2750 $mysql_logdir
     set -e
 
+    # Set the correct filesystem ownership for the PAM v2 plugin
+    chown mysql /usr/lib/mysql/plugin/auth_pam_tool_dir
+
     # This is important to avoid dataloss when there is a removed
     # mysql-server version from Woody lying around which used the same
     # data directory and then somewhen gets purged by the admin.
     db_set mariadb-server/postrm_remove_database false || true
 
diff --git a/debian/rules b/debian/rules
index 9914bae721b..ac85ef7dc26 100755
--- a/debian/rules
+++ b/debian/rules
@@ -144,10 +144,14 @@ endif
 	# Install libmysqlclientclientXX compatibility links
 	ln -s libmariadb.so.3 $(TMP)/usr/lib/$(DEB_HOST_MULTIARCH)/libmysqlclient.so.18
 	ln -s libmariadb.so.3 $(TMP)/usr/lib/$(DEB_HOST_MULTIARCH)/libmysqlclient.so.19
 	ln -s libmariadb.so.3 $(TMP)/usr/lib/$(DEB_HOST_MULTIARCH)/libmysqlclient.so.20
 
+override_dh_fixperms:
+	dh_fixperms
+	chmod 04755 debian/mariadb-server-10.4/usr/lib/mysql/plugin/auth_pam_tool_dir/auth_pam_tool
+	chmod  0700 debian/mariadb-server-10.4/usr/lib/mysql/plugin/auth_pam_tool_dir
 
 override_dh_installlogrotate-arch:
 	dh_installlogrotate --name mysql-server
 
 override_dh_systemd_enable:
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index caa575dc091..e9744333af5 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -476,20 +476,12 @@ do
       exit 1
     fi
   fi
 done
 
-if test -n "$user"
+if test -n "$user" -a "$in_rpm" -eq 0
 then
-  chown $user "$pamtooldir/auth_pam_tool_dir" && \
-  chmod 0700 "$pamtooldir/auth_pam_tool_dir"
-  if test $? -ne 0
-  then
-      echo "Cannot change ownership of the '$pamtooldir/auth_pam_tool_dir' directory"
-      echo " to the '$user' user. Check that you have the necessary permissions and try again."
-      exit 1
-  fi
   if test -z "$srcdir"
   then
     chown 0 "$pamtooldir/auth_pam_tool_dir/auth_pam_tool" && \
     chmod 04755 "$pamtooldir/auth_pam_tool_dir/auth_pam_tool"
     if test $? -ne 0
@@ -497,10 +489,18 @@ then
         echo "Couldn't set an owner to '$pamtooldir/auth_pam_tool_dir/auth_pam_tool'."
         echo " It must be root, the PAM authentication plugin doesn't work otherwise.."
         echo
     fi
   fi
+  chown $user "$pamtooldir/auth_pam_tool_dir" && \
+  chmod 0700 "$pamtooldir/auth_pam_tool_dir"
+  if test $? -ne 0
+  then
+      echo "Cannot change ownership of the '$pamtooldir/auth_pam_tool_dir' directory"
+      echo " to the '$user' user. Check that you have the necessary permissions and try again."
+      exit 1
+  fi
   args="$args --user=$user"
 fi
 
 if test -f "$ldata/mysql/user.frm"
 then
diff --git a/support-files/rpm/server-postin.sh b/support-files/rpm/server-postin.sh
index bccda7fbb8b..db249c326a6 100644
--- a/support-files/rpm/server-postin.sh
+++ b/support-files/rpm/server-postin.sh
@@ -67,15 +67,12 @@ if [ $1 = 1 ] ; then
   # Fix permissions for the permission database so that only the user
   # can read them.
   chmod -R og-rw $datadir/mysql
 fi
 
-# Set correct filesystem ownership/permissions for the PAM v2 plugin
-chown %{mysqld_group} /usr/lib*/mysql/plugin/auth_pam_tool_dir
-chmod 0700            /usr/lib*/mysql/plugin/auth_pam_tool_dir
-chown 0               /usr/lib*/mysql/plugin/auth_pam_tool_dir/auth_pam_tool
-chmod 04755           /usr/lib*/mysql/plugin/auth_pam_tool_dir/auth_pam_tool
+# Set the correct filesystem ownership for the PAM v2 plugin
+chown %{mysqld_user} /usr/lib*/mysql/plugin/auth_pam_tool_dir
 
 # install SELinux files - but don't override existing ones
 SETARGETDIR=/etc/selinux/targeted/src/policy
 SEDOMPROG=$SETARGETDIR/domains/program
 SECONPROG=$SETARGETDIR/file_contexts/program

Vulnerable code: if test -n "$user"
  chown $user "$pamtooldir/auth_pam_tool_dir" && \
  chmod 0700 "$pamtooldir/auth_pam_tool_dir"
  if test $? -ne 0
  then
      echo "Cannot change ownership of the '$pamtooldir/auth_pam_tool_dir' directory"
      echo " to the '$user' user. Check that you have the necessary permissions and try again."
      exit 1
  fi
# Set correct filesystem ownership/permissions for the PAM v2 plugin
chown %{mysqld_group} /usr/lib*/mysql/plugin/auth_pam_tool_dir
chmod 0700            /usr/lib*/mysql/plugin/auth_pam_tool_dir
chown 0               /usr/lib*/mysql/plugin/auth_pam_tool_dir/auth_pam_tool
chmod 04755           /usr/lib*/mysql/plugin/auth_pam_tool_dir/auth_pam_tool
Fixed code:     # Set the correct filesystem ownership for the PAM v2 plugin
    chown mysql /usr/lib/mysql/plugin/auth_pam_tool_dir

override_dh_fixperms:
	dh_fixperms
	chmod 04755 debian/mariadb-server-10.4/usr/lib/mysql/plugin/auth_pam_tool_dir/auth_pam_tool
	chmod  0700 debian/mariadb-server-10.4/usr/lib/mysql/plugin/auth_pam_tool_dir
if test -n "$user" -a "$in_rpm" -eq 0
  chown $user "$pamtooldir/auth_pam_tool_dir" && \
  chmod 0700 "$pamtooldir/auth_pam_tool_dir"
  if test $? -ne 0
  then
      echo "Cannot change ownership of the '$pamtooldir/auth_pam_tool_dir' directory"
      echo " to the '$user' user. Check that you have the necessary permissions and try again."
      exit 1
  fi
# Set the correct filesystem ownership for the PAM v2 plugin
chown %{mysqld_user} /usr/lib*/mysql/plugin/auth_pam_tool_dir