🔎 What is Insecure Deserialization?
프로그래밍에서 직렬화(Serialization)와 역직렬화(Deserialization)가 사용되는데 직렬화는 객체를 전송 가능한 형태로 변형하는것으로 컴퓨터에 파일을 저장하거나 일련의 데이터를 화면에 출력하거나 네트워크를 통해 전송하는 것을 직렬화라고 하며, 역직렬화는 반대되는 개념으로 파일을 읽어 들이거나 출력되는 데이터를 다시 Object화 하거나 네트워크로부터 전송받은 데이터를 Obect화 하는 행위를 말합니다.
안전하지 않은 역직렬화는 사용자가 제어할 수 있는 데이터가 웹사이트에서 역직렬화되는 경우
입니다.
이상적으로는 사용자 입력이 절대 역직렬화가 되어서는 안됩니다.
How to identify insecure deserialization?
PHP serialization format
PHP는 데이터 유형을 나타내는 문자와 각 항목의 길이를 나타내는 숫자로 대부분 사람이 읽을 수 있는 문자열 형식을 사용합니다.
$user->name = "carlos";
$user->isLoggedIn = true;
직렬화 되면 위의 객체는 다음과 같이 보일 수 있습니다.
O:4:"User":2:{s:4:"name":s:6:"carlos"; s:10:"isLoggedIn":b:1;}
- O:4 = “User” 4자리 클래스 이름을 가진 객체
- 2 = 객체는 2개의 속성 존재
- s:4 = “name” 첫번째 속성의 키는 4자리 문자열
- s:6 = “carlos” 첫번째 속성의 값은 6글자 문자열
- s:10 = “isLoggedIn” 두번째 속성의 키는 10자리 문자열
- b:1 = 두번째 속성의 값은 boolean 값
PHP는 직렬화를 위한 기본 메소드로 serialize() 및 unserialize()를 사용하는데 코드 분석이 가능한 경우 unserialize() 함수를 찾아 분석을 시작하면 됩니다. (소스코드 분석 도구를 사용할것을 권장)
Java serialization format
직렬화된 개체 속성 수정(쿠키 변조)
User개체를 사용하여 사용자 세션에 대한 데이터를 쿠키값에 저장하는 웹사이트
O:4:"User":2:{s:8:"username";s:6:"carlos";s:7:"isAdmin";b:0;}
isAdmin 속성의 boolean값을 1(true)로 변경하고 개체를 다시 인코딩 후 현재 쿠키를 수정된 값으로 덮어 쓸 수 있습니다.
직렬화된 데이터 타입 수정
PHP 기반 로직은 서로 다른 데이터 유형을 비교할때 loose comparison operator(느슨한 비교 연산자) “==” 을 사용하게 되면 취약점이 발생하게 됩니다.
예를 들어, 정수와 문자열 간에 느슨한 비교를 수행할 경우 PHP는 문자열을 정수로 변환하려고 시도합니다.
즉 5 == “5” 가 true로 평가되게 됩니다.
일반적으로 숫자로 시작하는 모든 문자열에서도 작동합니다. 예를들어 5 == “5 of something”은 실제로 초기 숫자를 기준으로 전체 문자열을 정수 값으로 변환하기에 문자열의 나머지 부분은 완전히 무시되어 5==5로 취급받게 됩니다.
그러나 문제는 문자열과 정수 0을 비교할때 더욱 이상해집니다.
0 == "Example string" // true
위와같은 경우는 문자열에 숫자가 없어 0으로 반환되어 정수 0으로 처리하게 되어 true값을 반환하게 됩니다.
위와같은 느슨한 비교 연산자가 사용자가 제어할 수 있는 역직렬화된 개체의 데이터와 함께 사용될 경우 잠재적으로 위험한 logic flaws 를 발생할 수 있습니다.
🍁 Cheat sheet
👀 How to Prevent ?
일반적으로 필수로 필요한 경우가 아니라면 사용자 입력값의 역직렬화를 사용하지 않아야 합니다.
신뢰할 수 없는 데이터를 역직렬화 해야하는 경우 검증을 통하여 데이터가 변조되지 않았는지 확인(디지털 서명을 구현하여 데이터 무결성 확인 등)을 해야하며 이 떄 역직렬화 프로세스를 시작 하기 전 데이터 값을 비교
하여야 합니다.