+2

File upload vulnerabilities - Các lỗ hổng upload tệp tin (Phần 2)

II. Phân tích và khai thác các lỗ hổng File upload (tiếp)

3. Kết hợp kỹ thuật path traversal

Đôi khi, hệ thống cài đặt thư mục lưu trữ các tệp do người dùng tải lên không có quyền thực thi. Đây là một cách ngăn chặn tốt, tuy nhiên, kẻ tấn công vẫn có thể tìm kiếm sự "may mắn" ở các thư mục khác bằng cách kết hợp với kỹ thuật path traversal.

Phân tích lab Web shell upload via path traversal

image.png

Miêu tả: Trang web chứa lỗ hổng upload file, trong đó cơ chế ngăn chặn không cho phép người dùng thực thi file. Để giải quyết bài lab, chúng ta cần vượt qua cơ chế này, khai thác lỗ hổng nhằm đọc nội dung tệp /home/carlos/secret. Tài khoản hợp lệ được cung cấp wiener:peter.

Đăng nhập với tài khoản wiener:peter. Upload một file php với nội dung như sau:

<?php
    echo file_get_contents('/home/carlos/secret');
?>

File được upload thành công:

image.png

Tuy nhiên, khi truy cập đường dẫn file chúng ta không thu được nội dung mong muốn, response chỉ trả về nội dung file được upload:

image.png

Điều này cho thấy chúng ta đã upload file thành công, tuy nhiên có thể thư mục chứa file upload đang được hệ thống cài đặt để không cho phép thực thi file với định dạng php. Bởi vậy chúng ta có thể kết hợp lỗ hổng Directory traversal, mục đích để đưa file upload tới thư mục khác cho phép thực thi file php, thay đổi tên file thành ../shell.php.

image.png

, trong response trả về, dòng thông báo chỉ còn avatars/shell.php, có vẻ cơ chế ngăn chặn đã loại bỏ chuỗi ../. Chúng ta có thể bypass cơ chế này với URL encode: ..%2fshell.php:

image.png

Bình thường file tải lên được lưu trữ tại thư mục /files/avatars (Có thể kiểm tra bằng cách upload một hình ảnh bình thường), còn trong trường hợp này do đã "lùi" một thư mục nên file được lưu tại thư mục /files. Có thể file upload được phép thực thi ở thư mục này, truy cập đường dẫn file upload:

image.png

File thực thi thành công và chúng ta có nội dung secret, submit và hoàn thành bài lab:

image.png

image.png

4. Bypass qua file signature - chữ ký tệp tin

Chữ ký tệp (file signature) là một chuỗi xác định các byte duy nhất được ghi vào tiêu đề của tệp. Trên hệ thống Windows, chữ ký tệp thường được chứa trong 20 byte đầu tiên của tệp. Các loại tệp khác nhau sẽ có các chữ ký tệp khác nhau, ví dụ: các tệp JPEG luôn bắt đầu bằng các byte FF D8 FF. Do đó hệ thống có thể kiểm tra định dạng file upload từ người dùng có phải hình ảnh hay không bằng cách kiểm tra signature của file tải lên.

Xét ví dụ sử dụng hàm exif_imagetype() thực hiện cơ chế này. Hàm exif_imagetype($filename) sẽ trả về false nếu tệp tải lên không thuộc các định dạng ảnh quy định, ngược lại nó sẽ trả về giá trị dạng số nguyên tương ứng với từng định dạng ảnh, ví dụ:

image.png

Cách cài đặt như sau:

<?php
$file_tmp_name = $_FILES["file"]["tmp_name"];
if (!exif_imagetype($file_tmp_name)) {
    die("Your upload file is not an image!");
}
?>

Lúc này chúng ta không thể upload một file với định dạng .php nữa:

image.png

Lưu ý rằng cách hoạt động của hàm exif_imagetype() là đọc các bytes đầu tiên của file upload và xác định kết quả có phải một tệp hình ảnh hay không dựa vào signature. Bởi vậy chúng ta có thể bypass cơ chế bảo vệ này bằng cách thêm GIF89a trong phần bắt đầu nội dung file, khi trang web kiểm tra ảnh bằng hàm exif_imagetype() sẽ xác định đây là một tệp GIF - thuộc một trong các định dạng ảnh quy định, khi đó hệ thống cho phép người dùng tải lên "hình ảnh" này. Thật vậy:

image.png

Ngoài ra có thể bypass bằng một số image signature khác:

image.png

image.png

image.png

...

5. Bypass thông qua phần mở rộng file

Một cơ chế ngăn chặn tấn công file upload tốt hơn là dựa vào phần mở rộng của tệp để kiểm tra đó có phải một hình ảnh hợp lệ hay không, ví dụ .png, .jpg, .jpeg, ...

Xét đoạn code xử lý phần mở rộng file upload như sau:

$file_ext = pathinfo($file_name, PATHINFO_EXTENSION);
$file_ext = str_replace('php', '', $file_ext);
$file_name = pathinfo($file_name, PATHINFO_FILENAME) . '.' . $file_ext;
$file_location = $file_dir . basename($file_name);

