我使用shell脚本与MySQL数据库进行通信。 MySQL支持将查询指定为shell参数,如下所示:
mysql my_db -B -N -e "select id from Table"
但是,如果我有一个参数,我想在查询中使用,我如何获得针对注入攻击的保护?
一种天真的方法是将变量值粘贴到请求中,但它不是很安全:
mysql my_db -B -N -e "select id from Table where name='$PARAM'"
是否有任何技巧或文档化的界面可以从命令行进行注入安全查询?
答案 0 :(得分:6)
您可以对该值进行base64编码,然后在MySQL中对其进行base64解码。 MySQL中有UDF用于将Base64数据转换为通用数据。此外,大多数系统要么具有uuencode,要么使用base64编码数据的“base64”命令。
答案 1 :(得分:0)
只要您通过连接参数构建SQL,您的应用程序就可以成功进行SQL注入攻击(如您的示例所示)。维基百科上有一篇关于此内容的文章:http://en.wikipedia.org/wiki/SQL_injection
我怀疑你会想要使用文章中提到的mysql_real_escape_string
函数编写一个unix过滤器来构建你的SQL查询。
考虑将SQL作为第一个参数传递,将变量作为后续参数传递,然后让它返回构造的SQL。如果您将过滤器命名为“blobbo”,则示例中的命令可能如下所示:
blobbo“从表中选择id,其中name =%s”$ PARAM
答案 2 :(得分:0)
您不仅要防止SQL注入,还要防止shell注入。您可能希望将查询(在清理任何动态部分之后)写入文件,然后将该文件重定向到mysql,而不是希望查询不会破坏shell。考虑:
PARAM="name'\"; rm -rf / ; echo 'pwn3d U"
成为
mysql my_db -B -N -e "select id from Table where name='name'"; rm -rf / ; echo 'pwn3d U'
或:
command 1: mysql my_db -B -N -e "select id from Table where name='name'"
command 2: rm -rf /
command 3: echo 'pwn3d U'
相反,做一些事情:
cat <<EOT > query.sql
select .... blah blaah blah .... sanitized query here
EOT
mysql my_db -B -N < query.sql
这将阻止任何用户指定的数据出现在shell命令本身中,从而防止至少一个级别的注入漏洞。但是,您仍然必须处理SQL注入问题。
答案 3 :(得分:0)
Sargun Dhillon的回答向我指出了正确的方向。不幸的是,在MySQL 5.6之前,FROM_BASE64不可用,所以我选择了UNHEX。
下面的脚本是一个从shell查询Redmine用户详细信息的示例。如果不受信任的用户有权访问此脚本,我仍然无法入睡,但在我的情况下它足够安全。 (它也仅限于字符串值,您不应该在查询中有问号,但这些限制对我来说没问题。)
#!/bin/bash
MYSQL_OPTS='--defaults-file=/etc/redmine/mysql.cnf'
mysql_query() {
local db=$1
local sql=$2
shift 2 || return 1
declare -a args=("$@")
sql=${sql//[%]/%%}
sql=${sql//[?]/UNHEX('%s')}
for ((i=0; i<${#args[@]}; i++)); do
args[$i]=$(echo -n "${args[$i]}" | hexdump -v -e '/1 "%02X"')
done
sql=$(printf "$sql" "${args[@]}")
mysql $MYSQL_OPTS "$db" -e "$sql" || return $?
}
for u in "$@"; do
mysql_query redmine 'select * from users where login=?\G' "$u"
done
如果您发现我错过了任何SQL或Shell注入,请发表评论。