Khai thác lỗ hổng File Upload trên php để up shell

1.Giới thiệu

    Trong thực tế chúng ta bắt gặp rất nhiều trang web cho phép chúng ta upload file từ máy lên. Đơn giản như upoad hình nền làm avatar hoặc gửi file video các thứ. Tuy nhiên nếu chúng ta không đảm bảo file upload lên được kiểm soát chặt chẽ, hacker rất có thể sẽ sử dụng các shell giả mạo dưới dạng file ảnh nhằm thực thi mã và chiếm quyền điều khiển. Bài viết này sẽ chỉ cho bạn 1 vài cách khai thác cơ bản khi đầu vào kiểm soát chưa được chặt chẽ. Vậy let's go.

2.Các cách khai thác

a. Khai thác cơ bản

    Đầu tiên cũng là đơn giản nhất. Đó là trang web tin tưởng hoàn toàn vào người dùng và không có bất kỳ biện pháp bảo vệ nào. Ta sẽ code 1 trang web đơn giản nhằm upload file như sau:

    Phần code php khi không có sự kiểm soát đầu vào sẽ có dạng:

    

    Giao diện trang web sẽ cho ta 1 chỗ để upload file:

    Sau khi upload thì file được lưu vào địa chỉ ./uploads/file_name. Ta sẽ thử gửi lên 1 ảnh 1 bất kỳ là test.jpg. Sau khi gửi lên thành công, ta có thể vào ./uploads/test.jpg để xem trực tiếp ảnh:

    

    Như vậy là upload thành công.Bây giờ ta sẽ thử up shell php lên, ở đây mình sử dụng tool pony shell để up:

    

    Sau khi upload và chạy ./uploads/shell.php thì đã vào được bảng terminal, tại đây ta có thể khai thác để chạy lệnh linux, từ đó lấy được thông tin:

    

b.Bypass MMI-Type

    Tiếp đến các trang web có thể giới hạn định dạng file, gọi là MMI file extension. Ta sẽ thêm 1 đoạn code như sau vào trang trước:

    Đoạn code trên sẽ sử dụng _FILES['userfile']['type'] để lấy file extension. Sau đó sử dụng hàm in_array để chỉ cho phép các file dạng jpg, gif và png. Ta thử up shell lên thì xuất hiện lỗi:

    

    Đến đây ta sẽ sử dụng burpsuite để khai thác. Bắt request bằng burpsuite ta được:

    

    Do file ta up lên là file php nên tại phần header sẽ có dạng Content-Type: application/x-php. Với đoạn code trên thì trang sẽ chỉ check xem Content-type có đúng định dạng hay không, còn không kiểm tra nội dung bên trong. Nên ta chỉ cần đổi Content-typecho phù hợp với file ảnh là được, ở đây ta sẽ dùng Content-Type: image/jpeg:

    Vậy là upload thành công.

c. Bypass getimagesize()

    Hàm getimagesize () sẽ đọc 1 lượng byte ban đầu nhất định nhằm xác định xem về định dạng file, chiều rộng cũng như chiều cao của file. Đoạn code sẽ được thêm như sau:

    Để bypass thì ta sẽ chỉnh sửa phần đầu của file php để hàm check sẽ nghĩ là file ảnh. Hoặc ta chỉ cần thêm đoạn GIF89a vào trước shell là được. Khi đó hàm sẽ check đây là 1 file gif. Thử kết hợp 2 lỗi trên và khai thác, sử dụng burpsuite để bắt và thay đổi content-type, sau đó thêm vào đầu đoạn shell GIF89a ta được:

    Vậy là upload thành công. Khá tiếc là cái pony shell sử dụng cách này lại không chạy được, Bạn có thể sử dụng các shell khác như mini shell hoặc r57 shell đều được.

d. Bypass pathinfo()

    Hàm pathinfo() sẽ lấy thông tin về đường dẫn truyền vào:

    Extension sẽ được check bởi đoạn sau dấu chấm cuối cùng. Ví dụ shell.php.jpg thì hàm pathinfo() sẽ check đây là 1 file jpg. Tuy nhiên nếu ta để như thế thì khi truyền url đoạn chứa shell vào sẽ không chạy được. Đến đây ta có 1 cách để khai thác. Đó là sử dụng null byte %00, hiểu đơn giản thì ta sẽ để file dạng shell.php%00.jpg hoặc shell.php/x00.jpg . Khi đó hàm sẽ hiểu là file ảnh. Tuy nhiên khi thực hiện upload ảnh thì đoạn sau %00 sẽ bị xóa mất, nên file trở lại thành shell.php và thực hiện khai thác bình thường. Tuy nhiên lỗi này đã được sửa từ phiên bản php 5.3.4 trở đi.

e. Một vài cách khai thác khác

  • Bên cạnh những cách khai thác trên. Đôi khi trang sẽ loại bỏ các file php bằng cách đưa các ký tự không cho phép vào blacklist. Thì ta có thể bypass bằng các sử dụng những đuôi như .Php, PhP, PHP5, php1, php2 vv.
  • Một vài trang web sẽ chỉ cho phép ta upfile với 1 dung lượng rất nhỏ. Khi đó ta chỉ có thể khai thác bằng cách sử dụng các shell đơn giản, ví dụ: <?system($_GET[0]);

3.Cách khắc phục

  • Trên đây là 1 vài cách trang web xử lý check file upload đi kèm với cách khai thác cơ bản.
  • Có rất nhiều cách để 1 trang web có thể khắc phục điều này. Với mình thì cách hay nhất là check xem nó thuộc file gì sau đó ta có thể thay đổi tên và fix cứng định dạng cho nó. Còn nếu file đó không nằm trong các định dạng cho phép thì sẽ bị bỏ qua và không cho upload.

    Up file lên sẽ được:

    Như vậy thì dù kẻ tấn công có vượt qua và up shell lên được thì vẫn không thể thực thi được lệnh do đã bị đổi định dạng sang file ảnh.

Nguồn: Viblo

Bình luận
Vui lòng đăng nhập để bình luận
Một số bài viết liên quan