Bezpieczny kod źródłowy

1. Przegląd

Techniki bezpiecznego kodu źródłowego to zbiór praktyk, które można stosować w celu zwiększenia bezpieczeństwa kodu źródłowego. Techniki te mogą pomóc w znalezieniu i naprawieniu luk w kodzie źródłowym, zapobiegać nieautoryzowanemu dostępowi do kodu źródłowego oraz chronić go przed modyfikacjami.

Oto kilka popularnych technik bezpiecznego kodu źródłowego:

  • Linting: linting to proces sprawdzania kodu źródłowego pod kątem błędów i problemów ze stylem. W tym celu używa się narzędzia lint, czyli programu, który analizuje kod źródłowy i wykrywa potencjalne problemy. Narzędzia do sprawdzania kodu mogą służyć do wykrywania różnych błędów, w tym błędów składniowych, semantycznych, stylistycznych i luk w zabezpieczeniach.
  • Statyczne testowanie bezpieczeństwa aplikacji (SAST): SAST to rodzaj testowania bezpieczeństwa, który analizuje kod źródłowy, kod binarny lub kod bajtowy w celu wykrycia luk w zabezpieczeniach. Narzędzia SAST mogą służyć do wykrywania luk w zabezpieczeniach w różnych językach programowania, w tym Go, Java, Python, C++ i C#.
  • Skanowanie licencji: skanowanie licencji to proces identyfikowania licencji komponentów oprogramowania innych firm używanych w aplikacji. Jest to ważne, ponieważ pomaga zapewnić zgodność aplikacji z warunkami licencji, co może zapobiec problemom prawnym.

Te techniki można stosować, aby zwiększyć bezpieczeństwo kodu źródłowego na wszystkich etapach cyklu życia oprogramowania (SDLC). Lintowanie może służyć do wczesnego wykrywania błędów w procesie programowania, SAST może służyć do znajdowania luk w zabezpieczeniach przed skompilowaniem lub wdrożeniem kodu, a skanowanie licencji może służyć do zapewnienia, że aplikacja jest zgodna z warunkami licencji.

Stosowanie tych technik może pomóc zwiększyć bezpieczeństwo kodu źródłowego i zmniejszyć ryzyko naruszenia bezpieczeństwa.

Czego się nauczysz

W tym laboratorium skupimy się na narzędziach i technikach zabezpieczania kodu źródłowego oprogramowania.

  • Lintowanie
  • Statyczne testowanie bezpieczeństwa aplikacji
  • Skanowanie licencji

Wszystkie narzędzia i polecenia użyte w tym module zostaną wykonane w Cloud Shell.

2. Konfiguracja i wymagania

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub użyj istniejącego. Jeśli nie masz jeszcze konta Gmail ani Google Workspace, musisz je utworzyć.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Nazwa projektu to wyświetlana nazwa uczestników tego projektu. Jest to ciąg znaków, który nie jest używany przez interfejsy API Google. Możesz ją zaktualizować w dowolnym momencie.
  • Identyfikator projektu jest unikalny we wszystkich projektach Google Cloud i nie można go zmienić po ustawieniu. Konsola Cloud automatycznie generuje unikalny ciąg znaków. Zwykle nie musisz się nim przejmować. W większości ćwiczeń z programowania musisz odwoływać się do identyfikatora projektu (zwykle jest on oznaczony jako PROJECT_ID). Jeśli wygenerowany identyfikator Ci się nie podoba, możesz wygenerować inny losowy identyfikator. Możesz też spróbować własnej nazwy i sprawdzić, czy jest dostępna. Po tym kroku nie można go zmienić i będzie obowiązywać przez cały czas trwania projektu.
  • Warto wiedzieć, że istnieje też trzecia wartość, czyli numer projektu, z której korzystają niektóre interfejsy API. Więcej informacji o tych 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć płatności w konsoli Cloud, aby korzystać z zasobów i interfejsów API Google Cloud. Ukończenie tego laboratorium nie powinno wiązać się z dużymi kosztami, a nawet z żadnymi. Aby wyłączyć zasoby i uniknąć naliczania opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub cały projekt. Nowi użytkownicy Google Cloud mogą skorzystać z bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.

Uruchamianie edytora Cloud Shell

To laboratorium zostało zaprojektowane i przetestowane pod kątem używania w edytorze Google Cloud Shell. Aby uzyskać dostęp do edytora:

  1. Otwórz projekt Google na stronie https://console.cloud.google.com.
  2. W prawym górnym rogu kliknij ikonę edytora Cloud Shell.

8560cc8d45e8c112.png

  1. U dołu okna otworzy się nowy panel.
  2. Kliknij przycisk Otwórz edytor.

