远程调用脚本并校验MD5的安全方案

当需要通过 curl 远程调用并运行脚本时,同时需要校验脚本的完整性(MD5校验),以下是几种安全实现方式:

方法1:下载脚本后校验MD5再执行

#!/bin/bash

SCRIPT_URL="https://example.com/script.sh"
EXPECTED_MD5="d41d8cd98f00b204e9800998ecf8427e"  # 替换为正确的MD5值

# 下载脚本
TEMP_SCRIPT=$(mktemp)
curl -fsSL "$SCRIPT_URL" -o "$TEMP_SCRIPT" || { echo "下载失败"; exit 1; }

# 计算MD5校验和
ACTUAL_MD5=$(md5sum "$TEMP_SCRIPT" | awk '{print $1}')

# 校验
if [ "$EXPECTED_MD5" != "$ACTUAL_MD5" ]; then
    echo "MD5校验失败!预期: $EXPECTED_MD5,实际: $ACTUAL_MD5"
    rm -f "$TEMP_SCRIPT"
    exit 1
fi

# 执行脚本
chmod +x "$TEMP_SCRIPT"
"$TEMP_SCRIPT"
rm -f "$TEMP_SCRIPT"

方法2:直接管道传输并校验(较不安全)

EXPECTED_MD5="d41d8cd98f00b204e9800998ecf8427e"
SCRIPT_URL="https://example.com/script.sh"

# 下载、校验并执行(不推荐,存在竞态条件)
curl -fsSL "$SCRIPT_URL" | {
    tee >(md5sum > /tmp/script.md5) | \
    if [ "$(cat /tmp/script.md5 | awk '{print $1}')" = "$EXPECTED_MD5" ]; then
        bash
    else
        echo "MD5校验失败"
        exit 1
    fi
}

方法3:使用更安全的SHA校验(推荐)

#!/bin/bash

SCRIPT_URL="https://example.com/script.sh"
EXPECTED_SHA256="aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f"

TEMP_SCRIPT=$(mktemp)
curl -fsSL "$SCRIPT_URL" -o "$TEMP_SCRIPT" || { echo "下载失败"; exit 1; }

# 计算SHA256
ACTUAL_SHA256=$(sha256sum "$TEMP_SCRIPT" | awk '{print $1}')

if [ "$EXPECTED_SHA256" != "$ACTUAL_SHA256" ]; then
    echo "SHA256校验失败!预期: $EXPECTED_SHA256,实际: $ACTUAL_SHA256"
    rm -f "$TEMP_SCRIPT"
    exit 1
fi

chmod +x "$TEMP_SCRIPT"
"$TEMP_SCRIPT"
rm -f "$TEMP_SCRIPT"

安全建议

  1. 优先使用SHA256:MD5已被证明不安全,建议使用SHA256或SHA512
  2. 使用HTTPS:确保下载链接是HTTPS而非HTTP
  3. 临时文件处理:使用mktemp创建临时文件,执行后立即删除
  4. 考虑使用GPG签名:比单纯的哈希校验更安全
  5. 避免直接管道执行:方法2存在安全隐患,不推荐生产环境使用

GPG签名验证方案(最安全)

#!/bin/bash

SCRIPT_URL="https://example.com/script.sh"
SIG_URL="https://example.com/script.sh.sig"
GPG_KEY_URL="https://example.com/public.key"

# 下载脚本和签名
TEMP_SCRIPT=$(mktemp)
TEMP_SIG=$(mktemp)
TEMP_KEY=$(mktemp)

curl -fsSL "$SCRIPT_URL" -o "$TEMP_SCRIPT"
curl -fsSL "$SIG_URL" -o "$TEMP_SIG"
curl -fsSL "$GPG_KEY_URL" -o "$TEMP_KEY"

# 导入GPG密钥
gpg --import "$TEMP_KEY"

# 验证签名
if gpg --verify "$TEMP_SIG" "$TEMP_SCRIPT"; then
    chmod +x "$TEMP_SCRIPT"
    "$TEMP_SCRIPT"
else
    echo "GPG签名验证失败!"
fi

# 清理
rm -f "$TEMP_SCRIPT" "$TEMP_SIG" "$TEMP_KEY"

选择哪种方案取决于您的安全需求,对于关键系统,建议使用GPG签名验证方式。

文档更新时间: 2025-07-11 00:01   作者:月影鹏鹏
IT运维支持-AIWALY-月影工作室