hwp CTF 2018 unpack0r

CTF/Writeup 2018. 12. 10. 11:23

해당 문제는 대회 기간중엔 못풀고 롸업을 봤는데 트릭이 상당히 재미있어서 정리해 봤다.


먼저 문제에 들어가보면 아래와 같이 소스코드를 제공해 준다.


<?php
if (isset($_FILES['zip']) && $_FILES['zip']['size'] < 10*1024 ){
    
$d 'files/' bin2hex(random_bytes(32));
    
mkdir($d) || die('mkdir');
    
chdir($d) || die('chdir');

    
$zip = new ZipArchive();
    if (
$zip->open($_FILES['zip']['tmp_name']) === TRUE) {
        for (
$i 0$i $zip->numFiles$i++) {
            if(
preg_match('/^[a-z]+$/'$zip->getNameIndex($i)) !== 1){
                die(
':/ security');
            }
        }

        
exec('unzip ' escapeshellarg($_FILES['zip']['tmp_name']));
        echo 
$d;
    }
}
else {
    
highlight_file(__FILE__);
}


코드를 보면 파일 업로드 시 특정 디렉토리 경로를 생성하고 해당 경로에 zip파일을 unzip하여 압축된 파일들이 업로드 되는 형태이다.


이 때 압축된 파일명들에 대해 정규식을 통해 검증하는데 알파벳 소문자외에 값이 들어갈 수가 없다. 즉 일반적인 형태로는 웹쉘 업로드가 불가능한 형태였다.


여기서 일단 커멘드 인젝션 같은 경우 escapeshellarg 함수가 적용되어있고 인풋으로 들어가는 값이 임시파일명이라 내가 컨트롤할 수 없는 부분이라 취약점을 터트릴 수 가 없었다.


그래서 일단 생각한게 Symlink 트릭으로 내부 파일 읽어오려고 해봤더니 업로드된 파일에 링크만 걸려있으면 무조건 권한부족으로 403이 떴다.


여기서 한참 헤매면서 ZipArchive관련 취약점들을 찾으면서 삽질을 했다. 


대회 종료 후 롸업을 보니 취약점이 $zip->numFiles 부분에서 터지고 있었다.


위의 파일 검증 루틴을 보면 ZipArchive 객체의 numFiles 속성을 통해 Zip 파일 내 압축되어있는 파일 개수를 가져오는 데 이 값을 가져올 때 아래와 같이 Zip 파일 내 해당 헤더 영역의 값을 참조하게 된다.


  

저 값을 01에서 00으로 수정할 경우 $zip->numFiles 가 0으로 세팅되면서 반복문 내 파일명 검증 루틴을 Bypass할 수 있다.


그 후 unzip을 통해 헤더 값이 변조된 zip파일이 압축해제 될 때 unzip 명령어에서는 저 값과 상관없이 정상적으로 zip 내 파일들을 압축해제하게 되어 웹쉘 업로드가 가능해 진다.


위 형태에 맞춰서 php 확장자를 가진 파일을 압축한 다음 헤더 값을 변조하여 업로드하니 웹쉘 실행이 됐다.








Flag = hxp{please_ask_gynvael_for_more_details_on_zips_:>} 









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

Codegate 2014 clone technique  (1) 2018.12.29
X-MAS CTF 2018 Web Write up  (0) 2018.12.24
TenDollar CTF 2018 Cat-Proxy  (0) 2018.12.02
TenDollar CTF 2018 Kou  (0) 2018.12.01
TenDollar CTF 2018 XSS  (0) 2018.12.01
블로그 이미지

JeonYoungSin

메모 기록용 공간

,