0
0
Lập trình
Admin Team
Admin Teamtechmely

Cách Ngăn Chặn Tấn Công Chuỗi Cung Ứng với GitHub Actions

Đăng vào 2 tháng trước

• 11 phút đọc

Cách Ngăn Chặn Tấn Công Chuỗi Cung Ứng với GitHub Actions


Trong một lần làm việc với dự án API REST Node.js của mình, tôi đã gặp phải một tình huống bất ngờ khi kiểm tra tệp package-lock.json từ một PR (pull request) của một contributor ngẫu nhiên. Một contributor khác đã phê duyệt PR này ngay sau đó. Điều này đã dẫn tôi vào một cuộc tấn công chuỗi cung ứng đang diễn ra nhắm vào các nhà phát triển như chúng tôi.

Hãy cùng đào sâu vào câu chuyện này để hiểu rõ hơn về cách mà phát triển phần mềm hiện đại có thể nhanh chóng trở nên nguy hiểm, và lý do tại sao một PR "hữu ích" có thể không hữu ích chút nào.

Tấn Công Chuỗi Cung Ứng Là Gì?

Tấn công chuỗi cung ứng xảy ra khi các hacker đưa mã độc hoặc các công cụ đánh cắp thông tin vào trong các phụ thuộc, kịch bản xây dựng hoặc pipelines CI/CD. Họ thường tấn công vào bất kỳ liên kết nào mà mã nguồn, bí mật và môi trường có thể tiếp xúc với nhau. Hãy nghĩ đến việc: "Nếu tôi có thể làm hỏng upstream, tại sao phải tấn công hàng ngàn repos một cách riêng lẻ?"

Điều này rất tinh vi bởi vì những công cụ này là những gì chúng ta tin tưởng một cách tuyệt đối. Khi lodash phát hành bản cập nhật, chúng ta thường không kiểm tra từng dòng mã, đúng không? Chúng ta chỉ cần npm update và tiếp tục với cuộc sống.

Bằng Chứng Hết Sức Rõ Ràng: Tệp Lock Đã Bị Can Thiệp

Mọi chuyện bắt đầu khi tôi xem xét tệp package-lock.json từ pull request. Tôi nhận thấy một điều gì đó làm tôi cảm thấy không ổn - cùng với các tin tức về hack NPM gần đây vào tháng 9 năm 2025:

json Copy
// TRƯỚC (Bình thường, an toàn)
"@types/body-parser": {
  "version": "1.17.0",
  "requires": {
    "@types/connect": "3.4.32",
    "@types/node": "10.12.18"
  }
}

// SAU (Đáng ngờ)
"@types/body-parser": {
  "version": "1.17.0",
  "dependencies": {
    "@types/connect": "*",
    "@types/node": "*"
  }
}

Những ký tự hoa thị nhỏ? Chúng là wildcards cho biết npm "hãy cho tôi bất kỳ phiên bản nào mà bạn cảm thấy thích hợp." Nó giống như đặt món ăn và nói với người phục vụ "bất ngờ tôi đi" - ngoại trừ bất ngờ có thể là mã độc.

Thay đổi này hoàn toàn bỏ qua việc khóa phiên bản, một trong những hàng rào chính của chúng ta chống lại các tấn công chuỗi cung ứng. Với wildcards, nếu bất kỳ gói nào bị xâm phạm sau này, bạn sẽ tự động kéo phiên bản độc hại trong lần cài đặt tiếp theo.

Đóng Góp "Hữu Ích"

Tôi tìm thấy bằng chứng quan trọng: một pull request từ ngày 5 tháng 9 năm 2025, được gửi bởi một người dùng có tên harshitcodez19. PR này trông có vẻ vô hại - chỉ thêm một số CI/CD với GitHub Actions. Thật chu đáo!

yaml Copy
name: Build on PR
# Heello đây là một tệp ymk được tạo ra cho cICD
on:
  push:
    branches:
      - main # ← Chờ đã, repo của tôi sử dụng 'master'
  pull_request:
    branches:
      - main # ← Điều này cũng sai...

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Sử dụng Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'

      - name: Cài đặt phụ thuộc
        run: npm install # ← Nên là 'npm ci' để đảm bảo an toàn

      - name: Chạy Build
        run: npm run build

