15 điểm bởi GN⁺ 2025-11-22 | 3 bình luận | Chia sẻ qua WhatsApp
  • Dependency cooldown là một biện pháp bảo mật đơn giản nhưng hiệu quả có thể giảm thiểu phần lớn các cuộc tấn công chuỗi cung ứng mã nguồn mở
  • Kẻ tấn công thường chiếm quyền các dự án mã nguồn mở phổ biến để phát tán mã độc, nhưng phần lớn các cuộc tấn công có thời gian lộ diện dưới một tuần
  • Nếu thiết lập cooldown để chờ một khoảng thời gian nhất định sau khi phát hành phiên bản mới (ví dụ: 7 ngày), có thể giảm mạnh rủi ro nhiễm mã độc do cập nhật tự động
  • Dependabot, Renovate, pnpm v.v. đã hỗ trợ sẵn tính năng cooldown và việc cấu hình rất dễ, không phát sinh chi phí
  • Nếu cooldown được cung cấp mặc định ở cấp trình quản lý gói, nó có thể giúp tăng cường bảo mật chuỗi cung ứng và giảm các cảnh báo không cần thiết

Cấu trúc và vấn đề của các cuộc tấn công chuỗi cung ứng

  • Phần lớn tấn công chuỗi cung ứng (supply chain attack) có cùng một mẫu hình
    • Kẻ tấn công lợi dụng đánh cắp thông tin xác thực của dự án mã nguồn mở phổ biến hoặc lỗ hổng CI/CD để truy cập
    • Tải các thay đổi độc hại lên kênh phân phối như PyPI, npm v.v.
    • Người dùng cài phải phiên bản bị nhiễm do cập nhật tự động hoặc không ghim phiên bản đầy đủ
    • Nhà cung cấp bảo mật phát hiện, đưa ra cảnh báo, sau đó kho gói xóa phiên bản đó
  • Khoảng cách giữa bước (1)~(2) có thể dài, nhưng từ (2)~(5) thường được xử lý trong vài giờ đến vài ngày, nên thời gian hoạt động của kẻ tấn công khá ngắn
  • Khoảng thời gian có thể bị khai thác (window of opportunity) của các trường hợp lớn trong 18 tháng gần đây
    • xz-utils: khoảng 5 tuần
    • Ultralytics: 12 giờ (giai đoạn 1), 1 giờ (giai đoạn 2)
    • tj-actions: 3 ngày
    • chalk: dưới 12 giờ
    • Nx: 4 giờ
    • rspack: 1 giờ
    • num2words: dưới 12 giờ
    • Kong Ingress Controller: khoảng 10 ngày
    • web3.js: 5 giờ
  • Trong số này, 8 vụ có thời gian tấn công dưới 1 tuần, và phần lớn có thể bị chặn bằng cooldown

Khái niệm và hiệu quả của cooldown

  • Cooldown là cách trì hoãn việc sử dụng dependency mới trong một khoảng thời gian nhất định sau khi nó được phát hành
    • Trong khoảng thời gian này, các nhà cung cấp bảo mật có thể phát hiện xem nó có độc hại hay không
  • Ưu điểm
    • Hiệu quả đã được chứng minh thực tế, có thể chặn phần lớn các cuộc tấn công quy mô lớn
    • Triển khai rất đơn giản và có thể cấu hình miễn phí trên hầu hết các công cụ
    • Ví dụ Dependabot
      version: 2
      - package-ecosystem: github-actions
        directory: /
        schedule:
          interval: weekly
        cooldown:
          default-days: 7
      
    • Thúc đẩy hành vi tích cực từ các nhà cung cấp bảo mật: tập trung vào phát hiện nhanh thay vì cảnh báo quá mức hoặc quảng bá

Kết luận và đề xuất

  • 8 trên 10 cuộc tấn công có thời gian dưới 1 tuần, và cooldown 7 ngày có thể chặn phần lớn
  • Nếu áp dụng cooldown 14 ngày, có thể phòng thủ trước mọi trường hợp ngoại trừ xz-utils
  • Cooldown không phải lời giải hoàn hảo, nhưng là cách đơn giản để giảm 80~90% rủi ro phơi nhiễm
  • Ngoài Dependabot và Renovate, cũng cần cải thiện để chính các trình quản lý gói hỗ trợ cooldown mặc định
  • Bảo mật chuỗi cung ứng không chỉ là vấn đề kỹ thuật mà còn là vấn đề của cấu trúc niềm tin xã hội, nhưng cooldown vẫn là một biện pháp giảm thiểu thực tế hữu ích

3 bình luận

 
regentag 2025-11-23

Thực ra nếu không có vấn đề gì thì có lẽ tốt hơn là không cần cập nhật.
Liệu có nhất thiết phải áp dụng một phiên bản mới không khác mấy so với phiên bản trước, trong khi vẫn phải chấp nhận rủi ro hay không.

 
GN⁺ 2025-11-22
Ý kiến trên Hacker News
  • Mọi người lo rằng nếu không cập nhật ngay thì sẽ phơi bày trước lỗ hổng nghiêm trọng, nhưng thực tế đa phần không phải vậy
    Nhiều phần mềm không triển khai liên tục mà theo cách khách hàng tự cài phiên bản mới, nên thường cập nhật theo chu kỳ vài tuần hoặc vài tháng
    Điều quan trọng là giám sát dependency và kiểm tra các lỗ hổng đã được công bố. Hãy đánh giá xem sản phẩm có thực sự bị ảnh hưởng hay không, rồi chỉ khi đó mới cập nhật ngay dependency đó

    • Toàn bộ hệ sinh thái đang thiếu văn hóa cập nhật có chọn lọc như vậy
      Có nhận thức lan rộng rằng cứ có phiên bản mới là phải cập nhật ngay trong ngày
      Cách tiếp cận kiểu “để sau sẽ còn vất vả hơn nên làm luôn bây giờ” mà không xem xét thay đổi thực tế là kém hiệu quả
      Việc luôn bám sát đầu sóng ngọn gió của số phiên bản đôi khi còn phản tác dụng về mặt bảo mật
    • Vấn đề thực tế là nhiều đội bảo mật ở các tập đoàn lớn ép buộc chính sách “zero CVE”
      Ở công ty chúng tôi, nếu scanner phát hiện lỗ hổng nghiêm trọng thì phải cập nhật trong vòng 7 ngày
      Nếu quá hạn sẽ bị coi là vi phạm quy định và kéo theo quy trình phức tạp, nên phần lớn mọi người cứ cập nhật ngay tất cả mọi thứ
    • Mọi người sợ 0-day, nhưng phần lớn sự cố thực tế lại đến từ những lỗ hổng không được vá suốt hàng trăm ngày
    • Điểm cốt lõi là ứng dụng có nhận đầu vào chưa biết từ bên ngoài hay không
      Ứng dụng như trình duyệt, nơi có rất nhiều đầu vào bên ngoài, thì cần cập nhật thường xuyên; còn trường hợp như ứng dụng thời tiết với đầu vào hạn chế thì tương đối an toàn hơn
    • Chiến lược “chỉ cập nhật khi cần” nghe có vẻ hay trên lý thuyết, nhưng thực tế chi phí đánh giá từng lỗ hổng theo ngữ cảnh sản phẩm là quá lớn
      Thà cập nhật định kỳ và đồng thời áp dụng biện pháp phòng vệ trước tấn công chuỗi cung ứng còn hiệu quả hơn
  • Mô hình để bản phân phối quản lý dependency dùng chung và nâng cấp toàn bộ vài năm một lần, như mô hình Debian stable, ngày càng có vẻ hợp lý hơn
    Một số hệ sinh thái di chuyển quá nhanh hoặc có hệ thống đóng gói theo từng bản phân phối còn yếu
    Ví dụ, việc cài thư viện Node.js bằng apt rồi dùng trong dự án vẫn còn khó khăn

    • Không nên nhầm “chuyển động” với “hành động”
      Một hệ sinh thái di chuyển nhanh mà không có thay đổi nền tảng thì không khỏe mạnh
      JS gần như không có tiến bộ thực chất nào trong 3 năm qua, vậy mà để build lại một dự án 3 năm tuổi thì phải chịu nỗi đau gần như viết lại từ đầu
    • Nhìn vào kết quả tìm kiếm gói node trên Debian thì có một số gói nhưng không đầy đủ
      Những bản phân phối như Arch thậm chí có khi không có luôn
    • Với Rust thì chỉ dùng kho Debian thôi cũng đủ để làm việc
    • Mô hình bản ổn định cũng có gánh nặng là ứng dụng phải hỗ trợ đồng thời cả phiên bản cũ lẫn mới
  • Có giả định rằng để ngăn chặn tấn công chuỗi cung ứng, nên đặt thời gian cooldown cho việc cập nhật dependency thay vì lập tức dùng bản mới nhất để chặn 0-day
    Đây là sự so sánh giữa xác suất bản cập nhật đưa vào lỗ hổng mới và xác suất nó sửa được lỗ hổng hiện có
    Theo SemVer, bản vá patch tương đối an toàn nên cũng có thể áp dụng cách tiếp cận cooldown ngắn hơn cho loại này
    Ví dụ, khi đang ở 2.3.4 mà 2.4.0 được phát hành, nếu không có tính năng gấp thì nên đợi tới 2.4.1 rồi hãy nâng cấp

    • Với 0-day đã được công khai thì sẽ có security advisory, nên các công cụ như Dependabot sẽ bỏ qua cooldown và vá ngay
      Phần lớn lỗ hổng không đến từ tấn công có chủ đích mà từ bug thông thường
    • Mặc định nào cũng luôn dựa trên giả định. Khi có thông tin mới thì có thể thay đổi
  • Chính sách giới hạn số lượng và độ phức tạp của dependency là cách tiếp cận mạnh hơn
    Thay vì thêm các thư viện “làm mọi thứ”, chỉ nên thêm những dependency nhỏ và có mục đích rõ ràng
    Ngoài ra, nếu các thư viện cũng cung cấp phiên bản LTS chỉ bao gồm bản vá bảo mật thì việc quản lý sẽ dễ hơn

    • Lập luận này xuất hiện thường xuyên, nhưng trên thực tế tái sử dụng mã đã được kiểm chứng hiệu quả hơn nhiều
      Tự triển khai lại có thể là lãng phí. Tôi tò mò ví dụ cụ thể nào về “everything library” là có vấn đề
    • Phần lớn tấn công chuỗi cung ứng xảy ra ở bề mặt tấn công mang tính social engineering
      Nếu bạn tin cùng một lập trình viên qua nhiều thư viện, thì quan hệ tin cậy quan trọng hơn số lượng package
      Độ phức tạp có tương quan với lỗ hổng, nhưng không phải nguyên nhân trực tiếp
    • Sự xuất hiện của công cụ AI làm giảm chi phí tự triển khai các dependency không cốt lõi
      Giờ đây có thể đưa ra lựa chọn cân nhắc bảo trì dài hạn thay vì chỉ ưu tiên tốc độ ngắn hạn
    • Dependency bị chia quá vụn có thể ngược lại làm tăng số lượng và gánh nặng build
    • Việc thư viện cấp thấp lại có thêm dependency khác là điều khó biện minh
      Trong thế giới C++, đây thậm chí còn là một điểm cạnh tranh
  • Áp lực phải luôn cập nhật lên bản mới nhất mỗi lần xuất phát từ niềm tin sai lầm rằng phần mềm lúc nào cũng tốt hơn
    Thực tế có thể chỉ là đổi những bug đã biết lấy những bug mới chưa biết
    Theo dõi các issue đã công khai và chỉ vá khi cần là hợp lý hơn

    • Ví dụ với log4shell, log4j 1.x không dễ bị tấn công, còn bug lại được đưa vào ở 2.x
      Tức là có trường hợp phiên bản cũ hơn lại an toàn hơn
    • Trước đây khoảng cách giữa các lần phát hành dài hơn nên cải thiện chất lượng thấy rõ hơn, còn ngày nay phần lớn chỉ là thay đổi ở phần rìa
      Có lẽ cũng vì chúng ta đang dùng phần mềm vốn đã đủ ổn định rồi
  • Nếu ai cũng nói “đợi thêm một chút”, cuối cùng sẽ thành bi kịch tài nguyên chung và không ai xác minh trước cả
    Chờ càng lâu thì nợ kỹ thuật càng tích tụ, nên cần cập nhật dần dần và các biện pháp giảm thiểu như zero trust và monitoring

    • Chờ khoảng một tuần sau khi bản mới phát hành không phải là nợ kỹ thuật lớn
      Trong khoảng thời gian đó các security scanner đã phát hiện lỗ hổng rồi
    • Các vụ tấn công chuỗi cung ứng gần đây được phát hiện không phải nhờ mức độ phơi bày với người dùng mà nhờ có thời gian để maintainer phản ứng
    • Dù số người dùng sớm có ít đi, điều đó vẫn tạo thời gian cho nhà nghiên cứu và maintainer phân tích
      Nếu kẻ tấn công đẩy lên một bản phát hành trái phép thì đôi khi sẽ bị phát hiện ngay
    • Các hệ thống quy mô lớn vốn dĩ cũng triển khai gradual rollout, nên không thể cập nhật toàn bộ ngay lập tức
  • Ý tưởng cooldown hay, nhưng có rủi ro kẻ tấn công lợi dụng nó để tạo ra cảm giác khẩn cấp giả
    Chúng có thể gắn nhãn “bản vá bảo mật khẩn cấp” để dụ cài sớm, trong khi phiên bản đó thực ra là độc hại
    Cần đề phòng kiểu tấn công gây áp lực tâm lý này

    • Khi phát tán exploit, nếu kẻ tấn công kèm cả sửa lỗi vào thì có thể khiến lập trình viên phá cooldown và cài đặt ngay
    • Có câu hỏi đặt ra là “làm sao để tạo ra thứ tiếng ồn như vậy?” — tức là thắc mắc về cách kẻ tấn công thao túng dư luận
  • Một lý do khác cho cooldown là để maintainer có thời gian tự nhận ra việc bị xâm phạm
    Kẻ tấn công nhắm vào lúc maintainer vắng mặt như kỳ nghỉ, hội nghị, ngày lễ...
    Nhiều dự án chỉ do một hoặc hai người quản lý, nên khoảng chênh thời gian như vậy cực kỳ quan trọng

  • Điều này phụ thuộc vào đặc tính dự án và bề mặt tấn công
    Đã đến lúc phải chấm dứt thời đại chỉ đơn giản làm theo “best practice”
    Bảo mật giống như môn thể thao va chạm trực diện, nơi bạn phải suy nghĩ phản biện về chi tiết mỗi ngày

  • Cooldown cũng có giới hạn nếu chỉ đơn giản cho rằng cứ qua thời gian là sẽ an toàn hơn
    Nếu không ai xem mã thì sau một tuần rủi ro vẫn y nguyên
    Thay vào đó, cách triển khai dần dần (gradual rollout) có thể hiệu quả hơn
    Mỗi bên sử dụng có thể đặt một delay factor, để phía chấp nhận rủi ro cao gặp vấn đề trước,
    trong khi những bên còn lại được bảo vệ trong thời gian đó
    Các bản cập nhật nguy hiểm sẽ bị loại khỏi hàng đợi, nên những bên trì hoãn sẽ không nhìn thấy chúng nữa

 
aer0700 2025-11-23

Gần đây đôi khi tôi thấy khó phân biệt xem việc tự làm lại bánh xe hay việc quản lý trò Tetris phụ thuộc thì cái nào còn dễ gánh hơn.
Nếu có gì sai trong một thời gian thì chỉ cần sửa code của mình là được, nhưng trong trò Tetris phụ thuộc, khi không biết bánh xe nào bỗng nhiên lệch đi thì việc debug cũng rất khó.