Bash

為什麼在嘗試循環使用者 輸入的次數時會得到意外的輸出?

  • October 24, 2021

我正在編寫這個 bash shell 腳本:

#!/bin/bash

declare -i N
read N
for i in {1..$N}
do
 echo "Number: $i"
done

(我相信declare -i N使N整數)

但是在執行它時,我得到以下輸出:

>vim new.sh
>chmod +x passgen.sh
>./passgen.sh
15
Number: {1..15}

在這裡,我想從使用者那裡獲取限制,然後執行循環。

來自man bash

展開順序為:大括號展開;波浪號擴展、參數和變數擴展、算術擴展和命令替換(以從左到右的方式完成);分詞;和路徑名擴展。

正如您所看到的,大括號擴展是第一個,所以顯然它在您的問題中被跳過了。我會改用不同的循環。

雖然已經指出了大括號擴展的問題,但我將僅評論:

(我相信 declare -i N 使 N 成為整數)

我會回答,是的,確實如此,這是一個問題,因為它使其成為命令注入漏洞。使用該整數屬性集,無論何時為變數分配一個值,該值都會被解釋為算術表達式。

如果使用者a[$(reboot)]在該read提示下輸入,例如,這將導致重新啟動嘗試。

這是,的一個普遍問題bash,每當計算算術表達式時。即使使用ksh93 樣式的形式(帶或不帶)也會成為問題,因為 的內容仍然在該算術上下文中進行評估。zsh``ksh``for (( i = 1; i <= N; i++ ))``declare -i N``N

for i in {1..$N}``declare -i N在 ksh、zsh 或yash -o braceexpand(會在亂碼上循環但不會引入命令注入漏洞)中會很好(沒有),或者如果sh您的sh實現不基於ksh.

#! /bin/sh -
IFS= read -r N
i=1; while [ "$i" -lt "$N" ]; do
 printf '%s\n' "Number: $n"
done

ksh’s[仍將操作數-lt視為算術表達式,因此仍會引入命令注入漏洞。不要用[[ $i -lt $N ]]or (( i < N ))in bash//裡面也有問題zshksh

或者您可以使用awk/perl或任何適當的程式語言來執行循環,或者您可以首先清理輸入。

引用自:https://unix.stackexchange.com/questions/674627