1. 개요
보안 소스 코드 기법은 소스 코드의 보안을 개선하는 데 사용할 수 있는 일련의 관행입니다. 이러한 기법을 사용하면 소스 코드의 취약점을 식별하고 수정하고, 소스 코드에 대한 무단 액세스를 방지하고, 소스 코드가 수정되지 않도록 보호할 수 있습니다.
몇 가지 일반적인 보안 소스 코드 기법은 다음과 같습니다.
- 린팅: 린팅은 소스 코드에서 오류 및 스타일 문제를 확인하는 프로세스입니다. 소스 코드를 분석하고 잠재적 문제를 식별하는 프로그램인 린트 도구를 사용하여 실행됩니다. 린트 도구는 문법 오류, 의미 오류, 스타일 오류, 보안 취약점 등 다양한 오류를 확인하는 데 사용할 수 있습니다.
- 정적 애플리케이션 보안 테스트 (SAST): SAST는 소스 코드, 바이너리 코드 또는 바이트 코드를 분석하여 보안 취약점을 식별하는 보안 테스트 유형입니다. SAST 도구는 Go, Java, Python, C++, C# 등 다양한 프로그래밍 언어에서 취약점을 찾는 데 사용할 수 있습니다.
- 라이선스 스캔: 라이선스 스캔은 소프트웨어 애플리케이션에 사용되는 서드 파티 소프트웨어 구성요소의 라이선스를 식별하는 프로세스입니다. 이는 애플리케이션이 라이선스 약관을 준수하도록 하는 데 도움이 되므로 법적 문제를 방지하는 데 도움이 됩니다.
이러한 기법은 소프트웨어 개발 수명 주기의 모든 단계에서 소스 코드의 보안을 개선하는 데 사용할 수 있습니다. 린팅은 개발 프로세스 초기에 오류를 식별하는 데 사용할 수 있고, SAST는 코드가 컴파일되거나 배포되기 전에 취약점을 찾는 데 사용할 수 있으며, 라이선스 검사는 애플리케이션이 라이선스 약관을 준수하는지 확인하는 데 사용할 수 있습니다.
이러한 기법을 사용하면 소스 코드의 보안을 강화하고 보안 침해 위험을 줄일 수 있습니다.
학습할 내용
이 실습에서는 소프트웨어 소스 코드를 보호하는 도구와 기법에 중점을 둡니다.
- 린트 작업
- 정적 애플리케이션 보안 테스트
- 라이선스 스캔
이 실습에서 사용되는 모든 도구와 명령어는 Cloud Shell에서 실행됩니다.
2. 설정 및 요구사항
자습형 환경 설정
- Google Cloud Console에 로그인하여 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. 아직 Gmail이나 Google Workspace 계정이 없는 경우 계정을 만들어야 합니다.
- 프로젝트 이름은 이 프로젝트 참가자의 표시 이름입니다. 이는 Google API에서 사용하지 않는 문자열이며 언제든지 업데이트할 수 있습니다.
- 프로젝트 ID는 모든 Google Cloud 프로젝트에서 고유하며, 변경할 수 없습니다(설정된 후에는 변경할 수 없음). Cloud 콘솔은 고유한 문자열을 자동으로 생성합니다. 일반적으로는 신경 쓰지 않아도 됩니다. 대부분의 Codelab에서는 프로젝트 ID (일반적으로
PROJECT_ID
로 식별됨)를 참조해야 합니다. 생성된 ID가 마음에 들지 않으면 다른 임의 ID를 생성할 수 있습니다. 또는 직접 시도해 보고 사용 가능한지 확인할 수도 있습니다. 이 단계 이후에는 변경할 수 없으며 프로젝트 기간 동안 유지됩니다. - 참고로 세 번째 값은 일부 API에서 사용하는 프로젝트 번호입니다. 이 세 가지 값에 대한 자세한 내용은 문서를 참고하세요.
- 다음으로 Cloud 리소스/API를 사용하려면 Cloud 콘솔에서 결제를 사용 설정해야 합니다. 이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 튜토리얼이 끝난 후에 요금이 청구되지 않도록 리소스를 종료하려면 만든 리소스 또는 전체 프로젝트를 삭제하면 됩니다. 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. 린트 작업
린팅은 구문과 관련된 일반적인 스타일 기반 실수나 결함을 확인하는 데 사용됩니다. 린팅은 여러 팀에 공통 문법 패턴을 제공하여 보안을 지원하므로 코드 검토 속도가 빨라지고 지식이 공유되며 코드가 명확해집니다.
또한 린팅은 라이브러리 또는 핵심 API의 부적절하거나 비효율적인 사용과 같은 일반적인 취약점으로 이어질 수 있는 일반적인 문법 실수를 식별합니다.
staticcheck
연결 도구 설치
go get honnef.co/go/tools/cmd/staticcheck@latest
프로젝트 루트 디렉터리에서 Go 린터 (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 $?
이 경우 명령어로 인해 오류가 발생하지 않았으므로 종료 상태는 0이 됩니다.
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
6. 축하합니다
축하합니다. Codelab을 완료했습니다.
학습한 내용
- 소스 코드 보호를 위한 도구 및 기법
—
최종 업데이트: 2023년 3월 23일