해당 문제는 대회 때 풀지못하고 추후 롸업을 보고 다시 풀어보았다.


소스는 다음과 같다.


<?php
    stream_wrapper_unregister
('php');
    if(isset(
$_GET['hl'])) highlight_file(__FILE__);

    
$mkdir = function($dir) {
        
system('mkdir -- '.escapeshellarg($dir));
    };
    
$randFolder bin2hex(random_bytes(16));
    
$mkdir('users/'.$randFolder);
    
chdir('users/'.$randFolder);

    
$userFolder = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']);
    
$userFolder basename(str_replace(['.','-'],['',''],$userFolder));

    
$mkdir($userFolder);
    
chdir($userFolder);
    
file_put_contents('profile',print_r($_SERVER,true));
    
chdir('..');
    
$_GET['page']=str_replace('.','',$_GET['page']);
    if(!
stripos(file_get_contents($_GET['page']),'<?') && !stripos(file_get_contents($_GET['page']),'php')) {
        include(
$_GET['page']);
    }

    
chdir(__DIR__);
    
system('rm -rf users/'.$randFolder);


내 IP를 기반으로한 디렉토리 내에 profile이란 파일을 생성한다. 이 때 파일 내용은 $_SERVER 변수에 담긴 값들이 삽입된다. 


위의 상황에서 나는 특정 페이지를 include시킬 수 있다.이 때 내가 입력한 페이지에서 .을 제거하고 wrapper와 같은 경우 php wrapper를 사용할 수 없다. 


여기서 간단히 생각해볼 수 있는건 헤더값에 php코드넣고 profile 파일을 포함시키면 될 것 같지만 profile 내에 php,<? 문자열이 존재하는지 검증을 해 php코드를 삽입할 수가 없다. 


현 상황에서 lfi로는 해볼만한게 없었고, rfi 중 현재상황에서 사용가능한 data wrapper를 사용해봤지만 allow_url_include가 off라 사용이 불가능 했다.


일단 profile 파일을 include 시켜야 할 것 같기 때문에 실제로 일단 include부터 시켜보려하면 include가 되지 않는다. 그 이유는 기본적으로 $_SERVER에 PHP_SELF란 속성이 존재해서 include자체가 될 수가 없다. 


말도안되는 상황이지만 해당 서버에 설정을 보면 allow_url_fopen이 On으로 되어있고 이 설정은 일반적으로 디폴트가 On이다. 즉 file관련함수에서 data wrapper사용이 가능하다는 거다. 이 말은 data wrapper로 <?,php 검증은 우회가 가능한데, 추가로 data wrapper 값이 include내에 들어갔을때 allow_url_include가 off라 에러가터져서 필터링 우회한 의미가 없다는 거다.


근데 여기서 우리가 눈여겨봐야할 게 사용자별 디렉토리를 만들 때 무조건 내 IP가 아니라 X_FORWARED_FOR 헤더를 통해 지정된 IP가 존재하면 이걸로 디렉토리를 만든다. 이 값은 내가 컨트롤이 가능하기 떄문에 이 헤더를 통해 디렉토리를 data wrapper형태로 만들어놓으면 data wrapper로 파일내용 검증을 우회한 뒤 이 값이 include에서 wrapper로서가 아닌 디렉토리로서 먼저 인식되어 에러를 안내고 profile 포함이 가능해진다는 거다.


include에서 입력값을 처리하는 순서에 의해 이러한 현상이 발생하는 것 같다. 만약 입력값을 파일경로로서 먼저처리하지않고 wrapper인지 먼저 처리하고 파일경로인지 확인했다면 wrapper로서 인식되어 그대로 에러가 터졌을 것이다. 


해당 문제를 풀면서 느낀건 한 로직 한 로직 의심을가지고 바라보며 한 로직이 우회가능할 때 다음 로직에서 이전 값들이 유효한지를 막연히 추측할게 하니라 이 또한 연계해서 또 끝없는 의심으로 실제 검증테스트까지 다 해봐야한다는 거다. 막연히 이건 이래서 안되라고 생각할게 아니라 혹시?라는 생각이 필요할 것 같다.


여기까지 설명하고 났으니 exploit은 간단하다.



























'CTF > Writeup' 카테고리의 다른 글

NCSC CTF 2019 Web Wrietup  (0) 2019.02.04
Codegate CTF 2019 Preliminary Rich Project  (0) 2019.01.27
Insomnihack CTF Teaser 2019 l33t-hoster  (0) 2019.01.21
ROOT CTF 2017 ROOT Ransomware  (0) 2019.01.02
ROOT CTF 2018 CrackMe  (0) 2019.01.01
블로그 이미지

JeonYoungSin

메모 기록용 공간

,