通过 Bash 脚本转义 MYSQL 命令行
PHP 有 mysql_real_escape_string()
来正确转义任何可能导致问题的字符。为 BASH 模拟此功能的最佳方法是什么?
无论如何,有没有使用 bash 做准备好的 mysql 语句?这似乎是最好的办法。
我的大多数变量不会(不应该)有特殊字符,但是我给用户完全自由的密码。它可能包含像 ' 和 " 这样的字符。
我可能正在执行多个 SQL 语句,因此我想要制作一个接受参数然后运行该语句的脚本。这是我到目前为止所拥有的:
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
和一个示例使用上述命令:
example.sh:
PASSWORD=$1
doSQL "INSERT INTO active_records (password) VALUES ('$PASSWORD')"
显然,如果密码密码中包含单引号,则这会失败。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
在 Bash 中,
printf
可以为您进行转义:我将让您决定这是否足够激进。
In Bash,
printf
can do the escaping for you:I'll leave it to you to decide if that's aggressive enough.
这似乎是一个使用错误工具完成工作的典型案例。
要在 bash 中实现
mysql_real_escape_string()
完成的转义,您还有大量工作要做。请注意,mysql_real_escape_string() 实际上将转义委托给 MySQL 库,该库会考虑连接和数据库字符集。它之所以被称为“真实”,是因为它的前身mysql_escape_string()
没有考虑字符集,并且可能被欺骗注入 SQL。我建议使用具有 MySQL 库的脚本语言,例如 Ruby、Python 或 PHP。
如果您坚持使用 bash,请使用 MySQL 准备的语句语法。
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 thatmysql_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 predecessormysql_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.
无论您使用什么引号,都无法逃脱以下构造:
There is no escape from the following construct, no matter what quotes you use:
mysql_real_escape_string()
当然,仅转义要引用的单个字符串文字,而不是整个语句。您需要清楚该字符串在语句中的用途。根据 MySQL 手册中关于字符串文字的部分,对于插入字符串字段时,您只需要转义单引号和双引号、反斜杠和 NUL。但是,bash 字符串不能包含 NUL,因此以下内容应该足够了:如果您将在
LIKE
之后使用该字符串,您可能还需要转义%
和<代码>_。准备好的陈述是另一种可能性。并确保您不在 bash 中使用
echo -e
。另请参阅 https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet
mysql_real_escape_string()
of course only escapes a single string literal to be quoted, not a whole statement. You need to be clear what purpose the string will be used for in the statement. According to the MySQL manual section on string literals, for inserting into a string field you only need to escape single and double quotation marks, backslashes and NULs. However, a bash string cannot contain a NUL, so the following should suffice:If you will be using the string after a
LIKE
, you will also probably want to escape%
and_
.Prepared statements are another possibility. And make sure you don't use
echo -e
in your bash.See also https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet
这将转义撇号
,但请注意 mysql_real_escape_string 也会转义 \x00、\n、\r、\、" 和 \x1a。为了完全安全,请务必转义这些。
例如,要转义 \x00:
稍加努力,您就可以可能使用一个 sed 命令来转义这些。
This will escape apostrophes
Please note though that mysql_real_escape_string also escapes \x00, \n, \r, \, " and \x1a. Be sure to escape these for full security.
To escape \x00 for example:
With a bit of effort you can probably escape these using one sed command.
当然,为什么不直接使用真实的东西呢?
注意:据我了解,使用
"$(cmd ..."$var")"
进行命令替换优于使用反引号。然而,由于不需要进一步的嵌套,所以两者都应该没问题。进一步注意:在命令替换
"$(...)"
内部时,会创建一个新的引用上下文。这就是变量周围的引号不会弄乱字符串的原因。Sure, why not just use the real thing?
Note: From what I understand, command substitution using
"$(cmd ..."$var")"
is preferred over using backticks. However, as no further nesting would be needed either should be fine.Further Note: When inside command substitution,
"$(...)"
, a new quote context is created. This is why the quotes around variables do not screw up the string.我就是这样做的,其中
my-file.txt
包含空格、换行符和引号:This is how I did it, where
my-file.txt
contains spaces, new lines and quotes:以下是我编写的几个 Bash 函数,它们被分组到一个库中。
它提供了正确引用/转义字符串和标识符的方法:
Here are a couple Bash functions I wrote, grouped into a library.
It provides methods for proper quoting/escaping strings and identifiers:
简短回答:使用
\
(转义字符)。如果您的值具有美元字符,例如:
$p123$hello
那么在 bash 中您可以通过\
转义它。那么字符串将是\$p123\$hello
在我的例子中,我已经像这样更改密码:
Short answer: use
\
(escape character).If your value has dollar character, for example:
$p123$hello
then in bash you may escape this by\
. Then string will be\$p123\$hello
In my case for example i have been change password like this:
这将起作用:
将其传递给变量:
This will work:
To pass it to a variable: