Github Actions: Góc nhìn security

Tuần rồi mình có ngồi xem qua mấy cái Github Actions cho vui. Và đây chính là một bài blog nói qua góc nhìn/quan điểm của mình (thì tất nhiên, post trên blog mình mà 🐧) về thứ công nghệ này. Cũng như những ý tưởng audit mình dự phóng được.

Càng ngày việc lập trình càng trở nên dễ dàng và phổ biến hơn. Những nghành nghề truyền thống khác cũng dần hòa nhập sát hơn với công nghệ, giờ tui thấy mấy bạn học kinh tế, dữ liệu giờ cũng bắt đầu học code.

Bởi lẽ thế việc nhu cầu tự động hóa mọi thứ và dần dần robot sẽ len lỏi trong các ngóc ngách của việc lập trình. Người ta càng ngày muốn nó càng tiện hơn và dễ tiếp cận hơn mà.

Nếu ai chưa biết thì Github Actions giúp chúng ta tự động hóa các workflow, đôi khi chỉ cần bạn push lên repo của mình là hệ thống có thể tự động build và publish nó lên đủ nơi.

Nó còn được dùng để xử lý các pull request, commits, issues một cách tự động hết. Thậm chí còn có thể chạy các workflow kiểm tra lỗi bảo mật bằng snyk/actions hoặc codeql-action khi có một pull request được merge vào chẳng hạn.

Cơ chế của nó thì để mình ráng review 3 phút lại

Tất cả các bước sẽ được định nghĩa trong một file có đuôi .ymltrong thư mục {your_repo}/.github/workflows/ của bạn.

Kèm theo các cấu hình để nói cho runner biết rằng nên chạy những thao tác nàò, nên chạy khi nào (push/pull/issue/…) hoặc thậm chí còn có thể đặt lịch.

Còn có thể chạy được lệnh shell nữa, quá xịn!

Và còn rất nhiều cấu hình khác nhau nữa. Các bạn muốn tìm hiểu nó thì tại đây nhé, cũng không quá khó đâu.

Giờ mình có một ví dụ một workflows demo.yml dùng để thao tác tự động ngay khi có một issue được mở ở repo của mình như sau:


[ Reference: https://github.community/t/get-contents-body-of-issue-in-action/136057 ]

Túm lại là:

Khi một issue được mở ra (opened) thì Actions sẽ mở một runner ubuntu phiên bản latest, sau đó chạy lệnh shell gửi một gói tin HTTP POST tới endpoint WEBHOOK_URL của mình định nghĩa sẵn. với nội dung là: {text:"Có người mở issue nè cha - _Title của Issue_"}

github.event.issue.title chính là một biến ngữ cảnh được sinh ra khi runner chạy. Có thể tham khảo trên tài liệu của Github Actions nha.

WEBHOOK ở đây có thể là Slack webhook chẳng hạn, vậy thì chỉ cần có người mở issue của mình lên là sẽ có một con bot chat vào slack room để thông báo cho mình biết. Tiện thế!

NHƯNG

Điều gì đến nó cũng đến, việc sinh ra features cũng đồng thời mang lại rủi ro. Rủi ro này nó có thể đến từ:

  1. Trong cách thiết kế, design ban đầu chúng ta chưa tính toán đầy đủ các trường hợp.
  2. Việc sử dụng sai của một số người dùng nó.

Về cái lí do thứ nhất: cái này khó tránh lắm, không có gì hoàn toàn bảo mật cả. Đôi khi vắt óc design rồi nhưng bạn cũng phải đưa nó chạy thử thì mới có sinh ra mấy vấn đề thực tế.

Cái thứ 2 thì :))) không phải ai cũng là siêu nhân, hoặc là một người lập trình giỏi, suy sét, cẩn thận. Mà thậm chí bạn có là người chu đáo thì cũng sẽ có một lúc nào đó bạn bất cẩn thôi.

NHỮNG SAI LẦM HAY MẮC PHẢI

Đầu tiên đó chính là cái expression ${{ ... }}

Trước khi shell chạy thì Github Actions, sẽ tìm trong nội dung script có thấy cái expression trên không. Nếu có thì sẽ thực thi lệnh trong expression đó rồi sẽ thay thế cả cái cụm đó bằng kết quả.

Tức nếu bây giờ quay lại với cái demo.yml thì nếu có một tay attacker nào đó tạo ra một cái issue tên là:

Thì ngay lập tức action sẽ được thực thi, và trong hình chúng ta có thể thấy

Mình đã thực hiện script injection và list dir thành công.

Và đây là by-design, vốn nguyên lý này đã hoạt động đúng như dự tính của nó, chỉ là người dùng đã ngây thơ tận dụng dùng nó để chạy shell trở nên tiện hơn.

Và vui hơn nữa, nếu nhìn lại thì demo.yml là mình tham khảo từ chính một đoạn cấu hình ví dụ trên trang github.community :))) nên chắc hẵn không ít người đã lên đọc bài này và copy các đoạn cấu hình về dùng mà không mảy may biết rủi ro của nó.

Từ việc script injection, attacker có thể chạy shell trên runner của nạn nhân, có thể lấy được các Github Token, Secrets từ đó có thể compromise cả một cái repo và nhiều hơn thế nữa (tùy vào ngữ cảnh).

Github cũng đã cho ra một bài viết nói về việc sử dụng sai expression ${{...}} có thể dẫn đến script injection để cảnh giác người dùng: https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#understanding-the-risk-of-script-injections

Như họ nói thì ngoài issue.title còn có rất nhiều untrusted input khác mà attacker có thể tác động

CÁC VẤN ĐỀ CÓ THỂ XẢY RA TRONG TƯƠNG LAI

Mình dự phóng có một số vấn đề có thể xảy ra tiếp theo như:

Vì ngoài run , Github Actions còn hỗ trợ uses tức là sử dụng các cấu hình workflow tự động từ các nhà lập trình khác. Vì rõ ràng nhu cầu rất phức tạp nên việc cộng đồng hỗ trợ nhau là điều tất nhiên.

Khi sử dụng uses nó sẽ kéo các actions từ các repos đó về chạy. Và các actions này còn có thể viết bằng đủ thứ ngôn ngữ lập trình (node/python/ruby/go/…) có thể chạy cả docker.

Vậy nên việc một actions nào đó nhiều stars và nổi tiếng mà bị lỗi lập trình gì đó dẫn đến bypass/injection/… thì sẽ đi cả food chain.

Ngoài ra còn có một actions hỗ trợ cho người dùng viết các script tự động một cách tiện hơn tên actions/github-script. Vậy quay lại bài toán là người viết script sẽ lập trình sai có thể dẫn đến các lỗi injection.

https://github.com/search?q=language%3Ayaml+actions%2Fgithub-script&type=code

Có khoảng 19,834 kết quả cho việc sử dụng actions/github-script

Mình nghĩ Github cũng đã lường được những rủi ro này rồi, chắc rằng họ cũng sẽ có những biện pháp nhất định.

Bài đến đây hết rồi, nói chung là tui khá thấy thích thú. Nghiên cứu nó cũng là một trải nghiệm mới mẻ, hi vọng bài viết sẽ có ích với những người đang dùng hoặc muốn nghiên cứu sâu về nó.

Peace.

manhluat Written by:

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *