이 글에서는 Python 2.x 버전에서 input() 함수가 어떻게 의도치 않은 방식으로 동작하는지 살펴봅니다. Python 2.x에서는 raw_input() 함수가 input() 함수를 대체하는 역할을 수행하며, 3.x 이상의 최신 버전에서는 두 함수의 모든 기능과 특성이 input() 함수 하나로 통합되었습니다.
먼저 Python 2.x에서 입력을 받기 위해 제공되는 내장 함수들의 동작 방식부터 확인해 보겠습니다.
예제
# Input Given : String
str1 = raw_input("Output of raw_input() function: ")
print type(str1)
str2 = input("Output of input() function: ")
print type(str2)
# Input Given : Float
str3 = raw_input("Output of raw_input() function: ")
print type(str3)
str4 = input("Output of input() function: ")
print type(str4)
# Input Given : Integer
str5 = raw_input("Output of raw_input() function: ")
print type(str5)
str6 = input("Output of input() function: ")
print type(str6)
출력 결과
Output of raw_input() function: Output of input() function: Output of raw_input() function: Output of input() function: Output of raw_input() function: Output of input() function:
설명 − 출력 결과에서 알 수 있듯이, raw_input() 함수는 사용자가 입력한 값의 자료형과 무관하게 항상 문자열(string) 타입으로 변환합니다. 반면 input() 함수는 입력 시 제공된 자료형을 그대로 유지합니다.
여기서 "자료형을 그대로 유지하면 오히려 편리할 텐데, 왜 취약하다는 걸까?"라는 의문이 들 수 있습니다. 다음 예시를 통해 그 이유를 명확히 살펴보겠습니다.
예시 1: random 모듈을 활용한 주사위 게임
예제
import random as rd
number = random.randint(1,6)
print ("Pick a number between 1 to 6")
while True:
user_input = input("Guess the number: ")
if user_input==number:
print ("You guessed it right.")
break
else:
print ("OOPS! try it next time.")
continue
설명 − 사용자가 정수형 값을 입력하면 조건문에 따라 의도한 대로 결과가 계산됩니다.
그러나 문제는 여기서 발생합니다. 만약 사용자가 문자열로 변수 이름과 동일한 값, 즉 random 모듈로 생성된 난수를 저장하고 있는 변수명을 그대로 입력하면 어떻게 될까요? 프로그램은 오류 없이 그대로 실행되어 결과를 출력합니다. 원래라면 잘못된 입력 타입에 대해 에러를 발생시켜야 하지만, input() 함수는 사용자가 직접 입력한 숫자와 변수명을 동일하게 취급하기 때문에 해당 표현식이 True로 평가되고 게임이 즉시 종료됩니다. 반면 raw_input()을 사용했다면 이러한 문제는 발생하지 않습니다.
이러한 취약점은 로그인 정보, 사용자 세부 정보, 계정 비밀번호 등을 다룰 때 치명적인 결과로 이어질 수 있습니다.
예시 2: PIN 번호를 입력받아 저장된 값과 비교하는 시스템
예제
stored_value = 7863
def return_function():
return stored_value
inp = input()
if inp == stored_value:
print "You Entered Correctly"
else:
print "Oops! It's Incorrect"
설명
앞선 예시에서 언급했듯이, 입력값이 정수형일 경우에는 함수가 정상적으로 작동합니다. 하지만 사용자가 함수의 반환값과 동일한 이름의 입력을 제공하면 조건문이 True로 평가되어 결과가 출력됩니다.
PIN 번호나 비밀번호처럼 중요하고 기밀성이 높은 정보를 처리할 때 이러한 동작은 매우 위험합니다. 다행히 Python 2.x에서 제공하는 raw_input()을 사용하면 이 문제를 손쉽게 해결할 수 있습니다.
위 두 가지 예시를 통해 input() 함수가 프로그램을 직접적인 변수 공격(Variable Attack)에 노출시킬 수 있다는 점이 분명해졌습니다.
결론
이 글에서는 Python 2.x 환경에서 input() 함수를 사용할 때 마주칠 수 있는 다양한 문제점과 보안 허점을 살펴보았습니다. 사용자 입력을 받을 때는 항상 문자열로 처리한 뒤 필요에 따라 명시적으로 형 변환을 수행하는 것이 안전한 코딩 습관입니다. 참고로 Python 3.x부터는 input() 함수가 내부적으로 raw_input()과 같이 동작하여 항상 문자열을 반환하므로, 이러한 취약점은 자연스럽게 해소되었습니다.