简体   繁体   English

如何安全地通过ssh返回bash数组?

[英]How can I safely return a bash array over ssh?

In the bash shell, arrays can be easily quoted with declare -p , then eval ed later to return them to normal. bash shell中,可以很容易地用declare -p引用数组,然后稍后进行eval以使它们恢复正常。 This seems acceptable for passing an array (as part of a script) to a remote machine over SSH. 对于通过SSH将数组(作为脚本的一部分)传递到远程计算机,这似乎可以接受。

The problem is, going the other way across the wire I don't want to expect the same level of trust. 问题是,我不希望对方获得相同级别的信任。 If the remote machine was compromised, an infection could spread to the local machine through unsanitised eval statements. 如果远程计算机受到威胁,则感染可能会通过未经确认的eval语句传播到本地计算机。

Currently, to pass arrays between machines I use an approach like this: 当前,要在机器之间传递数组,我使用的是这样的方法:

#!/bin/bash

# Define the modules we expect to find installed on the remote machine
expected_modules=(foo-module bar 'baz 2.0')

# SSH into the remote machine, send the arrays back and forth with "declare -p"
unparsed_missing_modules=$(ssh remote-machine /bin/bash << EOF
    check_for_module() {
        # Placeholder so that this can be tested locally
        case \$1 in
            foo*) true;;
            *) false;;
        esac
    }

    $(declare -p expected_modules)
    missing_modules=()
    for module in "\${expected_modules[@]}"; do
        if ! check_for_module "\$module"; then
            missing_modules+=( "\$module" )
        fi
    done

    declare -p missing_modules
EOF
)

# Unpack the result (this is what I want to find an alternative to)
eval "$unparsed_missing_modules"

# Do something with the result after unpacking into an array
for module in "${missing_modules[@]}"; do
    echo "Warning: Remote machine is missing $module" >&2
done

The primary insecurity in this script is near the end, when the output of a ssh session is passed directly to eval . ssh会话的输出直接传递到eval时,此脚本中的主要不安全因素已接近尾声。 How can I sanitise this input in bash ? 如何在bash清理此输入?

The generic, safe answer is to NUL-delimit your array's entries, pass the literal NUL-delimited data over stdout, and use a while read loop to interpret it. 通用,安全的答案是对数组的条目进行NUL分隔,在stdout上传递文字NUL分隔的数据,并使用while read循环对其进行解释。

Observe: 注意:

get_remote_array() {
  local args
  local hostname=$1; shift
  printf -v args '%q ' "$@"
  ssh "$hostname" "bash -s $args" <<'EOF'
# in real-world use, print something more useful than the arguments we were started with
# ...but for here, this demonstrates the point:
printf '%s\0' "$@" 
EOF
}

array=( )
while IFS= read -r -d ''; do
  array+=( "$REPLY" )
done < <(get_remote_array "localhost" \
            $'I\ncontain\nnewlines' \
            'I want to $(touch /tmp/security-fail)' \
            "'"'I REALLY want to $(touch /tmp/security-fail), even in single quotes'"'")

echo "---- Shell-escaped content"
printf '%q\n' "${array[@]}"

echo "---- Unescaped content"
printf '<<%s>>\n' "${array[@]}"

This demonstration passes potentially malicious data in both directions, and demonstrates that it survives the round-trip unharmed. 此演示在两个方向上传递了潜在的恶意数据,并演示了它在不受损害的往返过程中仍然可以生存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM