Bỏ qua để đến nội dung

Bảo mật và vận hành cho gói NextPDF Laravel

Gói này đặt các header phản hồi Portable Document Format (PDF) cố định, làm sạch tên tệp tải xuống, xác thực đường dẫn đầu ra của hàng đợi trên worker và định tuyến các lệnh gọi Hypertext Transfer Protocol (HTTP) đến timestamp authority qua một client có khả năng nhận biết tấn công giả mạo yêu cầu. Trang này giải thích mô hình mối đe dọa và cấu hình triển khai cần có cho từng biện pháp kiểm soát.

Terminal window
composer require nextpdf/laravel
php artisan vendor:publish --tag=nextpdf-config

Gói này điều chỉnh một engine PDF cho một web framework. Yêu cầu HTTP và transport hàng đợi xác định ranh giới tin cậy. Các biện pháp kiểm soát này bao phủ việc xử lý phản hồi, payload công việc được giải tuần tự hóa và HTTP gửi đi tới một timestamp authority.

Tài sảnMối đe dọaBiện pháp kiểm soát trong gói nàyCấu hình triển khai bắt buộc
Phản hồi HTTP PDFDò tìm content-type, clickjacking, lập chỉ mụcBộ header cố định trên mọi PdfResponse factoryKhông có; các header không thể cấu hình
Tên tệp tải xuốngTiêm header, vượt thư mục trong Content-DispositionBộ làm sạch tên tệp loại bỏ ký tự phân tách, ký tự điều khiển và byte nullKhông có; bộ làm sạch luôn chạy
Đường dẫn đầu ra của công việc hàng đợiGhi tệp tùy ý qua payload tuần tự hóa bị giả mạoĐường dẫn được xác thực trong handle() trên workerĐịnh tuyến đầu ra đến một đường dẫn lưu trữ được kiểm soát
HTTP gửi đi tới timestamp authority (TSA)Giả mạo yêu cầu phía máy chủ, giả mạo văn bản thuầnClient HTTP có khả năng nhận biết tấn công giả mạo yêu cầu; HTTPS được bắt buộc trừ khi nới lỏng một cách rõ ràngGiữ tsa.allow_insecure_http = false; ghim Subject Public Key Info (SPKI)
Trạng thái worker dùng chungRò rỉ trạng thái giữa các yêu cầu trong các worker chạy lâu dàiFont registry bị khóa; bộ nhớ đệm hình ảnh có giới hạn; tài liệu gắn với factoryĐặt preload_fonts; giới hạn bộ nhớ ở tầng container

Mọi factory PdfResponse đều đặt một bộ header cố định:

  • Cache-Control: private, max-age=0, must-revalidate
  • Pragma: public
  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • Content-Security-Policy: default-src 'none'
  • X-Robots-Tag: noindex, nofollow
  • Referrer-Policy: no-referrer

Các giá trị này là hằng số trong PdfResponse và không thể cấu hình. Bộ kiểm thử của gói kiểm tra từng header trên mọi phương thức factory, bao gồm cả các biến thể luồng.

Tên tệp tải xuống đi qua một bộ làm sạch trước khi được đưa vào header Content-Disposition. Bộ làm sạch loại bỏ các ký tự phân tách đường dẫn, ký tự điều khiển và byte null, đồng thời phát ra tham số filename*= theo Request for Comments (RFC) 5987 cho các tên không phải ASCII. Tên tệp rỗng sẽ trở thành document.pdf.

