我有一個在 Ubuntu(版本 18.04.6 LTS)上運行的 Bash(版本 4.4.20(1))腳本會生成 SCP 錯誤。然而,當我在命令列上運行有問題的命令時,同一行運行良好。
該腳本旨在從遠程機器上 SCP 檔案并將其復制到/tmp
本地機器上。一個警告是腳本必須運行為root
(是的,我知道這很糟糕,這是概念驗證的事情),但root
不能在我的環境中執行無密碼 SCP。用戶me
可以如此無密碼的 SCP,所以當root
運行腳本時,它必須“借用”me
的公共 SSH 密鑰。
這是我的腳本,稍微刪減了一些:
#!/bin/bash
writeCmd() { printf '%q ' "$@"; printf '\n'; }
printf -v date '%(%Y%m%d)T' -1
user=me
host=10.10.10.100
file=myfile
target_dir=/path/to/dir/$date
# print command to screen so I can see what is being submitted to OS:
writeCmd su - me -c 'scp -C me@$host:/$target_dir/$file.txt /tmp/.'
su - me -c 'scp -C me@$host:/$target_dir/$file.txt /tmp/.'
輸出是:
su - me -c [email protected]://.txt/tmp/.
看起來 ' ' 字符沒有被列印,但目前,我認為這是一個顯示問題,而不是問題的根源。更嚴重的是我在實際的 SCP 命令中看不到我的變數。
是什么賦予了?為什么變數會被忽略?su
命令的一部分是否會以某種方式干擾?謝謝你。
(注意:如果您想知道為什么下面的評論似乎離題,這篇文章已從其早期形式重新編輯。)
uj5u.com熱心網友回復:
當你運行時:
writeCmd su - me -c 'scp -C me@$host:/$target_dir/$file.txt /tmp/.'
您會看到它的輸出是(相當于 -- 可能會更改版本):
su - me -c scp\ -C\ me@\$host:/\$target_dir/\$file.txt\ /tmp/.
重要的是,還沒有任何變數被替換(并且它們被轉義以表明它們在運行之后才會被替換su
)。
這很重要,因為只有已匯出的變數——成為環境變數而不是 shell 變數——才能在行程邊界中存活,例如由 shell 啟動外部su
命令引起的,或者由su
啟動一個新的單獨的 shell引起的解釋器作為目標用戶帳戶。因此,由 啟動的新 shellsu
無法訪問變數,因此它用空值替換它們。
有時,您可以通過匯出變數來解決這個問題:export host target_dir file
,如果su
通過環境傳遞就足夠了。然而,這是一個相當大的“如果”:有令人信服的安全理由不通過特權邊界傳遞任意環境變數。
更安全的方法是使用已替換的變數構建一個正確轉義的命令:
#!/usr/bin/env bash
# ^^^^- needs to be bash, not sh, to work reliably
cmd=( scp -C "me@$host:/$target_dir/$file.txt" /tmp/. )
printf -v cmd_v '%q ' "${cmd[@]}"
su - me -c "$cmd_v"
使用printf %q
是針對外殼注入攻擊的保護 - 確保名為 target_dir/tmp/evil/$(rm -rf ~)
不會洗掉您的主目錄。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/505003.html