Nhìn thoáng qua, điều này dường như là một người mới đang cố gắng giúp đỡ. Các lỗi chính tả trong bình luận ("Heello", "ymk", "cICD") khiến nó có vẻ như là người đang học hỏi. Cấu hình nhánh cũng sai, vì vậy nó thậm chí sẽ không chạy.

Nhưng điều này - chính xác là cách mà chiến dịch GhostAction hoạt động.

Chiến Dịch GhostAction: Khi GitHub Actions Trở Nên Ác Độc

Thời gian của PR này không phải là tình cờ. Ngày 5 tháng 9 năm 2025 là khi các nhà nghiên cứu bảo mật lần đầu tiên phát hiện ra chiến dịch GhostAction - một cuộc tấn công chuỗi cung ứng tinh vi nhắm vào các kho GitHub.

Dưới đây là cách mà GhostAction hoạt động:

  1. Do Thám: Kẻ tấn công xác định các kho có phụ thuộc lỗi thời
  2. Kỹ Thuật Xã Hội: Gửi PR "hữu ích" thêm vào các quy trình CI/CD
  3. Phá Hoại Có Chủ Đích: Bao gồm những sai lầm rõ ràng để tránh thực thi ngay lập tức
  4. Kiên Nhẫn: Chờ đợi các nhà duy trì "sửa" các vấn đề rõ ràng
  5. Khai Thác: Khi quy trình hoạt động, nó thu thập bí mật và thông tin xác thực

Điều thông minh là sự phủ nhận hợp lý. PR trông như một contributor vô hại nhưng thiếu kinh nghiệm. Những "sai lầm" khiến nó có vẻ vô hại. Nhưng một khi những quy trình này chạy với quyền truy cập đúng, thì hết game.

Phân Tích Vector Tấn Công

Hãy phân tích điều gì sẽ xảy ra nếu tôi đã hợp nhất PR này:

yaml Copy
# Cấu hình nhánh sai ngăn chặn thực thi ngay lập tức
on:
  push:
    branches:
      - main # Repo của tôi sử dụng 'master', vì vậy điều này sẽ không kích hoạt

Điều này cho phép kẻ tấn công có thời gian. Nếu tôi đã "sửa" vấn đề nhánh rõ ràng và hợp nhất nó, quy trình sẽ:

yaml Copy
- name: Cài đặt Phụ Thuộc
  run: npm install # Kéo các phụ thuộc wildcard

Với những wildcards trong tệp lock của tôi, npm install sẽ lấy các phiên bản mới nhất của @types/node@types/connect. Nếu những gói đó đã bị xâm phạm (điều mà cuộc tấn công npm lớn đã thực hiện), môi trường CI của tôi sẽ cài đặt mã độc với quyền truy cập đầy đủ tới:

  • Bí mật GitHub
  • Thông tin xác thực AWS
  • Chuỗi kết nối cơ sở dữ liệu
  • Khóa API
  • Mã thông báo triển khai

Về cơ bản, mọi thứ bạn cần để hoàn toàn sở hữu cơ sở hạ tầng của tôi.

Bối Cảnh Rộng Hơn: Cuộc Tấn Công NPM Lớn Năm 2025

Cuộc tấn công này là một phần của một chiến dịch lớn hơn theo nghiên cứu của OX Security.

Các kẻ tấn công đã:

  • Xâm phạm tài khoản của các nhà duy trì gói hợp pháp
  • Tiêm mã độc vào các gói đáng tin cậy
  • Cụ thể nhắm vào môi trường CI/CD
  • Sử dụng GitHub Actions để lấy thông tin xác thực

Tệp lock cũ của tôi, với các gói từ 2018-2019, là mục tiêu hoàn hảo. Các phụ thuộc lỗi thời giống như những ổ khóa cũ - chúng hoạt động cho đến khi một người có công cụ phù hợp xuất hiện.

Những Dấu Hiệu Đỏ Tôi Nên Nhận Ra Sớm Hơn

Nhìn lại, có một vài dấu hiệu cảnh báo:

1. Hồ Sơ Contributor

  • harshitcodez19 có lịch sử đóng góp tối thiểu
  • Mẫu tên ngẫu nhiên điển hình của các tài khoản tạm
  • Không có mối quan hệ thiết lập với dự án của tôi

2. Những "Sai Lầm" Quá Tiện Lợi

  • Tên nhánh sai ngăn chặn thực thi ngay lập tức
  • Các lỗi chính tả tạo ra sự phủ nhận hợp lý
  • Sử dụng npm install thay vì npm ci an toàn hơn

3. Thời Gian

  • Được gửi vào ngày 5 tháng 9 năm 2025 (ngày phát hiện chính xác của GhostAction)
  • Các wildcards trong tệp lock của tôi xuất hiện xung quanh cùng thời điểm đó
  • Trùng hợp với các vụ xâm phạm chuỗi cung ứng npm lớn hơn

Điều Gì Có Thể Đã Xảy Ra Nếu Cuộc Tấn Công Thành Công

Nếu cuộc tấn công này thành công, đây là những gì kẻ tấn công có thể làm:

bash Copy
# Trong môi trường CI của tôi đã bị xâm phạm:
echo $AWS_SECRET_ACCESS_KEY  # Lấy thông tin xác thực đám mây
echo $DATABASE_URL          # Đánh cắp quyền truy cập cơ sở dữ liệu
echo $DEPLOY_TOKEN          # Xâm phạm pipeline triển khai

# Sau đó chuyển sang:
# - Triển khai backdoor lên production
# - Truy cập dữ liệu khách hàng
# - Khai thác tiền ảo trên cơ sở hạ tầng của tôi
# - Di chuyển sang các hệ thống khác

Bán kính thiệt hại từ một cuộc tấn công CI thành công là rất lớn vì các môi trường CI thường có quyền truy cập cao để triển khai, kiểm tra và tích hợp với các dịch vụ khác.

Thực Hành Tốt Nhất: Cách Để Không Bị Tấn Công

Dưới đây là những gì tôi đã học được và những gì bạn nên làm để bảo vệ bản thân:

1. Vệ Sinh Tệp Lock

bash Copy
# Luôn sử dụng npm ci trong môi trường sản xuất/CI
npm ci  # Sử dụng các phiên bản chính xác trong lockfile

# Không bao giờ sử dụng npm install trong CI
npm install  # Có thể cập nhật các phiên bản một cách bất ngờ
json Copy
// Giữ tệp lock của bạn ở trạng thái khóa
"dependencies": {
  "@types/node": "10.12.18",  // ✅ Phiên bản chính xác
  "@types/connect": "*"       // ❌ Wildcard = nguy hiểm
}

2. Bảo Mật CI/CD

yaml Copy
# Quy trình làm việc GitHub Actions an toàn
name: Bảo mật Xây dựng
on:
  pull_request:
    branches: [master] # Tên nhánh chính xác

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4 # Phiên bản mới nhất

      - name: Thiết lập Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm' # Lưu trữ cho hiệu suất

      # Sử dụng npm ci cho việc xây dựng tái tạo
      - name: Cài đặt phụ thuộc
        run: npm ci

      # Kiểm tra bảo mật trước khi xây dựng
      - name: Kiểm tra bảo mật
        run: npm audit --audit-level=critical

      - name: Xây dựng
        run: npm run build

3. Quản Lý Phụ Thuộc

bash Copy
# Bảo trì định kỳ
npm outdated        # Kiểm tra cập nhật
npm audit          # Lỗ hổng bảo mật
npm audit fix      # Tự động sửa lỗi khi có thể

# Giữ các phụ thuộc hiện tại
npm update         # Cập nhật trong các khoảng semver

4. Hướng Dẫn Xem Xét PR

