程式碼研究室簡介
1. 總覽
安全原始碼技術是一組做法,可用於提升原始碼的安全性。這些技術有助於識別及修正原始碼中的安全漏洞、防止未經授權的存取原始碼,並防止原始碼遭到修改。
常見的安全原始碼技術包括:
- Linting:Linting 是指檢查原始碼是否有錯誤和樣式問題的程序。方法是使用 Lint 工具,此工具可分析原始碼並找出潛在問題。Lint 工具可用於檢查各種錯誤,包括語法錯誤、語意錯誤、樣式錯誤和安全漏洞。
- 靜態應用程式安全性測試 (SAST):SAST 是一種安全性測試類型,可分析原始碼、二進位程式碼或位元組程式碼,以找出安全漏洞。SAST 工具可用來找出各種程式設計語言中的安全漏洞,包括 Go、Java、Python、C++ 和 C#。
- 授權掃描:授權掃描是指識別軟體應用程式中使用的第三方軟體元件授權的程序。請務必留意,確保應用程式符合授權條款規定,以避免發生法律問題。
這些技術可用於提高原始碼在軟體開發生命週期中所有階段的安全性。Linting 可用於在開發流程初期找出錯誤,可在程式碼編譯或部署之前利用 SAST 找出漏洞,並利用授權掃描來確保應用程式符合授權條款。
使用這些技術有助於提升原始碼的安全性,並降低安全性漏洞的風險。
學習目標
本研究室將著重介紹保護軟體原始碼的工具和技術。
- Linting
- 靜態應用程式安全性測試
- 授權掃描
本研究室中使用的所有工具和指令,都會在 Cloud Shell 中執行。
2. 設定和需求
自修環境設定
- 登入 Google Cloud 控制台,建立新專案或重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶。
- 「專案名稱」是這項專案參與者的顯示名稱。這是 Google API 未使用的字元字串。您隨時可以更新這項資訊。
- 所有 Google Cloud 專案的專案 ID 均不得重複,而且設定後即無法變更。Cloud 控制台會自動產生一個不重複的字串。但通常是在乎它何在在大部分的程式碼研究室中,您必須參照專案 ID (通常為
PROJECT_ID
)。如果您對產生的 ID 不滿意,可以隨機產生一個 ID。此外,您也可以自行嘗試,看看系統是否提供該付款方式。在完成這個步驟後就無法變更,而且在專案期間仍會保持有效。 - 資訊中的第三個值是專案編號,部分 API 會使用這個編號。如要進一步瞭解這三個值,請參閱說明文件。
- 接下來,您需要在 Cloud 控制台中啟用計費功能,才能使用 Cloud 資源/API。執行這個程式碼研究室並不會產生任何費用,如果有的話。如要關閉資源,以免系統產生本教學課程結束後產生的費用,您可以刪除自己建立的資源,或刪除整個專案。Google Cloud 的新使用者符合 $300 美元免費試用計畫的資格。
啟動 Cloud Shell 編輯器
本研究室專為與 Google Cloud Shell 編輯器搭配使用而設計和測試。如要存取編輯器
- 前往 https://console.cloud.google.com 存取 Google 專案。
- 按一下右上角的「Cloud Shell 編輯器」圖示
- 視窗底部隨即會開啟新的窗格
- 點選「開啟編輯器」按鈕
- 編輯器隨即開啟,右側會顯示多層檢視,中央區則顯示編輯者
- 畫面底部應會顯示終端機窗格
- 如果終端機「未」開啟,使用 `ctrl+` 的按鍵組合開啟新的終端機視窗
環境設定
將 GOPATH 設為單一目錄,即可簡化本研究室中使用的指令。
export GOPATH=$HOME/gopath
建立目錄來存放工作
mkdir -p workspace
cd workspace
複製原始碼存放區
git clone https://gitlab.com/gcp-solutions-public/shift-left-security-workshop/source-code-lab.git
cd source-code-lab
export WORKDIR=$(pwd)
3. Linting
程式碼檢查可用於檢查與語法相關的常見樣式錯誤或瑕疵。程式碼檢查可以在多個團隊提供通用的語法模式,因此能加快程式碼審查、知識分享以及程式碼清晰度,進而協助安全性。
此外,Lint 可找出可能導致常見安全漏洞的常見語法錯誤,例如程式庫或核心 API 使用不當或效率降低。
安裝 staticcheck
連結工具
go get honnef.co/go/tools/cmd/staticcheck@latest
在專案根目錄中執行 Go Linter (staticcheck)
staticcheck
查看輸出內容
main.go:42:29: unnecessary use of fmt.Sprintf (S1039)
你之所以會收到錯誤,是因為 http.ListenAndServe()
接受字串,而目前的程式碼卻使用 Sprintf
,但未將變數傳遞至字串
查看指令結束狀態。
echo $?
在此情況下,由於指令發生錯誤,結束狀態會是 1 以上。這是一個可用於 CI/CD 管道的方法,可用來判斷工具是否成功/失敗。
編輯 main.go
檔案並修正程式碼:
- 在
main()
方法中加上前置斜線(//
),將LINTING - Step 1
下方的程式碼註解排除。 - 移除開頭的斜線,以取消註解
main()
方法中LINTING - Step 2
下方的兩行。
在專案根目錄中重新執行 staticcheck
staticcheck
這個指令不應傳回任何結果 (即空白行)。
檢查指令的結束狀態。
echo $?
在此情況下,由於指令並未產生錯誤,因此結束狀態會是 0ro。
4. 靜態應用程式安全性測試
AST/靜態安全性測試:提供靜態程式碼分析,尋找常見的弱點與暴露 ( CWE)
安裝 AST 工具 (gosec
)
export GOSEC_VERSION="2.15.0"
curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | \
sh -s -- -b $(go env GOPATH)/bin v${GOSEC_VERSION}
針對原始碼執行含政策檔案的 gosec
gosec -conf policies/gosec-policy.json -fmt=json ./...
輸出內容應該會類似以下
{ "Golang errors": {}, "Issues": [ { "severity": "HIGH", "confidence": "LOW", "cwe": { "ID": "798", "URL": "https://cwe.mitre.org/data/definitions/798.html" }, "rule_id": "G101", "details": "Potential hardcoded credentials", "file": "/home/random-user-here/shift-left-security-workshop/labs/source-code-lab/main.go", "code": "31: \t// STEP 2: Change this and the reference below to something different (ie, not \"pawsword\" or \"password\")\n32: \tvar pawsword = \"im-a-cute-puppy\"\n33: \tfmt.Println(\"Something a puppy would use: \", username, pawsword)\n", "line": "32", "column": "6" } ], "Stats": { "files": 1, "lines": 89, "nosec": 0, "found": 1 } }
這項工具發現了潛在問題:Potential hardcoded credentials
5. 授權掃描
授權相當重要,因為這類授權要求必須依法揭露您可能不想公開的原始碼。這個概念稱為copyleft"授權時,您必須公開原始碼才能使用這類授權。
安裝「golicense
」
mkdir -p /tmp/golicense
wget -O /tmp/golicense/golicense.tar.gz https://github.com/mitchellh/golicense/releases/download/v0.2.0/golicense_0.2.0_linux_x86_64.tar.gz
pushd /tmp/golicense
tar -xzf golicense.tar.gz
chmod +x golicense
mv golicense $(go env GOPATH)/bin/golicense
popd
建構二進位檔檔案
go build
使用目前禁止「BSD-3-Clause」的政策檔案執行授權檢查授權數
golicense policies/license-policy.hcl hello-world
注意:這應該會失敗,產生相似的輸出結果:
🚫 rsc.io/sampler BSD 3-Clause "New" or "Revised" License 🚫 rsc.io/quote BSD 3-Clause "New" or "Revised" License 🚫 golang.org/x/text BSD 3-Clause "New" or "Revised" License
修改政策檔案 policies/license-policy.hcl
來移動「BSD-3-Clause」從 deny
清單到 allow
清單
重新執行授權檢查
golicense policies/license-policy.hcl hello-world
注意:輸出內容應類似下列輸出內容:
✅ rsc.io/quote BSD 3-Clause "New" or "Revised" License ✅ rsc.io/sampler BSD 3-Clause "New" or "Revised" License ✅ golang.org/x/text BSD 3-Clause "New" or "Revised" License