2016-06-26 86 views
3

我需要獲取用戶主文件夾。目前我使用這個無評估的Tilde擴展

home=$(eval echo ~$user) 

$user內容是由主叫方提供的,因此不被信任值。這裏使用的危險是eval?如果是(可能),如何解決它沒有它?

+0

類似'$(cd〜; pwd)'也許吧? – n0rd

+1

@ n0rd - 我認爲OP意味着他們需要獲得給定用戶名的主文件夾,這是從不可信任來源指定的用戶名。 –

+1

對於未經驗證的*輸入,'eval'是危險的;你可以確保'$ user'只包含一個有效的用戶名,例如'[[$ user =〜[a-zA-Z] [a-zA-Z0-9_]]] && home = $(eval echo 〜$用戶)'。 (我不記得具體是什麼構成了一個有效的用戶名,但它就像一個有效的標識符。) – chepner

回答

4

在擁有它的系統,你可以使用getent(1)

$ getent passwd "$username" | cut -d: -f 6 
/path/to/user/home 

確保雖然檢查結果爲空。

+0

很酷,我會與此一起去,謝謝。在我的Linux機器上工作。儘管如此,仍然看它是否也適用於cygwin。 – Paladin

1

Tilde擴展在解析過程中很早就發生,並且沒有任何方法可以在沒有多次評估的情況下實現您想要的功能。因此eval的一個解決方案。達到你想要什麼,最安全的方式是:

eval "$(printf "home=~%q" "$user")" 

多虧了%q修改,擴展$user將全面引用,所以這裏沒有危險(不修改行雖然,你一定會介紹一些安全漏洞)。

自身,則不應使用這樣的:這條線之後,你必須檢查你得到一個有效的目錄,例如,

if [[ ! -d $home ]]; then 
    echo >&2 "Couldn't find home dir for user $user" 
    exit 1 
fi 

而且考慮當user是空的:在這種情況下, home將是運行腳本的用戶的主目錄。你是否想要這種行爲取決於你。

還有一點需要考慮:當user包含斜槓:是否需要此功能取決於您。

現在,這取決於你想擁有什麼功能,它可能會更好,以驗證擴展$user對一些預定義的模式一勞永逸,例如,

if [[ $user != [a-z]*([-a-z0-9_]) ]]; then 
    echo >&2 'Provided user doesn't match valid pattern' 
    exit 1 
fi 

而且事實證明,用此驗證,您的解決方案很安全。


例子:

的情況一切正常:

$ user=gniourf 
$ eval "$(printf "home=~%q" "$user")" 
$ declare -p home 
declare -- home="/home/gniourf" 

,這將是你的代碼的危險的情況(與您的代碼,ls將被執行,而不是在這裏) :

$ user='; ls >&2' 
$ eval "$(printf "home=~%q" "$user")" 
$ declare -p home 
declare -- home="~; ls >&2"