9e504cb98a6a8005.png

  1. Edytor otworzy się z eksploratorem po prawej stronie i edytorem w środkowej części.
  2. U dołu ekranu powinien być też dostępny panel terminala.
  3. Jeśli terminal NIE jest otwarty, użyj kombinacji klawiszy „Ctrl+`”, aby otworzyć nowe okno terminala.

Konfiguracja środowiska

Ustaw GOPATH na jeden katalog, aby uprościć polecenia używane w tym module.

export GOPATH=$HOME/gopath

Utwórz katalog do przechowywania naszych prac.

mkdir -p workspace
cd workspace

Klonowanie repozytorium kodu źródłowego

git clone https://gitlab.com/gcp-solutions-public/shift-left-security-workshop/source-code-lab.git
cd source-code-lab
export WORKDIR=$(pwd)

3. Lintowanie

Linting służy do sprawdzania typowych błędów związanych ze stylem lub składnią. Linting zwiększa bezpieczeństwo, ponieważ zapewnia wspólny wzorzec składni w wielu zespołach, co przyspiesza sprawdzanie kodu, wymianę wiedzy i czytelność kodu.

Dodatkowo lintowanie wykrywa typowe błędy składni, które mogą prowadzić do powszechnych luk w zabezpieczeniach, takich jak nieprawidłowe lub mniej wydajne użycie bibliotek lub podstawowych interfejsów API.

Zainstaluj narzędzie do łączenia staticcheck

 go get honnef.co/go/tools/cmd/staticcheck@latest

Uruchom Go Linter (staticcheck) w katalogu głównym projektu.

 staticcheck

Sprawdź dane wyjściowe

main.go:42:29: unnecessary use of fmt.Sprintf (S1039)

Błąd występuje, ponieważ funkcja http.ListenAndServe() akceptuje ciąg znaków, a bieżący kod używa funkcji Sprintf bez przekazywania zmiennych do ciągu znaków.

Sprawdź stan zakończenia polecenia.

echo $?

W tym przypadku, ponieważ polecenie spowodowało błąd, kod zakończenia będzie wynosić co najmniej 1. Jest to jedna z metod, których można używać w potoku CI/CD do określania, czy narzędzie działa prawidłowo.

Edytuj plik main.go i popraw kod:

  • Zmień w komentarz wiersz poniżej LINTING - Step 1 w metodzie main(), dodając ukośniki(//).
  • Usuń znaczniki komentarza z 2 wierszy bezpośrednio pod LINTING - Step 2 w metodzie main(), usuwając ukośniki na początku.

Ponownie uruchom staticcheck w katalogu głównym projektu.

staticcheck

Polecenie nie powinno zwracać żadnych wyników (czyli pustego wiersza).

Sprawdź stan zakończenia polecenia.

  echo $?

W tym przypadku, ponieważ polecenie nie spowodowało błędu, stan zakończenia będzie wynosić zero.

4. Statyczne testowanie bezpieczeństwa aplikacji

Testowanie bezpieczeństwa statycznego (AST) – zapewnia statyczną analizę kodu w celu wykrycia typowych słabych punktów i luk w zabezpieczeniach (CWE).

Instalowanie narzędzia 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}

Uruchom gosec z plikiem zasad w odniesieniu do kodu źródłowego.

gosec -conf policies/gosec-policy.json -fmt=json ./...

Dane wyjściowe powinny być podobne do tych:

{
    "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
    }
}

Narzędzie wykryło potencjalny problem: Potential hardcoded credentials

5. Skanowanie licencji

Licencje są ważne dla bezpieczeństwa, ponieważ mogą prawnie wymagać udostępnienia kodu źródłowego, którego nie chcesz udostępniać. Koncepcja ta jest nazywana licencjami „copyleft”, które wymagają udostępnienia kodu źródłowego, jeśli używasz zależności z tymi licencjami.

Zainstaluj element 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

Kompilowanie pliku binarnego

go build

Uruchom sprawdzanie licencji z użyciem bieżącego pliku zasad, który nie zezwala na licencje „BSD-3-Clause”.

golicense policies/license-policy.hcl hello-world

UWAGA: powinno to się nie udać i wyświetlić podobne dane wyjściowe:

 🚫 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

Zmodyfikuj plik zasad policies/license-policy.hcl, aby przenieść licencję „BSD-3-Clause” z listy deny na listę allow.

Ponowne uruchomienie weryfikacji licencji

golicense policies/license-policy.hcl hello-world

UWAGA: powinno się to udać i wyświetlić podobne dane wyjściowe:

    ✅ 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. Gratulacje

Gratulacje! Codelab został ukończony.

Czego się dowiedziałeś

  • Narzędzia i techniki zabezpieczania kodu źródłowego

Ostatnia aktualizacja: 23 marca 2023 r.