Nhận diện và bảo vệ Laravel Path Traversal
2nd Nov 2022Thông thường tất cả các nội dụng, tài nguyên của trang web đều cần phải được phân quyền truy cập một cách đúng đắn. Mỗi hành động chỉ được phép truy cập tài nguyên trong một thư mục chỉ định. Nhưng với tấn công Path traversal có thể giúp hacker truy cập hoặc kiểm soát các thư mục nằm ngoài quyền hạn thông thường...
>> Laravel Gates xác định xem người dùng có quyền hay không
>> Tìm hiểu cơ bản về Laravel Cache
What is Path traversal?
- Path traversal ( còn có tên gọi khác là Directory traversal) là một dạng tấn công cho phép hacker truy cập được các thư mục và tệp tài nguyên nằm ngoài thư mục hiện hành. Những tài nguyên bị truy cập trái phép này có thể là source code, các thông tin cấu hình server, các tệp và thư mục hệ thống,...
- Ngoài ra lỗ hổng này thì thường được kết hợp với 1 số lỗ hổng khác để có thể khai thác sâu hơn.
Why is Path traversal attack dangerous?
- Đây là một lỗ hổng rất nguy hiểm vì nó có thể gây ảnh hưởng đến hệ thống. Ở mức độ đơn giản, hacker có thể đọc được các file trong thư mục web hay thậm chí là các file nhạy cảm trong hệ thống.
- Với 1 số cách khai thác và lỗ hổng ở mức độ chuyên sâu hơn, hacker có thể ghi được file vào hệ thống từ đó chèn thêm mã độc. Tệ nhất là có thể dẫn đến RCE
How Path traversal work?
- Một ví dụ đơn giản là việc lưu trữ ảnh trong hệ thống:
- Giả sử những file ảnh được dev lưu trong thư mục /var/www/html/blog/public/img/
- Khi truy cập file avatar.jpg trên thư mực này dev có thể để link là GET photo/file?name=avatar.jpg. Lúc này webserver sẽ truy cập vào file ở đường dẫn /var/www/html/blog/public/img/avatar.jpg và trả về cho người dùng.
- Nhưng thay vì việc truyền file name là avatar.jpg hacker có thể truyền tên file là ../../../../../../etc/password. Lúc này webserver sẽ truy cập và trả về file ở đường dẫn /var/www/html/blog/public/img/../../../../../../etc/password. Đường dẫn này tương đương với /etc/pasword nên webserver sẽ trả về file hệ thống cho chúng ta.
- Tất nhiên trong thực tế tùy theo web server và config của chúng mà cách khai thác có thể khác, khó hơn chút và đa dạng hơn chút
- Ví dụ như đối với windown server thì chúng ta có thể dùng cả ../ và ..\
Check Path traversal vulnerable
- Việc kiểm tra xem một trang web có thể bị tấn công Path traversal không có khá là nhiều cách nhưng về cơ bản thì chúng ta cần tập trung vào các endpoint truy cập file thông qua tên file, các endpoint upload file. Đây là những endpoint nhạy cảm và dễ bị dính nhất.
- Ngoài ra các endpoint này có thể sẽ không hiển thị rõ ràng trên url mà sẽ tồn tại ở đâu đó trong trang web. Có thể là trong source code html, trong các funtion call api của ajax, thậm trí trong cả cookiee.
- Ví dụ như trong thẻ html sau:
<img src="/loadImage?filename=218.png">
- Phía web server có thể có 1 bộ lọc để lọc các request này. Ta có thể thử một số cách để bypass chúng:
- Sử dụng các kí tự ....// or ....\/ thay cho ../
- Sử dụng một số mã hóa không chuẩn như: ..%c0%af or ..%252f
- Hoặc đôi khi ws yêu cầu một tên file với phần đuôi file cụ thể ta có thể sử dụng cách sau : ../../../etc/passwd%00.png. %00 chính là null byte và có thể bypass qua bộ lọc nếu bạn may mắn =))
Bạn đã từng xây dựng một website bằng Laravel và public nó ra ngoài internet với mong muốn mọi người truy cập, sử dụng nó. Nhưng hãy nhớ rằng có những thông tin mà trang web của bạn sẽ không muốn người dùng nhìn thấy nó.Đó có thể là các tệp chứa thông tin cấu hình cơ sở dữ liệu, API keys hoặc cũng có thể là private keys cho web server’s SSL certificate của bạn. Hoặc cũng có thể là các thông tin do người dùng tải lên cho mục đích sử dụng cá nhân, không có người dùng nào khác được truy cập vào các thông tin nhạy cảm này để đọc, chỉnh sửa, ghi đè hay xoá mà không được phép. Lúc này bạn cần bảo vệ nó khỏi một số nhóm người dùng độc hại ví dụ như các hacker.
Bài viết này sẽ cho bạn thấy cách tấn công vào ứng dụng web qua path url của trang web không được bảo vệ kỹ càng các tệp thông tin nhạy cảm. Chúng ta sẽ bắt đầu với các trang web xây dựng bằng Laravel và sau đó sẽ là các cách để loại bỏ nguy cơ tấn công này.
Path Traversal Attack là gì ?
Giống như các cuộc tấn công XSS (cross-site-scripting) và SQL injection, thì mục đích tấn công qua path traversal là các thông tin của người dùng website mà trước đó không được loại bỏ phát hiện và ngăn chặn từ sớm giai đoạn phát qua các dòng code của lập trình viên. Với XSS, những hacker dựa vào trang web thực mã độc của chúng dưới dạng JavaScript. Và với SQL injection, những hacker cố gắng sửa đổi các truy vấn cơ sở dữ liệu thô. Với tấn công duyệt qua Path Traversal, những kẻ tấn công muốn webserver thông tin đầu vào độc hại của chúng như một tên tệp với thông tin đường dẫn. Bằng cách này, họ có thể làm cho webserver cung cấp thông tin hoặc sửa đổi bất kỳ tệp nào miễn là PHP có thể truy cập tệp đó, ngay cả khi người dùng cuối không cho phép.
Có hai cách mà hacker có thể đưa vào thông tin đường dẫn không mong muốn. Một sử dụng một đường dẫn tuyệt đối bắt đầu từ thư mục gốc của hệ điều hành (“/”). Cách khác sử dụng đường dẫn tương đối với ký hiệu hai chấm để đi lên một thư mục trong cấu trúc phân cấp (“…/”).
Hiểu về cấu trúc thư mục của Laravel
Để hiểu được cách thực hiện tấn công Path Traversal xảy bạn cần hiểu được cấu trúc thư mục của Laravel. Khi tạo một project Laravel mới bạn sẽ thấy cấu trúc thư mục của nó.
Trong cấu hình webserver của bạn, có một thư mục gốc cho dự án Laravel của bạn. Nó không phải là thư mục chính của project mà là thư mục con được public. Do đó, webserver có thể cung cấp trực tiếp bất kỳ tệp nào trong thư mục con đó mà không liên quan đến Laravel. Các tệp trong các thư mục khác như tệp tin cấu hình nhạy cảm, … vì vậy chúng được bảo vệ khỏi truy cập trực tiếp.
Giả sử trang web của bạn là example.com, request https://example.com/file.jpg sẽ hiển thị file.jpg từ thư mục public nếu nó tồn tại. Request cho https://example.com/path/to/page sẽ chuyển đến index.php vì đường dẫn đó không tồn tại dưới dạng tệp trong thư mục public và Laravel sẽ xử lý nó theo các route bạn đã định nghĩa.
Ví dụ: bạn có chuyển ra khỏi thư mục con public bằng cách yêu cầu https://example.com/../config/app.php không? tất nhiên là không. Các webserver như Apache hoặc Nginx đã bảo vệ website của bạn khỏi việc truy cập trái phép ra khỏi thư mục gốc (thư mục public). Và tất cả các đường dẫn khác được xử lý bởi các route index.php và Laravel, không tương ứng trực tiếp với các tệp. Vậy vấn đề nằm ở đâu?
Laravel File Delivery
Đôi khi bạn muốn cho phép truy cập vào một file ngoài thư mục public cho người dùng. Một ví dụ điển hình là bạn chỉ muốn cho phép người dùng đã xác thực truy cập tệp đó. Laravel hỗ trợ kiểu truy cập này này với hàm download() trên Response object. Dưới đây là một ví dụ về route để tải xuống một file cụ thể từ thư mục storage/app:
Route::get('/download/PrivateDocument', function() { return response()->download(storage_path('app/PrivateDocument.pdf')); });
Ví dụ đoạn code trước đó là hoàn toàn an toàn vì không có tham số do người dùng truyền vào có thể gây ra lỗi. Bây giờ, hãy tưởng tượng bạn có nhiều file trong thư mục storage/app. Trong trường hợp này, bạn có thể tạo một function download được tham số hóa như sau:
Route::get('/download', function(\Illuminate\Http\Request $request) { return response()->download(storage_path('app/'.$request->get('filename'))); });
Để có thể truy cập được file như ví dụ đầu, người dùng sẽ nhập URL sau: https://example.com/download?filename=PrivateDocument.pdf
Vấn đề
Giả sử hacker cố gắng truy cập vào file trái phép. Ví dụ qua URL sau:
https://example.com/download?filename=../../.env
Chia buồn bạn đã mất hết thông tin biến môi trường nhạy cảm trong file .env.
“Vì không có kiểm tra path traversal attack. Hacker có thể tuỳ ý duyệt thư mục máy chủ website của bạn và lấy hết thông tin quan trọng. Vậy làm thế nào để ngăn chặn tấn công dạng này trong Laravel?”
Giải pháp
Nếu bạn xác định được các file cần thiết đều ở một thư mục, bạn có thể sử dụng hàm basename() tích hợp sẵn của PHP để loại bỏ bất kỳ thông tin đường dẫn nào khỏi tên file:
Route::get('/download', function(\Illuminate\Http\Request $request) { $filename = basename($request->get('filename')); return response()->download(storage_path('app/'.$filename)); });
Giải pháp trên sẽ ngăn chặn các truy cập trái phép với các thông tin nhạy cảm truyền qua đường dẫn. Nhưng nó có một hạn chế là không truy cập được các thư mục con nếu bạn muốn phân chia file theo thư mục. Ví dụ, bạn có thể có các file khác trong thư mục con và được phép truy cập. URL sau sẽ không truy cập được, ngay cả khi file đúng là lưu trữ ở đó /app/user1/document.pdf, vì nó sẽ tìm kiếm file như sau /app/document.pdf:
https://example.com/download?filename=user1/document.pdf
Chúng ta có thể giải quyết điều này bằng một hàm PHP khác có tên là realpath(). Không giống như basename(), hàm này sửa đổi một chuỗi và xóa tiền tố của nó, realpath() cũng sẽ tìm kiếm file được truy cập. Nó trả về false nếu file không tồn tại, bạn có thể sử dụng thông tin này để tạo ra thông báo lỗi thích hợp. Tuy nhiên, nếu file tồn tại, nó sẽ trả về toàn bộ đường dẫn của nó, giải quyết mọi ký hiệu không phù hợp trong trường hợp này.
Sau khi sử dụng realpath(), bạn có thể kiểm tra xem url được phép có phải là tiền tố của tên file đã nhập hay không và thực hiện hành động cần thiết nếu là truy cập trái phép. Ví dụ đoạn code sau đây minh họa điều đó. Đầu tiên, nó chỉ định thư mục được truy cập vào $basepath, sau đó đọc chỉ định tên file và xử lý nó bằng realpath(), và cuối cùng kiểm tra xem file có tồn tại hay không và nó có nằm trong $basepath hay không:
Route::get('/download', function(\Illuminate\Http\Request $request) { $basepath = storage_path('app'); $filename = realpath($basepath.'/'.$request->get('filename')); if ($filename !== false && substr($filename, 0, strlen($basepath)) == $basepath) return response()->download($filename); App::abort(404); });
Ví dụ trên sẽ trả về mã lỗi 404 cho cả file không tồn tại và tên file không hợp lệ.
Kết luận
Cách tấn công Path Traversal sẽ khiến cho bạn bị mất các thông tin nhạy cảm qua việc truy cập trái phép vào các thư mục, file không được phép. Để ngăn chặn điều này bạn cần sử dụng các kỹ thuật khác nhau như mục giải pháp đã đưa ở phần trên. Quan trọng nhất vẫn là bạn cần kiểm tra kỹ mọi thông tin đưa lên từ người dùng.
- 1 view
Add new comment