Bezpieczny kod źródłowy

1. Omówienie

Techniki bezpiecznego kodu źródłowego to zestaw metod, które można wykorzystać do poprawy bezpieczeństwa kodu źródłowego. Techniki te mogą pomóc w wykrywaniu i rozwiązywaniu luk w zabezpieczeniach kodu źródłowego, zapobieganiu nieautoryzowanemu dostępowi do kodu źródłowego oraz ochronie przed jego modyfikacjami.

Do popularnych technik bezpiecznego kodu źródłowego należą:

  • Linting: linting to proces sprawdzania kodu źródłowego pod kątem błędów i nieprawidłowości stylistycznych. W tym celu wykorzystano narzędzie lintujące, które jest programem analizującym kod źródłowy i wykrywającym potencjalne problemy. Narzędzia Lint umożliwiają wykrywanie różnych błędów, w tym błędów składniowych, semantycznych, stylów i luk w zabezpieczeniach.
  • Statyczne testowanie zabezpieczeń aplikacji (SAST): SAST to typ testów zabezpieczeń, który analizuje kod źródłowy, binarny i bajtowy w celu zidentyfikowania luk w zabezpieczeniach. Narzędzia SAST można wykorzystywać do wykrywania luk w zabezpieczeniach w różnych językach programowania, takich jak Go, Java, Python, C++ czy C#.
  • Skanowanie licencji: skanowanie licencji to proces identyfikowania licencji na komponenty oprogramowania innych firm używane w aplikacji. To ważne, ponieważ pozwala upewnić się, że aplikacja jest zgodna z warunkami licencji, co pozwala uniknąć problemów prawnych.

Techniki te mogą pomóc w zwiększeniu bezpieczeństwa kodu źródłowego na wszystkich etapach cyklu tworzenia oprogramowania. Linting może służyć do identyfikowania błędów na wczesnym etapie programowania, za pomocą SAST można wykrywać luki w zabezpieczeniach przed skompilowaniem lub wdrożeniem kodu, a także skanowanie licencji, aby upewnić się, że aplikacja jest zgodna z warunkami licencji.

Korzystanie z tych technik może pomóc w zwiększeniu bezpieczeństwa kodu źródłowego i zmniejszeniu ryzyka naruszenia bezpieczeństwa.

Czego się nauczysz

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

  • Lintowanie
  • Statyczne testowanie zabezpieczeń aplikacji
  • Skanowanie licencji

Wszystkie narzędzia i polecenia używane 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 wykorzystaj już istniejący. Jeśli nie masz jeszcze konta Gmail ani Google Workspace, musisz je utworzyć.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Nazwa projektu jest wyświetlaną nazwą uczestników tego projektu. To ciąg znaków, który nie jest używany przez interfejsy API Google. W każdej chwili możesz ją zmienić.
  • Identyfikator projektu jest unikalny we wszystkich projektach Google Cloud i nie można go zmienić (po jego ustawieniu nie można go zmienić). Cloud Console automatycznie wygeneruje unikalny ciąg znaków. zwykle nieważne, co ona jest. W większości ćwiczeń z programowania konieczne jest odwołanie się do identyfikatora projektu (zwykle nazywa się on PROJECT_ID). Jeśli nie podoba Ci się wygenerowany identyfikator, możesz wygenerować kolejny losowy. Możesz też spróbować własnych sił i sprawdzić, czy jest dostępna. Potem nie będzie można go zmienić. Pozostanie ono przez czas trwania projektu.
  • Dostępna jest trzecia wartość, numer projektu, z którego korzystają niektóre interfejsy API. Więcej informacji o wszystkich 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć płatności w Cloud Console, aby korzystać z zasobów Cloud/interfejsów API. Ukończenie tego ćwiczenia z programowania nie powinno kosztować zbyt wiele. Aby wyłączyć zasoby, aby nie naliczać opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub cały projekt. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego o wartości 300 USD.

Uruchom edytor Cloud Shell

Ten moduł został opracowany i przetestowany pod kątem użycia z edytorem Google Cloud Shell. Aby uzyskać dostęp do edytora:

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

8560cc8d45e8c112.png

  1. Na dole 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 obszarze środkowym.
  2. Okienko terminala powinno być też dostępne u dołu ekranu
  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, w którym będziemy przechowywać naszą 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 wykrywania typowych błędów związanych ze stylem i defektów związanych ze składnią. Linting zwiększa bezpieczeństwo, zapewniając ten sam wzorzec składni w wielu zespołach, co pozwala na szybsze sprawdzanie kodu, dzielenie się wiedzą i przejrzystość kodu.

Ponadto Linting identyfikuje typowe błędy składni, które mogą prowadzić do powstawania typowych luk w zabezpieczeniach, takich jak niewłaściwe lub mniej efektywne wykorzystanie bibliotek lub podstawowych interfejsów API.

Zainstaluj narzędzie do łączenia usługi staticcheck

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

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

 staticcheck

Sprawdzanie danych wyjściowych

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

Pojawia się błąd, ponieważ http.ListenAndServe() akceptuje ciąg znaków, a bieżący kod używa parametru Sprintf bez przekazywania zmiennych do ciągu znaków

Sprawdź stan wyjścia polecenia.

echo $?

W tym przypadku polecenie spowodowało błąd, więc stan wyjścia będzie miał wartość 1 lub większą. Tej metody można użyć w potoku CI/CD do określenia powodzenia lub niepowodzenia narzędzia.

Edytuj plik main.go i popraw kod:

  • Zmień w komentarz wiersz poniżej LINTING - Step 1 w metodzie main(), dodając ukośniki wiodące(//).
  • Usuń znacznik komentarza z 2 wierszy bezpośrednio pod nagłówkiem LINTING - Step 2 w metodzie main(), usuwając początkowe ukośniki.

Uruchom ponownie staticcheck w katalogu głównym projektu

staticcheck

Polecenie nie powinno zwrócić żadnych wyników (np. pustego wiersza).

Sprawdź stan wyjścia polecenia.

  echo $?

W tym przypadku polecenie nie spowodowało błędu, więc stan wyjścia będzie wynosić zero.

4. Statyczne testowanie zabezpieczeń aplikacji

AST/statyczne testy zabezpieczeń – przeprowadzają statyczną analizę kodu pod kątem typowych słabości i narażenia na ryzyko ( CWE).

Zainstaluj narzędzie 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 zasady w przypadku kodu źródłowego

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

Dane wyjściowe powinny być podobne do tego

{
    "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 możliwy problem: Potential hardcoded credentials

5. Skanowanie licencji

Licencje to ważna kwestia bezpieczeństwa, ponieważ mogą z powodu przepisów prawa wymagać ujawnienia kodu źródłowego, którego nie chcesz ujawniać. Nazwa „ copyleft" licencji, które wymagają udostępnienia kodu źródłowego, jeśli wraz z tymi licencjami używasz zależności.

Zainstaluj aplikację 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 przy użyciu bieżącego pliku zasad, który nie zezwala na „BSD-3-Clause” licencje

golicense policies/license-policy.hcl hello-world

UWAGA: to powinno zakończyć się niepowodzeniem przy podobnych wynikach:

 🚫 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 zasady policies/license-policy.hcl, aby przenieść element „BSD-3-Clause” z listy deny na listę allow.

Ponownie uruchom sprawdzanie licencji

golicense policies/license-policy.hcl hello-world

UWAGA: powinno to się udać, gdy dane wyjściowe będą podobne:

    ✅ 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. Udało Ci się ukończyć ćwiczenia z programowania.

Zdobyte informacje

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

Ostatnia aktualizacja: 23.03.2023