Biến $file_ext trích xuất phần mở rộng của file upload bằng hàm pathinfo(), sau đó sử dụng hàm str_replace() để loại bỏ chuỗi php trong phần mở rộng. Lúc này, khi upload file shell.php thì tên file sau khi xử lý trở thành shell.. File upload không còn thực thi được là do code PHP thực thi được cần có đuôi file là .php (hoặc với trường hợp đặc biệt như apache sử dụng .htaccess để thực thi tệp tin php), do vậy khi tên file được chuyển thành shell. thì không đủ điều kiện để hệ thống thực thi file này mặc dù nội dung file là mã PHP.

image.png

image.png

Do hàm str_replace() chỉ thực hiện thay thế chuỗi đầu tiên tìm kiếm được, nên chúng ta có thể bypass hàm này bằng cách sử dụng extension pphphp, như vậy sau khi thay thế thì shell.pphphp sẽ trở thành shell.php.

image.png

image.png

Xét một ví dụ khác xử lý phần mở rộng file:

$file_ext = pathinfo($file_name, PATHINFO_EXTENSION);
$black_list = ['php', 'Php', 'pHp', 'phP', 'PHp', 'PhP', 'pHP', 'PHP'];

if (in_array($file_ext, $black_list)) {
    return('Invalid extention!');
}

Sử dụng hàm in_array() kiểm tra phần mở rộng nếu nằm trong danh sách cấm $black_list sẽ ngăn cản người dùng upload. Chúng ta có thể bypass điều này bằng cách sử dụng một số kiểu phần mở rộng khác như .php5, .php7, .phps, ...

image.png

Phân tích lab Web shell upload via obfuscated file extension

image.png

Miêu tả: Trang web chứa lỗ hổng upload file, trong đó có một black list các extension file. Để giải quyết bài lab, chúng ta cần vượt qua cơ chế này, khai thác lỗ hổng nhằm đọc nội dung tệp /home/carlos/secret. Tài khoản hợp lệ được cung cấp wiener:peter.

Đăng nhập với tài khoản wiener:peter, với chức năng upload avatar, thử tải lên một file shell.php với nội dung như sau:

<?php
    echo file_get_contents('/home/carlos/secret');
?>

image.png

Hệ thống chỉ cho phép file dạng JPGPNG. Tất cả các cách bypass phía trên đều không hiệu quả, chúng ta cần nghĩ cách vượt qua black list hệ thống. Trong trường hợp này chúng ta có thể sử dụng ký tự null byte %00 để vượt qua cơ chế này (Lưu ý rằng bắt đầu từ phiên bản PHP 5.3.4, ký tự Null byte đã được fix). Sử dụng tên file shell.php%.png phần mở rộng trang web nhận được là .png không nằm trong black list, sau khi xử lý thì các ký tự bắt đầu từ ký tự Null byte được loại bỏ, tên file chỉ còn shell.php có thể thực thi.

image.png

Truy cập tới đường dẫn file upload thu được nội dung /home/carlos/secret:

image.png

Submit nội dung secret, bài lab hoàn thành:

image.png

image.png

Phân tích lab Web shell upload via extension blacklist bypass

image.png

Miêu tả: Trang web chứa lỗ hổng upload file, trong đó có một black list các extension file. Để giải quyết bài lab, chúng ta cần vượt qua cơ chế này, khai thác lỗ hổng nhằm đọc nội dung tệp /home/carlos/secret. Tài khoản hợp lệ được cung cấp wiener:peter.

Đăng nhập với tài khoản wiener:peter, với chức năng upload avatar, thử tải lên một file shell.php với nội dung như sau:

<?php
    echo file_get_contents('/home/carlos/secret');
?>

image.png

Hệ thống ngăn chặn người dùng tải lên file dạng php. Tất cả các cách bypass phía trên đều không hiệu quả. Lưu ý rằng chúng ta có thể tải lên nhiều file ảnh với cùng tên, và khi truy cập tới đường dẫn file upload sẽ hiển thị hình ảnh cuối cùng upload (các hình ảnh đã upload có cùng tên). Như vậy khả năng lớn hệ thống sẽ thay thế ảnh cuối cùng vào vị trí ảnh trước đó có cùng tên. Điều này dẫn đến chúng ta có thể ghi đè nội dung các file đã có.

Chúng ta nhắm tới file .htaccess - là một file có ở thư mục gốc của các hostting và do apache quản lý, cấp quyền. File .htaccess có thể điều khiển, cấu hình được nhiều yếu tố với đa dạng các thông số, nó có khả năng thay đổi các giá trị được set mặc định của Apache.

Upload một file với tên .htaccess, thay đổi header Content-Type thành giá trị text/plain, nội dung file như sau:

AddType application/x-httpd-php .viblo

Dòng lệnh trên sẽ tạo ra một ánh xạ cho phép các file có phần mở rộng là .viblo có quyền thực thi với Content-Type: application/x-httpd-php.

image.png

Như vậy, hiện tại chúng ta có thể upload các file với phần mở rộng .viblo và có thể thực thi các đoạn code tương đương với một file php.

image.png

Truy cập tới /avatars/shell.viblo:

image.png

Submit nội dung secret và bài lab hoàn thành:

image.png

image.png

V. Các tài liệu tham khảo


©️ Tác giả: Lê Ngọc Hoa từ Viblo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí