本文旨在解釋和探討 Python 2.x 中 input() 函數的漏洞。在 Python 3 中,raw_input() 函數被刪除,它的功能被轉移到一個新的內置函數,稱為 input()。
在 Python 2.x 中有兩種常用的接收輸入的方法:
讓我們使用以下程序來確定兩者之間的區別:
# Python 2.x 程序顯示兩者之間的差異# input() 和 rawinput() 函數# 使用 raw_input() 函數的 3 個輸入,# 之後顯示輸入值的數據類型s1 = raw_input("Enter input to test raw_input() function: ")print type(s1)s2 = raw_input("Enter input to test raw_input() function: ")print type(s2)s3 = raw_input("Enter input to test raw_input() function: ")print type(s3)# 使用 input() 函數的 3 個輸入,# 之後顯示輸入值的數據類型s4 = input("Enter input to test input() function: ")print type(s4)s5 = input("Enter input to test input() function: ")print type(s5)s6 = input("Enter input to test input() function: ")print type(s6)
輸入:
Hello456[1,2,3]45"goodbye"[1,2,3]
輸出:
Enter input to test raw_input() function: <type 'str'>Enter input to test raw_input() function: <type 'str'>Enter input to test raw_input() function: <type 'str'>Enter input to test input() function: <type 'int'>Enter input to test input() function: <type 'str'>Enter input to test input() function: <type 'list'>
注意: 在 input() 函數中輸入字符串時,我們必須用雙引號將值括起來。這在 raw_input() 中不是必需的
input() 方法的漏洞在於,任何人都可以通過使用變量或方法的名稱來訪問訪問輸入值的變量。讓我們一一探討:
具有輸入變量值的變量能夠直接訪問輸入變量的值。
Python 2.x 程序使用變量顯示 input() 函數中的漏洞
import randomsecret_number = random.randint(1,500)print "Pick a number between 1 to 500"while True: res = input("Guess the number: ") if res==secret_number: print "You win" break else: print "You lose" continue
Python 3 演示 input() 函數的差異
import randomsecret_number = random.randint(1,500)print ("Pick a number between 1 to 500")while True: res = input("Guess the number: ") if res==secret_number: print ("You win") break else: print ("You lose") continue
輸入:
15
輸出:
Pick a number between 1 to 500Guess the number: You loseGuess the number:
輸入:
secret_number
輸出:
Pick a number between 1 to 500Guess the number: You win
可以看出,在第二種情況下,變量“secret_number”可以直接作為輸入給出,答案總是“你贏了”。它像直接輸入數字一樣評估變量,這意味著它始終返回 True Boolean。無法使用 raw_input,因為它不允許直接讀取變量。
Python 3 顯示了不同的結果。如果“secret_number”作為輸入,答案是“You lose”。
漏洞就在這裡,因為我們甚至可以提供函數的名稱作為輸入並訪問原本不應該訪問的值。
# Python 2.x 程序通過傳遞函數名作為參數來演示 input() 函數漏洞secret_value = 500# 返回秘密值的函數def secretfunction(): return secret_value# 使用 raw_input() 輸入數字input1 = raw_input("Raw_input(): Guess secret number: ")# input1 將被顯式轉換為字符串if input1 == secret_value: print "You guessed correct"else: print "wrong answer" # 使用 input() 輸入數字input2 = input("Input(): Guess the secret number: ")# input2 在輸入時進行評估if input2 == secret_value: print "You guessed correct"else: print "wrong answer"
輸入:
400secretfunction()
輸出:
Raw_input(): Guess secret number: wrong answerInput(): Guess the secret number: You guessed correct
在這組輸入/輸出中,我們可以看到,當我們使用 raw_input 時,我們必然要輸入正確的數字。然而,在使用 input() 函數時,我們甚至可以提供函數或變量的名稱,解釋器將對其進行評估。例如,這裡的 input() 函數的輸入被指定為函數“secretfunction()”的名稱。解釋器評估這個函數調用並返回我們希望找到的秘密數字,因此即使我們沒有輸入秘密數字,如果條件評估為真,我們也會返回:
secretfunction()secret_value
輸出:
Raw_input(): Guess secret number: wrong answerInput(): Guess the secret number: You guessed correct
正如第一點所解釋的,在這個例子中,我們也能夠在“input()”函數的輸入中簡單地輸入變量名“secret_number”,我們就能夠訪問秘密值。然而,當試圖在 raw_input() 函數的輸入中調用 secretfunction() 時,它給了我們錯誤,因為解釋器將我們的參數轉換為字符串,並且不將其評估為函數調用。
在 python 2.x 中使用 raw_input() 總是更好,然後將輸入顯式轉換為我們需要的任何類型。例如,如果我們希望輸入一個整數,我們可以執行以下操作
n = int(raw_input())
這可以防止惡意調用或評估函數。