Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Escaping MYSQL command lines via Bash Scripting

PHP has mysql_real_escape_string() to correctly escape any characters that might cause problems. What is the best way to mimic this functionality for BASH?

Is there anyway to do prepared mysql statements using bash? This seems to be the best way.

Most of my variables won't (shouldn't) have special characters, however I give the user complete freedom for their password. It may include characters like ' and ".

I may be doing multiple SQL statements so I'll want to make a script that takes in parameters and then runs the statement. This is what I have so far:

doSQL.sh:

#!/bin/sh

SQLUSER="root"
SQLPASS="passwor339c"
SQLHOST="localhost"

SQL="$1"
SQLDB="$2"


if [ -z "$SQL" ]; then echo "ERROR: SQL not defined"; exit 1; fi
if [ -z "$SQLDB" ]; then SQLDB="records"; fi

echo "$SQL" | mysql -u$SQLUSER -p$SQLPASS -h$SQLHOST $SQLDB

and an example using said command:

example.sh:

PASSWORD=$1
doSQL "INSERT INTO active_records (password) VALUES ('$PASSWORD')"

Obviously this would fail if the password password contained a single quote in it.

like image 343
ParoX Avatar asked Dec 08 '10 00:12

ParoX


People also ask

How do you escape a command in bash?

A non-quoted backslash ' \ ' is the Bash escape character. It preserves the literal value of the next character that follows, with the exception of newline .

How do I run a SQL query in a bash script?

Run queries with “-e” option Basically, if you merely want to run a simple and short SQL query, use the -e option following the query. As the above code shows, the -D option is to specify which database to use and the -e option can execute a query.

How do I run a shell script from MySQL?

Save this question. mysql -u root -pmysql; SELECT TABLE_NAME AS "Table Name", table_rows AS "Quant of Rows", ROUND((data_length + index_length)/1024/1024,2) AS "Total Size Mb" FROM information_schema. TABLES WHERE information_schema.


3 Answers

In Bash, printf can do the escaping for you:

$ a=''\''"\;:#[]{}()|&^$@!?, .<>abc123'
$ printf -v var "%q" "$a"
$ echo "$var"
\'\"\\\;:#\[\]\{\}\(\)\|\&\^\$@\!\?\,\ .\<\>abc123

I'll leave it to you to decide if that's aggressive enough.

like image 194
Dennis Williamson Avatar answered Sep 19 '22 14:09

Dennis Williamson


This seems like a classic case of using the wrong tool for the job.

You've got a lot of work ahead of you to implement the escaping done by mysql_real_escape_string() in bash. Note that mysql_real_escape_string() actually delegates the escaping to the MySQL library which takes into account the connection and database character sets. It's called "real" because its predecessor mysql_escape_string() did not take the character set into consideration, and could be tricked into injecting SQL.

I'd suggest using a scripting language that has a MySQL library, such as Ruby, Python, or PHP.

If you insist on bash, then use the MySQL Prepared Statements syntax.

like image 34
hobodave Avatar answered Sep 17 '22 14:09

hobodave


There is no escape from the following construct, no matter what quotes you use:

PASSWORD=$1
doSQL "INSERT INTO active_records (password) VALUES (FROM_BASE64('$(echo -n $PASSWORD|base64)'))"
like image 20
brablc Avatar answered Sep 20 '22 14:09

brablc