wargame.kr 포스트는 이해한 내용과 복습을 위한 목적으로 작성되었습니다.

이번 포스트에서는 strcmp 문제에 대한 이해와 풀이를 진행해보도록 하겠습니다.


이번 문제도 어려움이 많았습니다. 이번 문제는 SQL 뿐만 아니라 PHP와 웹에 대한 이해가 필요합니다.


마음을 다잡고 문제를 풀어보도록 합시다.



 

 문제 이해


문제는 다음과 같습니다.


문제에서는 strcmp 함수의 취약점을 이용하여 우회 후, 플래그를 가져가라는 메시지가 작성되어 있습니다.

앙, 문제를 풀면서 strcmp 취약점에 대해 찾아봐야겠습니다.


문제로 들어가 소스를 확인해보았습니다.

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

    $password = sha1(md5(rand().file_get_contents("/var/lib/dummy_file")).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>" . auth_code("strcmp") ."</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>


4번 라인에서는 $password 값에 엄청나게 반복적으로 암호화를 수행한 것이 보입니다.

이렇게 해놓은 것으로 보아 password에 특정한 값을 넣어 때려맞추는 것은 불가능할 것 같습니다.


11번 라인에서는 strcmp 함수를 통해 비교한 값의 결과가 0이 리턴될 때 문제가 풀리도록 되어 있습니다.


이제 문제를 풀어봐야겠습니다.




 

 문제 풀이


일단 이번 문제를 풀기 앞서 strcmp에 대한 취약점을 찾아보도록 합시다.


 

 PHP strcmp 취약점


먼저 strcmp에 대한 이해가 먼저일 것 같습니다.


strcmp 함수는 두 개의 문자열을 비교하여 값을 리턴하는 구조입니다.


예시 : strcmp($a, $b);

(1) 만약 두 문자열의 값이 일치하면 0을 반환

(2) 만약 $a 값이 크면 양수를 반환

(3) 만약 $b 값이 크면 음수를 반환


그러나 PHP의 strcmp 함수는 문자열 두 개 중 하나가 배열일 경우 무조건 0을 반환한다는 취약점을 가지고 있습니다.


다음과 같은 테스트코드를 통해 시험을 해보실 수 있으실 것입니다.

<?php

$a = Array("a");
$b = "pass";

if(strcmp($a, $b)==0)
  echo "Strings are same !";
else
  echo "Strings are different!!";
?>


여기서 결과는 다음과 같습니다.


WARNING strcmp() expects parameter 1 to be string, array given on line number 6

Strings are same ! 


그렇다면 이제 POST 혹은 GET 방식으로 배열을 넘겨주게 되면 취약점으로 인해 우회가 가능할 것으로 보입니다.




 

 위의 기법을 응용한 문제풀이


위의 기법을 응요하기 위해서는 POST와 GET 방식으로 어떻게 배열을 보낼 수 있는지 알아봐야 합니다.

배열 값을 보내기 위해서는 다음과 같은 방법으로 보낼 수 있습니다.


GET : http://example.com/?value1[]='something'&value2[]='something'

POST : value1[]='something'&value2[]='something'


이제 값을 넘겨주도록 합시다.






+ Recent posts