해킹/wargame

[web hacking] strcmp 풀이

미스터 로봇 2023. 2. 28. 13:07

문제 소개

https://dreamhack.io/wargame/challenges/328/

 

[wargame.kr] strcmp

Description if you can bypass the strcmp function, you get the flag.

dreamhack.io

wargame.kr 사이트에 있던 문제입니다.

 

strcmp 함수

strcmp(string $string1, string $string2): int

문자열 두 개를 비교하는 함수입니다.

string1이 string2보다 작으면 -1을, 크다면 1을, 같다면 0을 반환합니다.

 

코드 분석

<?php
    require("./lib.php"); // for FLAG

    $password = sha1(md5(rand().rand().rand()).rand());

    if (isset($_GET['view-source'])) {
        show_source(__FILE__);
        exit();
    }else if(isset($_POST['password'])){
        sleep(1); // do not brute force!
        if (strcmp($_POST['password'], $password) == 0) {
            echo "Congratulations! Flag is <b>" . $FLAG ."</b>";
            exit();
        } else {
            echo "Wrong password..";
        }
    }

?>
<br />
<br />
<form method="POST">
    password : <input type="text" name="password" /> <input type="submit" value="chk">
</form>
<br />
<a href="?view-source">view-source</a>

소스코드를 살펴보면 3번째 줄에 password가 rand함수, md5 암호화, sha-1 암호화 과정을 거쳐 만들어진 것을 볼 수 있습니다.

그리고 10번 줄에서 사용자가 입력한 password가 암호화를 통해 생성한 password와 일치하는지 비교하고 있습니다.

일반적으로는 두 문자열이 같을 때 flag값을 얻어낼 수 있겠지만, rand함수는 시드에 따라 값이 변하기 때문에 유추해 낼 수 없습니다.

 

해결법

저희는 php5의 strcmp 함수에 있는 취약점을 이용할 것입니다.

기본적으로 두 문자열을 비교하는 함수이지만, strcmp(string, array) 이런 식으로 배열을 전달하게 되면, null을 리턴하게 됩니다.

또한 php의 == 비교 연산자를 살펴보면, 아래 자료와 같이 null과 0을 비교할 때 true를 반환하게 되어있습니다.

 

따라서 우리는 post 방식으로 password를 전달할 때, 문자열이 아닌 배열로 전달하면 될 것입니다.

 

<!--
<form method="POST">
	password : <input type="text" name="password"> <input type="submit" value="chk">
</form>
-->

<form method="POST">
	password : <input type="text" name="password[]"> <input type="submit" value="chk">
</form>

여기서 name="password"를 다음과 같이 name="password[]" 로 변경하고 아무 password나 입력한 후 submit을 하면,

post 방식으로 배열이 전달되어 flag 값을 취득할 수 있습니다.

 

취약점 보완법

strcmp 함수의 결과로 null이 나올 수 있으므로, 비교 연산자를 == 을 사용하는 것이 아닌, ===을 사용하게 되면,

null === 0 -> false 결과를 반환하기 때문에, 취약점을 보완할 수 있습니다.