首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在bash中提取CGI查询参数值

在bash中提取CGI查询参数值
EN

Stack Overflow用户
提问于 2019-09-28 19:53:45
回答 2查看 150关注 0票数 0

好了,朋友们,你们可能见过这个臭名昭著的怪癖来掌握这些价值观:

代码语言:javascript
运行
复制
query=`echo $QUERY_STRING | sed "s/=/='/g; s/&/';/g; s/$/'/"`
eval $query

如果查询字符串是host=example.com&port=80,那么它就可以正常工作,并且您可以获得bash变量host和port中的值。但是,您可能知道精心设计的查询字符串将导致在服务器端执行任意命令。我正在寻找一个安全的替代品或不使用eval的替代方案。在一些研究之后,我发现了这些替代方案:

代码语言:javascript
运行
复制
read host port <<< $(echo "$QUERY_STRING" | tr '=&' '  ' | cut -d ' ' -f 2,4)
echo $host
echo $port

代码语言:javascript
运行
复制
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。在另一个线程中没有回答的问题。

EN

回答 2

Stack Overflow用户

发布于 2019-09-28 20:46:57

此方法是安全的。它不计算或执行QUERY_STRING。它使用字符串操作将字符串拆分成多个片段:

代码语言:javascript
运行
复制
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“百分比解码”左侧作为练习。

票数 3
EN

Stack Overflow用户

发布于 2019-09-28 21:23:28

当字符串来自不受信任的来源时,必须避免始终执行这些字符串。因此,我强烈建议不要在Bash中使用eval,用字符串来做一些事情。

为了真正保存,我认为我应该将字符串回显到一个文件中,使用grep检索字符串的一部分,然后删除该文件。始终使用web根目录之外的目录。

代码语言:javascript
运行
复制
#! /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

这会产生以下结果:

代码语言:javascript
运行
复制
lepmaxe.moc = 80
example.com = 80
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58146057

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档