Những nguy cơ từ các form upload và cách bảo vệ các form upload
Các form upload cho phép người dùng đầu cuối upload file lên trang web của bạn cũng giống như việc mở một của hậu cho tin tặc xâm nhập máy chủ của bạn. Mặc dù vậy, trong ứng dụng web hiện nay, upload là một nhu cầu phổ biến bởi nó giúp tương tác trở nên hiệu quả hơn. Upload file được cho phép ...
Các form upload cho phép người dùng đầu cuối upload file lên trang web của bạn cũng giống như việc mở một của hậu cho tin tặc xâm nhập máy chủ của bạn. Mặc dù vậy, trong ứng dụng web hiện nay, upload là một nhu cầu phổ biến bởi nó giúp tương tác trở nên hiệu quả hơn. Upload file được cho phép trong các ứng dụng mạng xã hội như Facebook và Twitter. Các diễn đàn, blog, Youtube, trang web thương mại điện tử hay cổng hỗ trợ trực tuyến cũng sử dụng tính năng này nhằm cho phép người dùng đầu cuối chia sẻ file với nhân viên công ty. Người dùng được phép tải lên hình ảnh, video, ảnh đại diện và nhiều khiểu file khác.
Nhiều chức năng cung cấp cho người dùng sẽ càng ẩn chứa nhiều nguy cơ tồn tại lỗ hổng và những lỗ hổng này sẽ bị tin tặc lợi dụng nhằm đoạt quyền truy cập vào trang web hay xâm nhập vào máy chủ. Sau khi kiểm thử một vài ứng dụng web, chúng tôi nhận ra rằng một lượng lớn các trang web nổi tiếng không có các form upload form bảo mật. Một vài lỗ hổng rất dễ khai thác và chúng ta có thể chiếm quyền truy cập vào tệp tin hệ thống của máy chủ lưu trữ ứng dụng web đó. Trong tài liệu này, chúng tôi mang đến cho bạn 8 cách thường gặp nhằm bảo vệ file upload form và làm thế nào một tin tặc có thể dễ dàng qua mặt các biện pháp bảo mật của bạn.
TRƯỜNG HỢP 1: FILE UPLOAD FORM ĐƠN GIẢN KHÔNG PHÊ DUYỆT
Trong PHP, một file upload form đơn giản thường chứa một HTML form và một PHP script. HTML form sẽ hiện thị trước người dùng và PHP script chứa code đảm nhận việc upload file. Dưới đây là một ví dụ minh họa
HTML Form:
<form enctype="multipart/form-data" action="uploader.php" method="POST"> <inputtype="hidden" name="MAX_FILE_SIZE" value="100000" /> Choose a file to upload: <inputname="uploadedfile" type="file" /><br /> <input type="submit" value="Upload File" /> </form>
PHP Code:
<?php $target_path = "uploads/"; $target_path = $target_path . basename($_FILES['uploadedfile']['name']); if (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { echo "The file " . basename($_FILES['uploadedfile']['name']) . " has been uploaded"; } else { echo "There was an error uploading the file, please try again!"; } ?>
Khi PHP nhận một yêu cầu POST với kiểu mã hóa multipart/form-data, nó sẽ tạo ra một file tạm thời với tên ngẫu nhiên trong một thư mục tạm thời (ví du /var/tmp/php6yXOVs). PHP cũng sẽ sử dụng biến mảng $_FILE với thông tin của tệp tin được tải lên:
- $_FILES[‘uploadedfile’][‘name’]: tên gốc của file trên máy người dùng
- $_FILES[‘uploadedfile’][‘type’]: kiểu của tệp tin
- $_FILES[‘uploadedfile’][‘size’]: dung lượng tệp tin đơn vị byte
- $_FILES[‘uploadedfile’][‘tmp_name’]: Tên tạm thời của tệp tin được tải lên lưu trữ trên máy chủ.
Hàm PHP move_uploaded_file sẽ chuyển file tạm thời đến địa chỉ được cung cấp bởi người dùng. Trong trường hợp này, đích đến sẽ nằm trong thư mục gốc uploads ở gốc của trang web. File có thể được truy cập bằng URL: http://www.domain.tld/uploads/uploadedfile.ext. Trong ví dụ đơn giản này không có giới hạn kiểu file cho phép tải lên và vì vậy tin tặc có thể tải một file PHP hay .NET với mã độc để xâm hại máy chủ.
Trông có vẻ là một ví dụ đơn giản nhưng chúng tôi đã gặp những đoạn code như vậy ở rất nhiều ứng dụng web.
TRƯỜNG HỢP 2: CÓ KIỂM DUYỆT KIỂU TỆP TIN
Một lỗi phổ biến các nhà phát triển web mắc phải khi thực hiện bảo mật cho các form upload file là chỉ kiểm tra kiểu trả về từ PHP. Khi một file được tải lên máy chủ, PHP sẽ đặt biến $_FILES[‘uploadedfile’][‘type’] cho kiểu file mà người dùng cung cấp. Tuy nhiên, một form upload nếu có kiểm duyệt không thể chỉ dựa vào giá trị này. Một người dùng độc hại có thể dễ dàng tải file lên server bằng việc sử dụng một script hoặc một vài ứng dụng tự động khác cho phép gửi yêu cầu HTTP POST và cho phép gửi kèm một kiểu file giả mạo.
TRƯỜNG HỢP 3: CHẶN NHỮNG PHẦN MỞ RỘNG NGUY HIỂM
Trong trường hợp này, chúng ta sẽ đề cập đến upload form sử dụng một danh sách đen những kiểu file không được phép. Danh sách các kiểu file nguy hiểm được tạo ra bởi các nhà phát triển và những kiểu file này sẽ bị chặn khi được upload.
Một bất lợi chính của việc sử dụng danh sách đen phần mở rộng không được phép là không thể liệt kê được toàn bộ những phần mở rộng mà tin tặc có thể dùng. Ví dụ nếu code được chạy trong một môi trường cho phép nhiều ngôn ngữ như Perl, Python, Ruby… thì danh sách này sẽ vô hạn. Một người dùng dộc hại có thể dễ dàng qua mặt bằng cách tải lên một tệp tin “.htacces” chứa một dòng lệnh giống như dưới đây:
AddType application/x-httpd-php .jpg
Dòng lện trên sẽ điều khiển Apache web server chạy file ảnh jpg như một PHP script. Tin tặc có thể tải một file với phần mở rộng .jpg chứa PHP code. Hình ảnh minh họa dưới đây cho thấy một file ảnh chứa lệnh phpinfo():
TRƯỜNG HỢP 4: PHẦN MỞ RỘNG KÉP
Tương tự trường hợp 3, thay vì kiểm tra chuỗi kí tự phần mở rộng trong toàn bộ tên file, nhà phát triển sẽ lấy phần mở rộng bằng cách kiểm tra các kí tự sau dấu “.” . Tuy nhiên việc sử dụng mở rộng kép sẽ qua mặt biện pháp kiểm duyệt này. Đầu tiên, hãy cùng xem Apache xử lí file có nhiều phần mở rộng như thế nào. “File có thể có nhiều phần mở rộng và thứ tự phần mở rộng không quan trọng. Ví dụ nếu file welcom.html.fr chứa nội dụng kiểu text/html và ngôn ngữ Pháp thì tệp tin welcome.fr.html cũng chứa thông tin tương tự như vậy. Nếu phần mở rộng chứa cùng kiểu meta-infomation thì phần mở rộng phía ngoài cùng bên phải sẽ được sử dụng, trừ ngôn ngữ và nội dung mã hóa. Ví dụ .gif là của kiểu file hình ảnh và .html là kiểu text/html thì welcome.gif.html sẽ được hiểu là kiểu text/html”.
Vì vậy một file có tên “filename.php.124” sẽ được coi như một file PHP và sẽ được chạy. Nó sẽ hoạt động nếu phần mở rộng cuối cùng (.124) không nằm trong danh sách kiểm duyệt. Nhà phát triển web thường không nhận thức được tính năng này trên Apache và một vài trường hợp sẽ rất nguy hiểm. Không thể đoán trước được tất cả các trường hợp phần mở rộng mà người dùng độc hại có thể tải file lên máy chủ.
TRƯỜNG HỢP 5: PHẦN MỞ RỘNG KÉP (phần 2)
Một cách tiếp cận tốt hơn nhằm bảo vệ file upload form là tại danh sách trắng. Trong trường hợp này, nhà phát triển sẽ tạo ra một danh sách các phần mở rộng được phép một cách cụ thể. Tuy nhiên trong một số trường hợp cách tiếp cận này sẽ không hiệu quả như mong đợi. Khi Apache được cấu hình thực thi PHP code, có 2 cách: sử dụng AddHandler trực tiếp hoặc sử dụng AddType. Nếu AddHandler được sử dụng, tất cả tên file chứa .php sẽ được chạy như PHP script. Tuy nhiên, nếu cấu hình Apache chứa những dòng lệnh dưới đây, bạn có thể sẽ bị tấn công:
AddHandler php5-script .php
Tin tặc có thể tải một tệp tin ‘filename.php.jpg’ để vượt qua biện pháp bảo vệ và thực thi mã độc.
TRƯỜNG HỢP 6: KIỂM TRA HEADER ẢNH
Khi chỉ cho phép tải ảnh lên, các nhà phát triển thường kiểm duyệt header của ảnh bằng cách sử dụng hàm PHP getimagesize. Khi gọi hàm này sẽ trả về dung lượng của ảnh. Nếu kiểm duyệt ảnh thất bại nghĩa là header của ảnh không đúng và hàm sẽ trả về false. Vì vậy một nhà phát triển cơ bản thường sử dụng thông tin này để kiểm duyệt. Nếu tin tặc cố gắng tải một PHP shell tích hợp trong một tệp tin jpg, hàm sẽ trả về false và sẽ không thể tải file lên nữa. Tuy nhiên, cách này dễ dàng bị vượt qua nếu ảnh được mở bởi một trình chỉnh sửa ảnh như Gimp, có thể chỉnh sửa comment trong ảnh và chèn PHP code:
Hình ảnh vẫn có header hợp lệ vì vậy vượt qua kiểm duyệt dễ dàng.
TRƯỜNG HỢP 7: BẢO VỆ THƯ MỤC UPLOAD BẰNG .HTACCESS
Một trong những cách phổ biến bảo vệ file upload form là bảo vệ thư mục nơi file được tải lên thông qua file .htaccess. Ý tưởng này là ngăn ngừa việc thực thi script file trong thư mục này. Một file .htacess thường chứa code dưới đây:
AddHandler cgi-script .php .php3 .php4 .phtml .pl .py .jsp .asp .htm .shtml .sh .cgi Options –ExecCGI
Đây là một cách tiếp cận khác của danh sách đen vốn thường không bảo mật. Trong PHP, phần move_uploaded_file có cảnh báo “nếu file gốc đã tồn tại, nó sẽ bị ghi đè”. Bởi vì file được tải lên có thể ghi đè nên tin tặc có thể dễ dàng thay thế file .htaccess với phiên bản khác.
TRƯỜNG HỢP 8: KIỂM DUYỆT PHÍA NGƯỜI DÙNG
Một trong những cách bảo mật được sử dụng trong upload form là kiểm duyệt file tải lên. Nó khá phổ biến trong ứng dụng ASP.NET vì ASP>NET thường dễ kiểm soát việc kiểm duyệt hơn. Nhà phát triển được phép kiểm tra thường xuyên những file được tải lên, kiểm tra phần mở rộng của file trong danh sách phần mở rộng được phép cụ thể. Dưới đây là code từ Microsoft:
<asp:FileUpload ID="FileUpload1" runat="server" /><br /> <br /> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Upload File" /> <br /> <br /> <asp:Label ID="Label1" runat="server"></asp:Label> <asp:RegularExpressionValidator id="RegularExpressionValidator1" runat="server" ErrorMessage="Only mp3, m3u or mpeg files are allowed!" ValidationExpression="^(([a-zA-Z]:)|({2}w+)$?)((w[w].*)) +(.mp3|.MP3|.mpeg|.MPEG|.m3u|.M3U)$" ControlToValidate="FileUpload1"></asp:RegularExpressionValidator> <br /> <asp:RequiredFieldValidator id="RequiredFieldValidator1" runat="server" ErrorMessage="This is a required field!" ControlToValidate="FileUpload1"></asp:RequiredFieldValidator>
Code ASP.NET trên chỉ cho phép người dùng đầu cuối tải file .mp3, .mpeg, hoặc .m3u lên máy chủ. Nếu không đúng 3 loại đó, kiểm duyệt sẽ ném ra một ngoại lệ và file sẽ không được tải lên. Bởi vì loại kiểm duyệt này được thực hiện từ phía client nên tin tặc dễ dàng có thể vượt qua.
GIẢI PHÁP ĐỀ XUẤT
Phía trên là danh sách những vấn đề có thể gặp phải khi chức năng file upload được sử dụng trên ứng dụng web.
- Xác định một file .htaccess chỉ cho phép truy cập file với phần mở rộng được phép.
- Không đặt file .htaccess trong cùng địa chỉ với file upload.
- File .htaccess chỉ cho phép tải gif, jpg, jpeg, và png nên chứa lệnh dưới đây để đề phòng phần mở rộng kép.
deny from all<Files ~ “^w+.(gif|jpe?g|png)$”>order deny,allowallow from all</Files>
- Nếu có thể, tải file lên một địa chỉ nằm ngoài gốc của máy chủ web.
- Ngăn ngừa ghi đè những file đã tồn tại.
- Tạo một danh sách mime-type được chấp nhận.
- Tạo ra tên file ngẫu nhiên và thêm vào sau đó phần mở rộng.
- Không nên phụ thuộc vào kiểm duyệt phía client, điều đó là không an toàn. Cần kiểm duyệt cả từ phía máy chủ.
KẾT LUẬN
Có rất nhiều cách mà tin tặc có thể vượt qua bảo mật upload form. Vì lí do này, khi cài đặt một form upload trong ứng dụng web nên đảm bảo thực hiện đúng những hướng dẫn bảo mật và kiểm tra chúng. Thật không may, để thực hiện những kiểm tra cần thiết tốn rất nhiều thời gian và yêu cầu thành thạo về kỹ năng bảo mật và lập trình.
Tham khảo thêm từ Acunetix