MariaDB / mariadb-docker

Docker Official Image packaging for MariaDB
https://mariadb.org
GNU General Public License v2.0
770 stars 438 forks source link

SQL escape passwords #356

Closed grooverdan closed 3 years ago

grooverdan commented 3 years ago

To correctly SQL escape passwords, escaping \ first is required. Then we need to escape ' in the password to prevent it being treated as a end of SQL statement quote.

All escaping needs to use \, so we cannot be in NO_BACKSLASH_ESCAPES sql_mode otherwise no escaping will work.

As an added complication when using the config file within the entrypoint, for waiting until MariaDB can initialize, a password mechanism a different escaping applies (https://mariadb.com/kb/en/configuring-mariadb-with-option-files/).

The printf %q is close, however it provides a much richer escape of non-printable characters than what can be read in the configuration file. As such the password complexity of the root password is limited to escaping \n, \r, \t, \b, \s, \", \', and \ while for a user MARIADB_PASSWORD anything, including positively crazy strings such as \0 will work.

Closes #183

grooverdan commented 3 years ago

todo: look at https://github.com/grooverdan/mariadb/runs/2092312601?check_suite_focus=true fails CI there but not on the PR here.

grooverdan commented 3 years ago

After far too long looking at this:

The '\x00' character will confuse printf %q, escaping in ESC below will generate some unexpected output, AND any tempt to pass a \x00 containing bash variable to a process will terminate at that character - (strace -fe trace=network -s99 -p $(pidof mysqld) with mysql -u root <<<$'CREATE OR REPLACE USER bob@localhost IDENTIFIED BY \'rr\x00My#1PasswordIsSecure\''. In the entrypoint read -d '' is always \x00 terminated. read -N will stop an '\x00' before EOF (so the bash man pages lies).

So any handling of '\x00' in bash is for the totally mad.

P=$'\'\\aa-\x00-zz"_%'; ESC="${P//\\/\\\\}"; ESC="${ESC//\'/\\\'}"; od -h <<<"$ESC" ; echo LENP=${#P} LENESC=${#ESC}; printf ESC=%q "${ESC}" ; mysql -u root  -p"${MARIADB_ROOT_PASSWORD}" <<<"create or replace user bob@localhost identified by '$ESC';";  mysql -u bob -p"${P}" -e "select 1" ; printf "[client]\npassword=%q\n" "$P" | tee ~/.my.cnf ; mysql -u bob -e 'select 1'; echo "\"$(printf "%q" "$P")\"" 
0000000 275c 5c5c 6161 0a2d
0000010
LENP=5 LENESC=7
ESC=\\\'\\\\aa-+---+
| 1 |
+---+
| 1 |
+---+
[client]
password=\'\\aa-
+---+
| 1 |
+---+
| 1 |
+---+
"\'\\aa-"

ref: ansi string https://wiki.bash-hackers.org/syntax/quoting#ansi_c_like_strings