Khi xem xét các PR liên quan đến CI/CD hoặc phụ thuộc:

  • Ai là contributor? Họ có lịch sử với dự án của bạn không?
  • Tại sao họ thực hiện thay đổi này? PR CI/CD không được yêu cầu là đáng ngờ
  • Quyền truy cập nào sẽ được cấp? Kiểm tra bí mật và quyền truy cập môi trường
  • Có những "sai lầm" rõ ràng không? Đôi khi lỗi là tính năng cho kẻ tấn công

5. Bảo Vệ Kho

yaml Copy
# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: 'npm'
    directory: '/'
    schedule:
      interval: 'weekly'
    reviewers:
      - 'tên-người-dùng-của-bạn'

Kích hoạt các quy tắc bảo vệ nhánh:

  • Yêu cầu xem xét PR cho các thay đổi CI/CD
  • Yêu cầu kiểm tra trạng thái phải vượt qua
  • Hạn chế ai có thể sửa đổi các quy trình làm việc

Yếu Tố Con Người

Điều đáng sợ nhất của các cuộc tấn công chuỗi cung ứng không phải là sự tinh vi về kỹ thuật – mà là cách chúng khai thác bản chất con người của chúng ta. Chúng ta muốn giúp đỡ các contributor. Chúng ta muốn tin tưởng vào những công cụ mà chúng ta sử dụng hàng ngày. Chúng ta muốn hợp nhất PR mà "sửa" một lỗi rõ ràng.

Nhưng trong thời đại các cuộc tấn công tự động và các gói bị xâm phạm, một chút nghi ngờ có thể đi một chặng đường dài. Contributor thân thiện có thể là một bot. PR hữu ích có thể là một cuộc do thám. Việc sửa lỗi chính tả đơn giản có thể đang thiết lập một backdoor.

Bài Học Rút Ra

  1. Tin nhưng cần kiểm tra: Ngay cả những PR hữu ích cũng cần phải được xem xét kỹ lưỡng
  2. Giữ phụ thuộc được cập nhật: Các gói cũ là mục tiêu hấp dẫn
  3. Sử dụng tệp lock một cách chính xác: Khóa các phiên bản và dùng npm ci
  4. Bảo mật CI/CD của bạn: Đây là viên ngọc quý mà kẻ tấn công muốn
  5. Luôn cập nhật thông tin: Theo dõi các nhà nghiên cứu bảo mật và cơ sở dữ liệu lỗ hổng

Ánh Sáng Cuối Đường Hầm

Mặc dù bị nhắm đến bởi một cuộc tấn công chuỗi cung ứng là điều không thoải mái, nhưng nó cũng rất giáo dục. Nó nhắc nhở tôi rằng bảo mật không chỉ là viết mã an toàn – mà còn là bảo vệ toàn bộ quy trình phát triển.

Hệ sinh thái npm cực kỳ mạnh mẽ, nhưng sức mạnh đó đi kèm với trách nhiệm. Mỗi lần npm install là một phiếu bầu tin tưởng vào hàng trăm người duy trì gói. Mỗi quy trình làm việc GitHub Action là một vector tấn công tiềm năng.

Nhưng đừng để điều này khiến bạn sợ hãi khỏi mã nguồn mở. Cộng đồng chính là điều làm cho phát triển JavaScript trở nên tuyệt vời. Chỉ cần thông minh về điều đó. Kiểm tra các phụ thuộc của bạn. Xem xét các quy trình làm việc của bạn. Tin nhưng cần kiểm tra.

Và có thể, chỉ có thể, hãy nghi ngờ một chút khi harshitcodez19 đề nghị giúp đỡ với pipeline CI/CD của bạn.


Chúc các bạn an toàn, các nhà phát triển. Các kẻ tấn công chuỗi cung ứng đang trở nên sáng tạo, nhưng chúng ta cũng vậy.

Tài Liệu Tham Khảo

  • OX Security: Các gói NPM bị xâm phạm
  • Cơ sở dữ liệu tư vấn bảo mật GitHub
  • Tài liệu kiểm tra bảo mật npm
  • Bảo mật GitHub Actions
Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào