Commit 2025597c authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-21778 Disable system commands in mysql/mariadb client

mysql --sandbox

disables system (\!), tee (\T), pager with an argument(\P foo), source (\.)

does *not* disable edit (\e). Use EDITOR=/bin/false to disable
or, for example, EDITOR=rnano for something more useful

does *not* disable pager (\P) without an argument. Use
PAGER=cat or, for example PAGER=less LESSSECURE=1 for something
more useful

using a disabled command is an error, which can be ignored with --force

Also, a "sandbox" command (\-) - enables the sandbox mode until EOF
(current file or the session, if interactive)
parent 83aedeac
...@@ -136,7 +136,7 @@ typedef struct st_status ...@@ -136,7 +136,7 @@ typedef struct st_status
ulong query_start_line; ulong query_start_line;
char *file_name; char *file_name;
LINE_BUFFER *line_buff; LINE_BUFFER *line_buff;
bool batch,add_to_history; bool batch, add_to_history, sandbox;
} STATUS; } STATUS;
...@@ -154,7 +154,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0, ...@@ -154,7 +154,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0,
vertical=0, line_numbers=1, column_names=1,opt_html=0, vertical=0, line_numbers=1, column_names=1,opt_html=0,
opt_xml=0,opt_nopager=1, opt_outfile=0, named_cmds= 0, opt_xml=0,opt_nopager=1, opt_outfile=0, named_cmds= 0,
tty_password= 0, opt_nobeep=0, opt_reconnect=1, tty_password= 0, opt_nobeep=0, opt_reconnect=1,
opt_secure_auth= 0, opt_secure_auth= 0,
default_pager_set= 0, opt_sigint_ignore= 0, default_pager_set= 0, opt_sigint_ignore= 0,
auto_vertical_output= 0, auto_vertical_output= 0,
show_warnings= 0, executing_query= 0, show_warnings= 0, executing_query= 0,
...@@ -235,7 +235,8 @@ static int com_quit(String *str,char*), ...@@ -235,7 +235,8 @@ static int com_quit(String *str,char*),
com_rehash(String *str, char*), com_tee(String *str, char*), com_rehash(String *str, char*), com_tee(String *str, char*),
com_notee(String *str, char*), com_charset(String *str,char*), com_notee(String *str, char*), com_charset(String *str,char*),
com_prompt(String *str, char*), com_delimiter(String *str, char*), com_prompt(String *str, char*), com_delimiter(String *str, char*),
com_warnings(String *str, char*), com_nowarnings(String *str, char*); com_warnings(String *str, char*), com_nowarnings(String *str, char*),
com_sandbox(String *str, char*);
#ifdef USE_POPEN #ifdef USE_POPEN
static int com_nopager(String *str, char*), com_pager(String *str, char*), static int com_nopager(String *str, char*), com_pager(String *str, char*),
...@@ -311,6 +312,8 @@ static COMMANDS commands[] = { ...@@ -311,6 +312,8 @@ static COMMANDS commands[] = {
{ "prompt", 'R', com_prompt, 1, "Change your mysql prompt."}, { "prompt", 'R', com_prompt, 1, "Change your mysql prompt."},
{ "quit", 'q', com_quit, 0, "Quit mysql." }, { "quit", 'q', com_quit, 0, "Quit mysql." },
{ "rehash", '#', com_rehash, 0, "Rebuild completion hash." }, { "rehash", '#', com_rehash, 0, "Rebuild completion hash." },
{ "sandbox", '-', com_sandbox, 0,
"Disallow commands that access the file system (except \\P without an argument and \\e)." },
{ "source", '.', com_source, 1, { "source", '.', com_source, 1,
"Execute an SQL script file. Takes a file name as an argument."}, "Execute an SQL script file. Takes a file name as an argument."},
{ "status", 's', com_status, 0, "Get status information from the server."}, { "status", 's', com_status, 0, "Get status information from the server."},
...@@ -1675,6 +1678,8 @@ static struct my_option my_long_options[] = ...@@ -1675,6 +1678,8 @@ static struct my_option my_long_options[] =
&safe_updates, &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, &safe_updates, &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"i-am-a-dummy", 'U', "Synonym for option --safe-updates, -U.", {"i-am-a-dummy", 'U', "Synonym for option --safe-updates, -U.",
&safe_updates, &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, &safe_updates, &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"sandbox", 0, "Disallow commands that access the file system (except \\P without an argument and \\e).",
&status.sandbox, &status.sandbox, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"secure-auth", 0, "Refuse client connecting to server if it" {"secure-auth", 0, "Refuse client connecting to server if it"
" uses old (pre-4.1.1) protocol.", &opt_secure_auth, " uses old (pre-4.1.1) protocol.", &opt_secure_auth,
&opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, &opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
...@@ -4146,6 +4151,8 @@ static int com_tee(String *, char *line) ...@@ -4146,6 +4151,8 @@ static int com_tee(String *, char *line)
{ {
char file_name[FN_REFLEN], *end, *param; char file_name[FN_REFLEN], *end, *param;
if (status.sandbox)
return put_info("Not allowed in the sandbox mode", INFO_ERROR, 0);
if (status.batch) if (status.batch)
return 0; return 0;
while (my_isspace(charset_info, *line)) while (my_isspace(charset_info, *line))
...@@ -4226,6 +4233,8 @@ static int com_pager(String *, char *line) ...@@ -4226,6 +4233,8 @@ static int com_pager(String *, char *line)
} }
else else
{ {
if (status.sandbox)
return put_info("Not allowed in the sandbox mode", INFO_ERROR, 0);
end= strmake_buf(pager_name, param); end= strmake_buf(pager_name, param);
while (end > pager_name && (my_isspace(charset_info,end[-1]) || while (end > pager_name && (my_isspace(charset_info,end[-1]) ||
my_iscntrl(charset_info,end[-1]))) my_iscntrl(charset_info,end[-1])))
...@@ -4321,6 +4330,9 @@ static int com_shell(String *, char *line) ...@@ -4321,6 +4330,9 @@ static int com_shell(String *, char *line)
{ {
char *shell_cmd; char *shell_cmd;
if (status.sandbox)
return put_info("Not allowed in the sandbox mode", INFO_ERROR, 0);
/* Skip space from line begin */ /* Skip space from line begin */
while (my_isspace(charset_info, *line)) while (my_isspace(charset_info, *line))
line++; line++;
...@@ -4416,6 +4428,9 @@ static int com_source(String *, char *line) ...@@ -4416,6 +4428,9 @@ static int com_source(String *, char *line)
FILE *sql_file; FILE *sql_file;
my_bool save_ignore_errors; my_bool save_ignore_errors;
if (status.sandbox)
return put_info("Not allowed in the sandbox mode", INFO_ERROR, 0);
/* Skip space from file name */ /* Skip space from file name */
while (my_isspace(charset_info,*line)) while (my_isspace(charset_info,*line))
line++; line++;
...@@ -4450,6 +4465,7 @@ static int com_source(String *, char *line) ...@@ -4450,6 +4465,7 @@ static int com_source(String *, char *line)
bfill((char*) &status,sizeof(status),(char) 0); bfill((char*) &status,sizeof(status),(char) 0);
status.batch=old_status.batch; // Run in batch mode status.batch=old_status.batch; // Run in batch mode
status.sandbox=old_status.sandbox;
status.line_buff=line_buff; status.line_buff=line_buff;
status.file_name=source_name; status.file_name=source_name;
glob_buffer.length(0); // Empty command buffer glob_buffer.length(0); // Empty command buffer
...@@ -4571,6 +4587,13 @@ static int com_use(String *, char *line) ...@@ -4571,6 +4587,13 @@ static int com_use(String *, char *line)
return 0; return 0;
} }
static int com_sandbox(String *, char *)
{
status.sandbox= 1;
put_info("Sandbox mode.", INFO_INFO);
return 0;
}
static int com_warnings(String *, char *) static int com_warnings(String *, char *)
{ {
show_warnings = 1; show_warnings = 1;
......
...@@ -633,3 +633,27 @@ drop table t1; ...@@ -633,3 +633,27 @@ drop table t1;
WARNING: option '--enable-cleartext-plugin' is obsolete. WARNING: option '--enable-cleartext-plugin' is obsolete.
1 1
1 1
# End of 10.3 tests
#
# MDEV-21778 Disable system commands in mysql/mariadb client
#
ERROR at line 1: Not allowed in the sandbox mode
1
ERROR at line 1: Not allowed in the sandbox mode
2
ERROR at line 1: Not allowed in the sandbox mode
3
1
entering sandbox
system
tee
source
^^^
2
entering sandbox
system
tee
source
^^^
3
# End of 10.5 tests
...@@ -716,3 +716,43 @@ drop table t1; ...@@ -716,3 +716,43 @@ drop table t1;
# #
--echo --echo
--exec $MYSQL test --enable-cleartext-plugin -e "select 1" --exec $MYSQL test --enable-cleartext-plugin -e "select 1"
--echo # End of 10.3 tests
--echo #
--echo # MDEV-21778 Disable system commands in mysql/mariadb client
--echo #
--error 1
--exec $MYSQL --sandbox -Ne "select 1; \! echo foo; select 0" 2>&1
--error 1
--exec $MYSQL --sandbox -Ne "select 2; \T echo foo; select 0" 2>&1
--error 1
--exec $MYSQL --sandbox -Ne "select 3; \. echo.foo; select 0" 2>&1
--write_file $MYSQL_TMP_DIR/mysql_in
select 'entering sandbox';
\-
select 'system';
\! echo foo
select 'tee';
\T echo foo
select 'source';
\. echo.foo
select '^^^';
EOF
write_line "select 1;
source $MYSQL_TMP_DIR/mysql_in;
select 2;
source $MYSQL_TMP_DIR/mysql_in;
sandbox;
select 3;
source $MYSQL_TMP_DIR/mysql_in;" $MYSQL_TMP_DIR/mysql_in2;
--exec $MYSQL -fN <$MYSQL_TMP_DIR/mysql_in2
--remove_file $MYSQL_TMP_DIR/mysql_in
--remove_file $MYSQL_TMP_DIR/mysql_in2
--echo # End of 10.5 tests
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment