安全原始碼

1. 總覽

安全的原始碼技術是一組可用於提升原始碼安全性的做法。這些技術有助於找出及修正原始碼中的安全漏洞、防止未經授權存取原始碼,以及保護原始碼免於遭到修改。

常見的安全原始碼技術包括:

  • Linting:Linting 是檢查原始碼是否有錯誤和樣式問題的程序。這項工作是透過 lint 工具完成,這是一項可分析原始碼並找出潛在問題的程式。您可以使用 Lint 工具檢查各種錯誤,包括語法錯誤、語義錯誤、樣式錯誤和安全漏洞。
  • 靜態應用程式安全性測試 (SAST):SAST 是一種安全性測試,可分析原始碼、二進位碼或位元碼,找出安全性漏洞。SAST 工具可用於找出各種程式設計語言中的安全漏洞,包括 Go、Java、Python、C++ 和 C#。
  • 授權掃描:授權掃描是指識別軟體應用程式中所用第三方軟體元件的授權。這很重要,因為這有助於確保應用程式遵守授權條款,避免法律問題。

這些技巧可用於軟體開發生命週期的所有階段,提升原始碼的安全性。您可以使用 Linting 在開發過程的早期找出錯誤,也可以使用 SAST 在編譯或部署程式碼前找出安全漏洞,並使用授權掃描功能確保應用程式遵守授權條款。

使用這些技術有助於提升原始碼的安全性,並降低安全性違規的風險。

學習目標

本實驗室將著重於保護軟體原始碼的工具和技巧。

  • Linting
  • 靜態應用程式安全性測試
  • 掃描授權

本研究室中使用的所有工具和指令都會在 Cloud Shell 中執行。

2. 設定和需求

自學環境設定

  1. 登入 Google Cloud 控制台,然後建立新專案或重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請務必建立帳戶

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • 「Project name」是這個專案參與者的顯示名稱。這是 Google API 不會使用的字元字串。您隨時可以更新。
  • 專案 ID 在所有 Google Cloud 專案中都是不重複的值,且無法變更 (設定後即無法變更)。Cloud 控制台會自動產生一個專屬字串,您通常不需要特別留意。在大多數程式碼研究室中,您都需要參照專案 ID (通常會標示為 PROJECT_ID)。如果您不喜歡系統產生的 ID,可以隨機產生另一組 ID。或者,您也可以自行嘗試,看看是否可用。這項設定在這個步驟後即無法變更,並會在專案期間維持不變。
  • 僅供參考,有些 API 會使用第三個值,也就是「專案編號」。如要進一步瞭解這三個值,請參閱說明文件
  1. 接下來,您需要在 Cloud 控制台中啟用帳單功能,才能使用 Cloud 資源/API。執行本程式碼研究室時,費用應該不會太高,甚至可能不收費。如要關閉資源,避免產生教學課程以外的費用,您可以刪除已建立的資源,或刪除整個專案。Google Cloud 新使用者可享有 $300 美元的免費試用期

啟動 Cloud Shell 編輯器

本研究室是專為搭配 Google Cloud Shell 編輯器使用而設計及測試。如要存取編輯器,請按照下列步驟操作:

  1. 前往 https://console.cloud.google.com 存取 Google 專案。
  2. 按一下右上角的雲端 Shell 編輯器圖示

8560cc8d45e8c112.png

  1. 視窗底部會開啟新的窗格
  2. 按一下「Open Editor」(開啟編輯器) 按鈕

9e504cb98a6a8005.png

  1. 編輯器會隨即開啟,右側顯示探索器,中央區域則顯示編輯器
  2. 畫面底部也應有終端機窗格
  3. 如果終端機未開啟,請使用 `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

檢查工具可用於檢查常見的樣式錯誤或與語法相關的瑕疵。透過 Linting 提供跨團隊通用的語法模式,有助於提升安全性,讓團隊更快完成程式碼審查、分享知識,並讓程式碼更清晰。

此外,Linting 會找出可能導致常見漏洞的常見語法錯誤,例如不當或效率較低的程式庫或核心 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 下方的 LINTING - Step 1 行註解排除,方法是加上開頭斜線(//)。
  • 移除 main() 方法內 LINTING - Step 2 下方兩行的開頭斜線,取消註解這兩行。

在專案根目錄中重新執行 staticcheck

staticcheck

指令不應傳回任何結果 (即空白行)。

檢查指令的結束狀態。

  echo $?

在這種情況下,由於指令不會導致錯誤,因此結束狀態會是

4. 靜態應用程式安全性測試

AST/靜態安全性測試:提供靜態程式碼分析,找出常見的弱點和曝露 ( CWEs)

安裝 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

6. 恭喜

恭喜,您已完成程式碼研究室!

您學到的內容

  • 保護原始碼的工具和技巧

上次更新時間:2023 年 3 月 23 日