好了,朋友们,你们可能见过这个臭名昭著的怪癖来掌握这些价值观:
query=`echo $QUERY_STRING | sed "s/=/='/g; s/&/';/g; s/$/'/"`
eval $query如果查询字符串是host=example.com&port=80,那么它就可以正常工作,并且您可以获得bash变量host和port中的值。但是,您可能知道精心设计的查询字符串将导致在服务器端执行任意命令。我正在寻找一个安全的替代品或不使用eval的替代方案。在一些研究之后,我发现了这些替代方案:
read host port <<< $(echo "$QUERY_STRING" | tr '=&' ' ' | cut -d ' ' -f 2,4)
echo $host
echo $port和
if [[ $QUERY_STRING =~ ^host=([^&]*)\&port=(.*)$ ]]
then
echo ${BASH_REMATCH[1]}
echo ${BASH_REMATCH[2]}
else
echo no match, sorry
fi不幸的是,这两个替代方案只有在pars以host,port的顺序出现时才有效。但它们可能会以相反的顺序出现。也可以有两个以上的pars,任何顺序都是可能和允许的。那么,您打算如何将值放入适当的bash var中呢?上述的方法可以修改吗?请记住,对于n个pars,就有n个!可能的命令。2个pars只有2个,但3个pars已经有3个了!= 6。
我回到了第一个方法。它可以安全地运行eval吗?你能以一种安全的方式用sed转换$QUERY_STRING $query吗?
编辑:请注意,此问题与参考的其他问题不同,并且不是重复的。这里的重点是以安全的方式使用eval。在另一个线程中没有回答的问题。
发布于 2019-09-28 20:46:57
此方法是安全的。它不计算或执行QUERY_STRING。它使用字符串操作将字符串拆分成多个片段:
QUERY_STRING='host=example.com&port=80'
declare -a pairs
IFS='&' read -ra pairs <<<"$QUERY_STRING"
declare -A values
for pair in "${pairs[@]}"; do
IFS='=' read -r key value <<<"$pair"
values["$key"]="$value"
done
echo do something with "${values[host]}" and "${values[port]}"URL“百分比解码”左侧作为练习。
发布于 2019-09-28 21:23:28
当字符串来自不受信任的来源时,必须避免始终执行这些字符串。因此,我强烈建议不要在Bash中使用eval,用字符串来做一些事情。
为了真正保存,我认为我应该将字符串回显到一个文件中,使用grep检索字符串的一部分,然后删除该文件。始终使用web根目录之外的目录。
#! /bin/bash
MYFILE=$(mktemp)
QUERY_STRING='host=example.com&port=80&host=lepmaxe.moc&port=80'
echo "${QUERY_STRING}" > ${MYFILE}
TMP_ARR=($(grep -Eo '(host|port)[^&]*' ${MYFILE}))
[ ${#TMP_ARR} -gt 0 ] || exit 1
[ $((${#TMP_ARR} % 2)) -eq 0 ] || exit 1
declare -A ARRAY;
for ((i = 0; i < ${#TMP_ARR[@]}; i+=2)); do
tmp=$(echo ${TMP_ARR[@]:$((i)):2})
port=$(echo $tmp | sed -r 's/.*port=([^ ]*).*/\1/')
host=$(echo $tmp | sed -r 's/.*host=([^ ]*).*/\1/')
ARRAY[$host]=$port
done
for i in ${!ARRAY[@]}; do
echo "$i = ${ARRAY[$i]}"
done
rm ${MYFILE}
exit 0这会产生以下结果:
lepmaxe.moc = 80
example.com = 80https://stackoverflow.com/questions/58146057
复制相似问题