Series Opcodes Log Viewer Thực chiến #2: "Bôi đen" Dữ liệu Nhạy cảm (Data Masking) và Chặn Exfiltration
1. Vô hiệu hóa tính năng "Mang log về nhà" (Exfiltration)
Giao diện của opcodesio/log-viewer mặc định cung cấp một nút Download rất to để tải file .log về máy. Với các hệ thống lõi xử lý vé AFC, tuyệt đối không được phép cho tải file này ra khỏi Server (để đề phòng thiết bị của kỹ sư bị dính mã độc đánh cắp file).

Bước 1: Bạn mở file app/Providers/AppServiceProvider.php (hoặc AuthServiceProvider.php nếu bạn đang dùng các bản Laravel cũ hơn).
Bước 2: Khai báo các thư viện cần thiết và thiết lập quyền bên trong phương thức boot().
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Opcodes\LogViewer\Facades\LogViewer;
use Opcodes\LogViewer\LogFile;
use Opcodes\LogViewer\LogFolder;
class AppServiceProvider extends ServiceProvider
{
// ...
// Chặn tải xuống / xóa file & thư mục log (đặt ngoài closure auth)
Gate::define('downloadLogFile', fn ($user, LogFile $file) => false);
Gate::define('deleteLogFile', fn ($user, LogFile $file) => false);
Gate::define('downloadLogFolder', fn ($user, LogFolder $folder) => false);
Gate::define('deleteLogFolder', fn ($user, LogFolder $folder) => false);
}
2. Che giấu Tham số Nhạy cảm trong Exception
Khi một lỗi văng ra (Exception), Laravel mặc định sẽ ghi lại toàn bộ dấu vết (Stack Trace) cùng với những biến được gửi lên trong Request lúc đó. Nếu user đang gọi API /login, mật khẩu của họ sẽ bị in chình ình trong file laravel.log.
Để chặn việc này, hệ thống Laravel đã có sẵn cơ chế giấu đi các tham số nhạy cảm. Nếu bạn đang dùng cấu trúc mới, hãy mở file bootstrap/app.php và thêm cấu hình vào phần withExceptions:
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
// ...
->withExceptions(function (Exceptions $exceptions) {
// Khai báo những từ khóa cấm kị không bao giờ được in ra log
$exceptions->dontReport([
'password',
'password_confirmation',
'credit_card_number',
'pin_code',
'access_token',
]);
})->create();
Lưu ý: Nếu dùng Laravel 10 trở xuống, bạn khai báo mảng $dontReport này trong file app/Exceptions/Handler.php.
Khi có lỗi xảy ra ở API chứa các trường này, Log Viewer sẽ chỉ hiển thị: password: "********".
3. Kỹ thuật cao cấp: Masking bằng Monolog Processor
Cách số 2 chỉ hiệu quả với các trường hợp lỗi tự động của Laravel. Nhưng trong thực tế vận hành trạm Metro, đôi khi chúng ta chủ động ghi log bằng tay:
\Log::info("Khách hàng đang quẹt thẻ", [
'card_uid' => 'E1F4A5002B',
'phone' => '0912345678'
]);
Làm sao để hệ thống tự động dò tìm và che đi số điện thoại hoặc mã UID thẻ trước khi ghi xuống file? Đây là lúc chúng ta phải can thiệp vào tầng sâu nhất của bộ ghi log: Monolog.
Hãy tạo một Class tên là DataMaskingProcessor:
php artisan make:class Logging/DataMaskingProcessor
Mở file app/Logging/DataMaskingProcessor.php và viết logic dùng Regex (Biểu thức chính quy) để tìm và che dữ liệu:
namespace App\Logging;
use Monolog\LogRecord;
class DataMaskingProcessor
{
/**
* Hàm này sẽ tự động chạy mỗi khi có 1 dòng log chuẩn bị được ghi
*/
public function __invoke(LogRecord $record): LogRecord
{
// 1. Che giấu số điện thoại Việt Nam (Che 6 số giữa)
$message = preg_replace(
'/(0[3|5|7|8|9])+([0-9]{2})([0-9]{4})([0-9]{2})/',
'$1$2****$4',
$record->message
);
// 2. Duyệt qua mảng Context để che giấu mã thẻ (card_uid)
$context = $record->context;
if (isset($context['card_uid'])) {
$context['card_uid'] = '***' . substr($context['card_uid'], -4); // Chỉ hiện 4 số cuối
}
// Trả lại Record đã được bôi đen an toàn
return $record->with(message: $message, context: $context);
}
}
4. Đăng ký Masking Processor vào Hệ thống
Cuối cùng, chúng ta cần nói với Laravel hãy sử dụng "người gác cổng" này. Mở file config/logging.php, tìm đến channel bạn đang dùng (thường là single hoặc daily), và thêm thuộc tính tap:
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'days' => 14,
// Đưa lớp Processor của chúng ta vào chuỗi xử lý
'tap' => [App\Logging\DataMaskingProcessor::class],
],
Tổng kết Bài 2
Tuyệt vời! Bằng việc kết hợp khóa tính năng Download của Opcodes Log Viewer và xử lý triệt để dữ liệu ngay tại tầng Monolog bằng Regex, bạn đã loại bỏ hoàn toàn nguy cơ rò rỉ dữ liệu nội bộ. Kể cả khi ai đó vào được màn hình Log Viewer, những gì họ thấy chỉ là những chuỗi *** vô hại, nhưng vẫn đủ thông tin ngữ cảnh để debug lỗi phần mềm. Đây chính là tiêu chuẩn bảo mật khắt khe mà các tổ chức tài chính lớn đang áp dụng.
Ở Bài 3 (Trạm cuối), chúng ta sẽ mở rộng quy mô kiến trúc. Nếu mạng lưới trạm của bạn có 5 Server chạy song song (Load Balancing), việc mở 5 tab Log Viewer cho từng Server là không khả thi. Bạn có muốn tìm hiểu cách cấu hình Centralized Logging (Thu thập log tập trung) kết hợp với Opcodes Log Viewer để xem toàn bộ lỗi của hệ thống trên một màn hình duy nhất không?
All rights reserved