Trong bài viết này, chúng ta sẽ tìm hiểu về cách hàm input hoạt động theo cách không mong muốn trong phiên bản 2.x hoặc các phiên bản trước đó. Trong phiên bản 2.x, hàm raw_input() hoạt động như sự thay thế của hàm input(). Trong các phiên bản mới hơn 3.x hoặc sau này, tất cả các tính năng & chức năng mong muốn của cả hai hàm được gộp vào hàm input().
Trước tiên hãy xem kiểu input của các hàm tích hợp sẵn để lấy input trong Python 2.x.
Ví dụ
# Input cho trước: String
str1 = raw_input("Output của raw_input(): ")
print(type(str1))
str2 = input("Output của input(): ")
print(type(str2))
# Input cho trước: Float
str3 = raw_input("Output của raw_input(): ")
print(type(str3))
str4 = input("Output của input(): ")
print(type(str4))
# Input cho trước: Integer
str5 = raw_input("Output của raw_input(): ")
print(type(str5))
str6 = input("Output của input(): ")
print(type(str6))
Kết quả
Output của raw_input(): Output của input(): Output của raw_input(): Output của input(): Output của raw_input(): Output của input():
Giải thích − Từ đầu ra, rõ ràng là hàm raw_input chuyển đổi tường minh input sang kiểu string bất kể kiểu input được cung cấp. Ngược lại, hàm input giữ nguyên kiểu dữ liệu như được cung cấp khi input.
Bây giờ sau khi xem ví dụ trên, bạn có thể thắc mắc nếu hàm input giữ nguyên kiểu dữ liệu thì tại sao nó lại dễ bị tấn công? Hãy làm rõ điều này bằng một minh họa:
MINH HỌA 1: Hãy tạo một trò chơi xúc xắc sử dụng module random.
Ví dụ
import random as rd
number = random.randint(1, 6)
print("Chọn một số từ 1 đến 6")
while True:
user_input = input("Đoán số: ")
if user_input == number:
print("Bạn đoán đúng.")
break
else:
print("Ối! Thử lần sau nhé.")
continue
Giải thích − Trong trường hợp người dùng cung cấp input kiểu integer, đầu ra mong muốn theo biểu thức điều kiện sẽ được tính toán tương ứng.
Trong trường hợp người dùng cung cấp input kiểu string giống hệt tên biến mà chúng ta lưu số nguyên ngẫu nhiên tạo ra bởi xúc xắc dùng module random, thì đầu ra cũng được tính toán. Nhưng đây không phải là đầu ra mong muốn. Thực tế nó phải raise lỗi báo kiểu input sai. Nó coi tên biến tương đương với số được nhập trực tiếp bởi người dùng, biểu thức cho giá trị Boolean True và trò chơi kết thúc. Ngược lại, nếu dùng raw_input(), không có vấn đề nào được gặp phải.
Lỗ hổng này có thể gây nguy hiểm trong trường hợp chúng ta lưu thông tin đăng nhập, chi tiết người dùng & mật khẩu tài khoản.
MINH HỌA 2: Hãy tạo một hệ thống yêu cầu PIN và so sánh với giá trị đã lưu.
Ví dụ
stored_value = 7863
def return_function():
return stored_value
inp = input()
if inp == stored_value:
print "Bạn đã nhập đúng"
else:
print "Ối! Sai rồi"
Giải thích
Như chúng ta đã thảo luận trong MINH HỌA trước, trong trường hợp input cung cấp là kiểu integer, hàm hoạt động bình thường. Nhưng trong bất kỳ trường hợp nào người dùng cung cấp input giống hệt giá trị trả về của hàm, điều kiện trở thành True và đầu ra được tạo ra.
Điều này rất nguy hiểm khi dùng trong xử lý thông tin quan trọng và bảo mật như PIN & mật khẩu. Điều này có thể khắc phục bằng cách sử dụng raw_input() trong Python 2.x.
Từ hai MINH HỌA trên, rõ ràng là hàm input làm cho chương trình sẵn sàng cho tấn công biến trực tiếp (Variable attack).
Kết luận
Trong bài viết này, chúng ta đã tìm hiểu về những vấn đề và lỗ hổng gặp phải khi sử dụng hàm input() trong Python 2.x.