GeneratePdfJob tuần tự hóa một closure lên transport hàng đợi. Worker xác thực đường dẫn đầu ra bên trong handle(), không phải tại thời điểm dispatch. Bước xác thực từ chối:

  • byte null trong đường dẫn,
  • các scheme stream-wrapper (ví dụ php://),
  • .. các đoạn vượt thư mục (path-traversal),
  • bất kỳ đường dẫn nào không kết thúc bằng .pdf (không phân biệt chữ hoa chữ thường).

Mỗi lần từ chối sẽ phát sinh InvalidArgumentException. Việc xác thực chạy khi worker tiêu thụ công việc. Payload tuần tự hóa trên transport Redis hoặc cơ sở dữ liệu có thể bị thay đổi trước khi worker đọc nó. Hãy định tuyến đường dẫn đầu ra đến một thư mục lưu trữ được kiểm soát; không suy ra đường dẫn này từ dữ liệu đầu vào yêu cầu chưa được xác thực.

Khi một timestamp authority được cấu hình, gói sẽ gắn một Psr\Http\Client\ClientInterface theo PHP Standard Recommendation (PSR)-18. Client PSR-18 gửi một yêu cầu PSR-7 và trả về một phản hồi PSR-7 (PSR-18 §2). Client được gắn bao bọc một client dựa trên curl bằng một lớp có khả năng nhận biết tấn công giả mạo yêu cầu. Lớp này bắt buộc HTTPS, trừ khi tsa.allow_insecure_http được đặt rõ ràng là true.

Timestamp authority là một tính năng thuộc bậc Premium. Gói Core được trình bày ở đây gắn kết HTTP client và wiring của timestamp client; bản thân việc ký yêu cầu nextpdf/premium. Trang này không trình bày hành vi baseline PDF Advanced Electronic Signatures (PAdES) vượt quá B-B; các baseline cao hơn nằm ngoài phạm vi.

Hướng dẫn vận hành cho timestamp authority:

  1. Giữ tsa.allow_insecure_http được đặt là false trong môi trường sản xuất.
  2. Đặt tsa.pinned_public_keys thành các hash SPKI SHA-256 dạng base64 của chứng chỉ timestamp authority (dạng RFC 7469).
  3. Giữ tsa.warn_on_key_rotation được đặt là true để SPKI thay đổi được ghi log trước khi chứng chỉ đã ghim hết hạn.
  4. Chỉ lấy tsa.url từ cấu hình đáng tin cậy. Nếu người vận hành có thể đặt giá trị này từ giao diện quản trị, hãy áp dụng tường lửa egress hoặc chính sách DNS để giảm mức độ phơi nhiễm với tấn công giả mạo yêu cầu.

Sử dụng Psr\Log\LoggerInterface để chẩn đoán. Truyền ngữ cảnh có cấu trúc, không truyền các chuỗi đã nội suy. PSR-3 để phần triển khai logger xử lý việc escape placeholder và hướng dẫn bên gọi không escape trước các giá trị ngữ cảnh (PSR-3 §1.2). Hãy ghi log lớp exception, không ghi thông báo hay trace, để giảm chi tiết nội bộ trong log.

resource: config/nextpdf.php (tsa hardening) + src/Laravel/NextPdfServiceProvider.php
<?php
declare(strict_types=1);
// .env — production timestamp-authority hardening
// NEXTPDF_TSA_URL=https://tsa.example.test
// NEXTPDF_TSA_ALLOW_INSECURE_HTTP=false
// NEXTPDF_TSA_WARN_ROTATION=true
return [
'tsa' => [
'url' => env('NEXTPDF_TSA_URL'),
'allow_insecure_http' => env('NEXTPDF_TSA_ALLOW_INSECURE_HTTP', false),
'warn_on_key_rotation' => env('NEXTPDF_TSA_WARN_ROTATION', true),
'pinned_public_keys' => [
// base64 SHA-256 SPKI hashes of the TSA certificate
],
],
];
  • Bộ header phản hồi là cố định. Các ứng dụng cần một Content Security Policy (CSP) khác phải xử lý hậu kỳ phản hồi sau khi factory trả về.
  • Việc xác thực đường dẫn chạy trên worker. Một đường dẫn không hợp lệ vẫn vượt qua dispatch() và chỉ thất bại khi công việc thực thi.
  • tsa.allow_insecure_http = true loại bỏ việc bắt buộc HTTPS và làm suy yếu độ tin cậy của timestamp. Chỉ giới hạn nó cho phát triển cục bộ.
  • Font registry bị khóa sau khi khởi động làm nóng; gói được thiết kế để từ chối các nỗ lực đăng ký phông chữ tại thời điểm chạy trong một worker chạy lâu dài.

Các biện pháp kiểm soát bảo mật sử dụng thao tác chuỗi và mảng với thời gian hằng định và không thêm chi phí đo lường được trên mỗi yêu cầu. Việc phân tích phông chữ ở lần sử dụng đầu tiên là chi phí vận hành chủ đạo; hãy nạp trước phông chữ khi worker khởi động để tránh độ trễ của yêu cầu đầu tiên.

Trang này là tài liệu tham chiếu mô hình mối đe dọa cho gói. Mã nguồn thực thi các biện pháp kiểm soát này, còn bộ kiểm thử xác nhận chúng. Bảng mô hình mối đe dọa và các bước timestamp authority nêu rõ cấu hình triển khai mà người vận hành phải cung cấp.

Tuyên bốNguồnĐiều khoảnreference_id
Client PSR-18 gửi yêu cầu PSR-7, trả về phản hồi PSR-7PSR-18 HTTP Client§2
Bên gọi truyền ngữ cảnh log có cấu trúc chưa được escapePSR-3 Logger§1.2

Việc ghim SPKI theo RFC 7469 đặt tên cho định dạng được khóa cấu hình tsa.pinned_public_keys sử dụng. Gói tiêu thụ các giá trị pin do người vận hành cung cấp và bản thân không triển khai RFC.

Việc ký PAdES B-B và tích hợp timestamp authority yêu cầu nextpdf/premium. Tính năng Enterprise tùy chọn này không yêu cầu thay đổi code nào trong gói Core được trình bày ở đây. Xem https://nextpdf.dev/get-license/?intent=laravel-signing.

  • /integrations/laravel/configuration/ — tất cả khóa TSA, chữ ký và hàng đợi
  • /integrations/laravel/production-usage/ — các mẫu dependency injection (DI) và xử lý lỗi
  • /integrations/laravel/troubleshooting/ — lý do các kiểm tra đường dẫn từ chối dữ liệu đầu vào
  • /integrations/laravel/boot-and-discovery/ — vòng đời binding trong các worker chạy lâu dài