ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • <Root-me> Local File Inclusion
    Wargame/Root-me = Web - Server 2022. 1. 18. 14:14

    Local File Inclusion

    각 경로에 있는 파일들을 보여준다.

     

    문제 설명을 살펴보면

    admin 구역에 접근하라고 한다.

     

    우측 상단을 보면 "guest | admin"을 찾을 수 있는데,

    admin을 누르면 로그인 창이 뜬다.

    문제 제목인 LFI 취약점을 이용하여 admin의 비밀번호를 찾아야 한다.

     

    sysadm, reseau, esprit 등 각 경로는 URL 쿼리의 파라미터로 결정하는 것을 확인할 수 있다.

    파라미터의 값으로 상위경로를 뜻하는 "../"을 입력해보면

    답으로 보이는 admin 파일을 찾을 수 있다.

     

    admin을 누르면

    "File : admin"만 출력한다. 파일이 아닌 디렉터리라 열리지 않는 것 같다.

     

    쿼리 파라미터 값을 "../admin"으로 주게되면

    index.php 파일을 찾을 수 있다.

     

    열어보면

    <?php
    
    function http_digest_parse($txt)
    {
        $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
        $data = array();
        $keys = implode('|', array_keys($needed_parts));
     
        preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);
    
        foreach ($matches as $m) {
            $data[$m[1]] = $m[3] ? $m[3] : $m[4];
            unset($needed_parts[$m[1]]);
        }
    
        return $needed_parts ? false : $data;
    }
    
    
    function auth($realm){
        header('HTTP/1.1 401 Unauthorized');
        header('WWW-Authenticate: Digest realm="'.$realm.'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
        die($realm);
    }
    
    
    $realm = 'PHP Restricted area';
    $users = array('admin' => 'OpbNJ60xYpvAQU8');
    
    
    if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
      auth($realm);
    }
    
    if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) || !isset($users[$data['username']]))
        auth($realm);
    
    
    $A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
    $A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
    $valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
    
    if ($data['response'] != $valid_response)
        auth($realm);
    
    echo "<html>
    	<head></head>
    	<body>
    	    <h3>You could use this password to validate the challenge !</h3>
    	</body>
          </html>";
    
    ?>

    $_SERVER['PHP_AUTH_DIGEST'], nonce, nc, cnonce, qop 등을 통해 다이제스트 인증 방식을 사용함을 알 수 있다.

     

    다이제스트(DIGEST) 인증은 비밀번호를 보내지않고, 비밀번호를 뒤섞어 만든 다이제스트를 보낸다.

    클라이언트와 서버 둘다 비밀번호를 알고 있으며, 서버는 클라이언트가 보낸 다이제스트가 알맞게 대응하는 지 검사한다.

     

    nonce는 재전송 방지를 위해 사용하는 일종의 출입증으로, 자주 바뀌며, nonce가 바뀔 때 마다 다이제스트도 바뀐다.

     

    qop는 "quality of protection"의 약자로, 클라이언트와 서버가 어떤 보호 기업을 어느 수준으로 사용할 것인지 약속한다.서버가 WWW-Authenticate 헤더에 qop 옵션을 쉼표로 구분하여 보낸다.

    클라이언트는 자신의 요구에 맞는 옵션을 선택하여 Authorization 헤더의 qop에 담아 보낸다.

    인증을 뜻하는 "auth"와 메시지 무결성 보호를 뜻하는 "auth-init" 2개의 옵션을 사용한다.

     

    서버가 realm, nonce, 알고리즘을 보내면, 클라이언트가 이를 이용해 다이제스트를 생성하여 서버에게 보낸다.

    서버는 클라이언트에게서 받은 다이제스트를 자신이 계산한 다이제스트와 일치하는 지 확인한다.

     

    그런데 admin의 비밀번호 값이 나와있음에도 불구하고 다이제스트 인증만 신경써 시간이 제법 걸렸다.

    $users = array('admin' => 'OpbNJ60xYpvAQU8');

    ...

Designed by Tistory.