[root-me]PHP Loose Comparison

바로 소스코드를 확인할 수 있으니 확인해보자.

간단하게 요약을 하면,

sanitize_user_input함수는 preg_replace를 가지고 필터링을 한다.
preg_replace("[검색 패턴]","[바꿀 패턴]","[기존 문장]")으로 사용이 되는데,

preg_replace($re, "", $input); 라는 의미는
사용자가 입력한 값에 $re(='/[^a-zA-Z0-9]/) 부분이 있으면 ""로 바꾸겠다는 의미.
즉, 입력값에 영어나 숫자가 아닌 다른 값이 있으면 없애버리겠다는 의미이다.
이 함수를 거쳐 seed값이 필터링된다.


secured_hash_function함수는 입력값을 받아 위처럼 필터를 거친 뒤, md5로 인크립트하는 과정이 추가되어 있다.
즉, md5 encrypt되는 값은 secured_hash_function을 거쳐야 한다.
이 함수를 거쳐 hash값이 필터링 및 md5 encrypt된다.


아래 소스까지 보면, $s.$r == $h로 비교를 하게 되는데,
$r부분은 난수를 발생시켜 $s과 결합시키는 부분이다.

==비교연산은 자료형까지는 비교를 하지 않으므로 이를 이용한 취약점 문제인 듯 하다.

문제에서 말한 Type Juggling이란,

Auto Casting, 자동 자료형 변환 등 부르는 이름이 다양하다.
서로 다른 자료형이라고 하더라도 편의를 위해 같이 쓰이는 경우에 자료형을 자동으로 변환시켜주는 것을 말한다. 심지어는 같은 자료형이라고 하더라도 다른 자료형으로 변환이 되는 경우도 존재한다.

이 때, 매직해쉬라는게 있는데, 특수한 포맷 형태일 경우에 발생한다.
0x로 시작하면 16진수,
0o로 시작하면 8진수,
0e,7e등으로 시작하면 지수(exponential)을 의미한다.
(7e21 = 7*10^21, 0e21 = 0*10^21 = 0)

처음에 입력한 값이 문자열 형태로 전달이 된다고 하더라도, 
PHP의 ==비교연산에 의해 Type Juggling이 된다.
이 과정에서 0e~~~는 연산 결과에 의해 0값이 되어 버린다.


이를 이용해 seed값과 hash값을 만들어보자.

md5는 32자리의 숫자로 이루어져 있다.
codebeautify의 string tool을 이용해 0e로 시작하는 아무 숫자나 만들자.

0e741283471289471289381290381111

그리고 이 값을 md5 online encrypt 툴을 이용해 Decrypting하면


md5를 복호화한 값을 얻을 수 있다.
이 값을 hash값 부분에 넣게 되면 소스코드에 의해 원래 만들었던 0e741283471289471289381290381111가 될 것이다.

seed 값에는 비교해서 0이 될 수 있는 값이면 0을 제외한 어떤 값이라도 상관이 없다.
(hash와 seed값은 0인지 아닌지를 먼저 검사한다.)
그래서 0e1234따위의 값으로 seed 값을 입력한다.


Check를 눌러 제출하면 flag를 얻을 수 있다.



댓글