Ambisjonen med denne artikkelen er å opplyse leseren om hva secret scanning er. I tillegg skal jeg vise hvordan man kan evaluere egen kildekode uten at man trenger å abonnere på en tjeneste. Samt vise hvordan man kan gjøre secret scanning uten å gi fra seg koden til en tredjepart.

Så hva er egentlig secret scanning?

Det innebærer at man tråler gjennom kildekode i søken på passord, sertifikater, privat-nøkler eller API-nøkler. Enten fordi man har hensikter om å misbruke informasjonen, eller fordi man ønsker å styrke sikkerheten ved å skifte ut lekkede nøkler.

Man begynner gjerne jakten på nøkler der kildekoden eksisterer. Kall det kodebibliotek, publiseringssted, versjonskontrollsystem eller repository som vi gjerne sier på nynorsk. Publiseringsstedet trenger ikke være basert på git, men de mest populære tilbyderne av versjonskontroll-tjenester bygges som oftest på git (GitHub, GitLab, Bitbucket).

Whoops! Vi publiserte!

På et tidspunkt har man kanskje publisert kode med hardkodede nøkler. Kanskje man også presterte å slette commiten fra repositoriet innen kort tid. Det kan likevel være lurt å rotere nøkkelen man kom til skade for å publisere. Truffle Security Company publiserte i sommer en artikkel der de demonstrerer hvordan de kan aksessere data fra commits som eieren selv har slettet. Commiten vil være tilgjengelig «for alltid» så lenge man får tak i commit-hashen.

Man trenger ikke å få tak i den 32 karakter lange SHA-1 hashen engang, da det holder med kortversjonen (eksempel:6757d9be8d5487e0faa1dadeb1f9eb634e66885f mens kortversjonen er 6757d9b). Alternativt kan man støtte seg på gharchive.org eller lignende tjenester for å finne en hash. Det er derfor trygt å anta at en lekket nøkkel må roteres. Alltid.

Les gjerne mer om disse funnene på trufflesecurity.com. Hvis du har det travelt med å rotere noen nøkler nå, kan jeg anbefale deg å ta en titt her.

Hvor oppbevarer du koden din i dag?

Et viktig aspekt er hvor og hvordan man oppbevarer og håndterer kildekode. Noen velger å publisere koden sin som åpen kildekode på GitHub eller Bitbucket. Andre velger gjerne å oppbevare den på Gitlab servere som man selv administrerer «on-prem». Det som fungerer for en bedrift fungerer ikke nødvendigvis for alle andre.

En virksomhet som velger å publisere all kode bør selvsagt ha et bevisst forhold til secret scanning. En virksomhet som holder all kildekode for seg selv vil gjerne ta litt lettere på det. Men i dagens utviklingstakt er det absolutt lurt å ta standpunkt til secret scanning likevel. Det kan tenkes at man skal samarbeide på tvers av avdelinger og virksomheter, eller kanskje virksomheten din kjøper opp en annen bedrift. Det er ikke alle situasjoner som er like lett å forutse. Da kommer «god sikkerhetshygiene» godt med.

For dem som eventuelt tenker at private repositories er «bombesikre»; Husk at det menneskelige aspektet er der sikkerheten svikter oftest. Innside-trusselen vil alltid være reell og tabber skjer. Om ikke det var nok, så finner vi stadig sårbarheter som potensielt kan gi fotfeste i sikret infrastruktur. Det er med andre ord lurt å ha et bevisst forhold til hvordan man håndterer secrets i egen kildekode, selv om man har lukket tilgangen til repository-serveren med flere sikkerhetsmekanismer.

Så hvordan sikrer vi oss?

En informert leser vil sannsynlig utrope ganske raskt at GitHub allerede har en gratis secret scanning for sine åpne repositories (configure secret scanning). Denne funksjonaliteten er «opt-in» og må således skrus på. Det finnes et hav av måter å oppbevare egen kildekode på. Det er således ingen «one stop solution». Jeg ønsker med denne artikkelen å bevisstgjøre leseren om fallgruven som er publisering av tokens, api-nøkler, artefakter og passord. Bedriften eller teamet må selv finne en egnet metode for å sikre god sikkerhetskultur på arbeidsplassen.

Jobb med kulturen

En gjenganger er at funksjonalitet trumfer sikkerhet, og høy utviklingstakt trumfer sikkerhetsrevisjoner. Et annet aspekt er at ferske utviklere gjerne måles på antall commits som legger til ny funksjonalitet eller lukker bugs fra backloggen. En senior har gjerne flere frister og deloppgaver. Oppfølging av junior-utviklerne blir gjerne ikke satt øverst på prioriteringslista, og vipps så står vi i en situasjon der produktiviteten til den enkelte utvikler trumfer fokuset på «skuddsikker» kode.

En god start kan være å dele relevante nyheter relatert til informasjonssikkerhet i teamet. En sterk sikkerhetskultur starter med godt opplyste engasjerte medarbeidere.

Kunstig Intelligens, AI og buzzword-bingo

Med kunstig intelligens inntog dukker det stadig opp nye eksempler på slepphendt håndtering av secrets. Microsofts KI forskere publiserte eksempelvis 38 terabyte med data som uheldigvis inneholdt store mengder private nøkler, passord og interne meldingslogger fra teams samtaler. WIZ Research har skrevet en spennende analyse av saken.

En observant leser vil gjerne oppdage at dataene i dette tilfellet ble eksponert for almuen gjennom feilkonfigurasjon av SAS tokens. Men utfordringen er likevel høyst relevant. Passord, API-nøkler og tilsvarende burde definitivt vært sanert før datasettet ble lastet opp.

Fremdeles ikke overbevist?

Et godt eksempel på hvorfor problemstillingen i aller høyeste grad er gjeldende for et bredt publikum, illustreres i How Bad Can It Git? Characterizing Secret Leakage in Public GitHub Repositories som er utarbeidet ved North Carolina State University. De fleste som forstår git ville naturlig tenkt at man lagrer secrets og annen sensitiv informasjon i egne filer, og referer til disse i .gitignore for å slippe at sensitiv informasjon lastes opp når en commit pushes. I deres rapport kommer det frem at de oppdaget 58 secrets i løpet av en tre ukers periode ved å analysere innholdet i .gitignore filer de samlet inn. Det kommer antagelig av fundamental misforståelse om hvordan git benytter .gitignore filen.

Det finnes et bredt spekter av verktøy som kan bistå utvikleren med deteksjon av secrets. Vi skal ta en titt på Gitleaks og trufflehog, ettersom det er to enkle og gode alternativ som kan kjøres lokalt på egen maskin.

Lab gitleaks

La oss først se på Gitleaks. Gitleaks kan installeres gjennom homebrew på mac, i en docker container hvis du kjører windows eller hent kildekoden direkte hvis det er din foretrukne metode.

MacOS

brew install gitleaks

Docker (ghcr.io)

docker pull ghcr.io/gitleaks/gitleaks:latest
docker run -v ${path_to_host_folder_to_scan}:/path ghcr.io/gitleaks/gitleaks:latest [COMMAND] --source="/path" [OPTIONS]

From Source

git clone https://github.com/gitleaks/gitleaks.git
cd gitleaks
make build

Jeg har opprettet et repository på GitHub for demoens skyld. Lesere må gjerne benytte dette repositoriet for sin egen labbing. Det er lagt inn en API-nøkkel og en SSH nøkkel i dette repositoriet for demonstrasjon. Disse er kun generert for blogg-innlegget og benyttes således ikke til noe annet.

git clone https://github.com/karltehgreat/shiny-secrets

For en enkel test og verifikasjon kan man kjøre en gitleaks detect for å se at det eksisterer en SSH nøkkel og en api-nøkkel i repositoriet.

cd shiny-secrets
gitleaks detect

Stdout vil svare med:

shiny-secrets % gitleaks detect

    ○
    │╲
    │ ○
    ○ ░
    ░    gitleaks

12:51PM INF 3 commits scanned.
12:51PM INF scan completed in 31.5ms
12:51PM WRN leaks found: 2

Så vi ser i siste linje at det ligger inne to advarsler. Vi benytter verbose flagget for å få mer informasjon.

shiny-secrets % gitleaks detect -v

    ○
    │╲
    │ ○
    ○ ░
    ░    gitleaks

Finding:     "localAPI-Key": "8ugS5gDLVzKDHRez0QwLgKLXX369TJNKegMslrMwAPGHn30kUHajRv2N91L8kvxMwc9mvoATPgsoy7hiBAtkAOb0QIayDlTysSAO..."
Secret:      8ugS5gDLVzKDHRez0QwLgKLXX369TJNKegMslrMwAPGHn30kUHajRv2N91L8kvxMwc9mvoATPgsoy7hiBAtkAOb0QIayDlTysSAO...
RuleID:      generic-api-key
Entropy:     5.580564
File:        shiny-secrets.py
Line:        8
Commit:      7fdddf4b0c36af6445965e233dded52a25ef5cea
Author:      Karl Valle
Email:       
Date:        2024-06-21T10:24:11Z
Fingerprint: 7fdddf4b0c36af6445965e233dded52a25ef5cea:shiny-secrets.py:generic-api-key:8

Finding:     -----BEGIN OPENSSH PRIVATE KEY-----                                
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDa...
Secret:      -----BEGIN OPENSSH PRIVATE KEY-----                                
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDa...
RuleID:      private-key
Entropy:     5.733593
File:        shiny-secrets.py
Line:        14
Commit:      7fdddf4b0c36af6445965e233dded52a25ef5cea
Author:      Karl Valle
Email:       
Date:        2024-06-21T10:24:11Z
Fingerprint: 7fdddf4b0c36af6445965e233dded52a25ef5cea:shiny-secrets.py:private-key:14

Her ser vi at gitleaks finner to utfordringer i shiny-secrets.py filen. Legg merke til at gitleaks ikke detekterer noen utfordringer med filen api-key.txt. Hvis du gjør en print shiny-secrets.py vil du også se at api-nøkkelen forekommer to ganger i filen, men det er kun linje 8 som rapporteres som problematisk.

Det er greit å være klar over at man potensielt kan eksponere secrets selv om man har benyttet seg av flere tilgjengelige verktøy. Her handler det om å kjenne verktøyene sine og svakhetene i dem. Gitleaks rapporterer ikke api nøkkelen på linje XX i koden ettersom at den ikke er definert som en variabel. Hvis man lagt inn en API nøkkel i en kommentar eller sakset den inn i koden uten å tilordne den til en variabel, er det ikke sikkert at verktøyet du benytter klarer å detektere at det er en API nøkkel.

.gitignore – hvordan brukes den?

Den korrekte måten å benytte secrets i koden er selvsagt å deklarere dem i egne filer og referere til disse filene i koden når vi trenger nøklene. Disse filene vil vi selvsagt unngå å laste opp i vårt repository. Da refererer vi til filene i .gitignore. Vi kan også illustrere feil bruk av gitignore filen. La oss prøve å legge inn noen secrets i .gitignore filen for å se hvordan gitleaks behandler den.

shiny-secrets % cat .gitignore 
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDatt+BA9
n06PgkmJ5sZEJ9AAAAGAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIEUJSQ/swQ5m1Jnk
6yRVS3e3q/FIZQ4lgOzb3ADn57DYAAAAoFV6lLP6kCl2HrUUB4piiV96zTwtq3M5smy/Nt
zVicrzw/XXGuPNPdgkBUWkOE+2wnyLuaEg81x0PLnAHofgfsHFpnsMubiPF7rKA2YOOorM
IMYN6DeK3Gk/sCGVO0Ghf9NDLmM5azru/4suds1Hc06yTsoe0tkx7FFwkfMLBr9OQIosbO
yIqQTsaUMUd68Af0fUc+9aAMjK7mclZ756ie0=
-----END OPENSSH PRIVATE KEY----

"localAPI-Key": "8ugS5gDLVzKDHRez0QwLgKLXX369TJNKegMslrMwAPGHn30kUHajRv2N91L8kvxMwc9mvoATPgsoy7hiBAtkAOb0QIayDlTysSAOwPHb5aACFP5egmYeru7c5pmzLITn"

Vi kjører gitleaks detect -v for å avdekke om vi har noe rusk i .gitignore filen.

shiny-secrets % gitleaks detect -v

    ○
    │╲
    │ ○
    ○ ░
    ░    gitleaks

Finding:     "localAPI-Key": "8ugS5gDLVzKDHRez0QwLgKLXX369TJNKegMslrMwAPGHn30kUHajRv2N91L8kvxMwc9mvoATPgsoy7hiBAtkAOb0QIayDlTysSAO..."
Secret:      8ugS5gDLVzKDHRez0QwLgKLXX369TJNKegMslrMwAPGHn30kUHajRv2N91L8kvxMwc9mvoATPgsoy7hiBAtkAOb0QIayDlTysSAO...
RuleID:      generic-api-key
Entropy:     5.580564
File:        shiny-secrets.py
Line:        8
Commit:      7fdddf4b0c36af6445965e233dded52a25ef5cea
Author:      Karl Valle
Email:       
Date:        2024-06-21T10:24:11Z
Fingerprint: 7fdddf4b0c36af6445965e233dded52a25ef5cea:shiny-secrets.py:generic-api-key:8

Finding:     -----BEGIN OPENSSH PRIVATE KEY-----                                
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDa...
Secret:      -----BEGIN OPENSSH PRIVATE KEY-----                                
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDa...
RuleID:      private-key
Entropy:     5.733593
File:        shiny-secrets.py
Line:        14
Commit:      7fdddf4b0c36af6445965e233dded52a25ef5cea
Author:      Karl Valle
Email:       
Date:        2024-06-21T10:24:11Z
Fingerprint: 7fdddf4b0c36af6445965e233dded52a25ef5cea:shiny-secrets.py:private-key:14

1:09PM INF 3 commits scanned.
1:09PM INF scan completed in 20.8ms
1:09PM WRN leaks found: 2

Fremdeles bare de to originale funnene. Det betyr at tabben vår i .gitignore vil lastes opp til github ved neste push. Her burde jeg selvsagt lagt mine nøkler i egne filer, og heller referert til dem i .gitignore slik at filene ikke lastes opp ved neste anledning.

Gitleaks kan også benyttes til å kjøre en pre-commit hook som vil teste koden din før en commit – hvis man ønsker det.

Lab – Trufflehog

Vi tar en rask titt på trufflehog som et alternativ til Gitleaks. Trufflehog kan installeres i en docker container eller gjennom brew. Se trufflehog sin README.md for hva som passer ditt miljø best.

Vi gjør en enkel scan av mitt repository.

shiny-secrets % trufflehog git https://github.com/karltehgreat/shiny-secrets
🐷🔑🐷  TruffleHog. Unearth your secrets. 🐷🔑🐷

2024-07-08T11:47:35+02:00       info-0  trufflehog      running source  {"source_manager_worker_id": "9nQ4X", "with_units": true}
2024-07-08T11:47:35+02:00       info-0  trufflehog      scanning repo   {"source_manager_worker_id": "9nQ4X", "unit": "/var/folders/42/fhl81d7d3qx5xnmlt85ryvgc0000gn/T/trufflehog-83252-1724173974", "unit_kind": "dir", "repo": "https://github.com/karltehgreat/shiny-secrets"}
2024-07-08T11:48:13+02:00       info-0  trufflehog      finished scanning       {"chunks": 6, "bytes": 1676, "verified_secrets": 0, "unverified_secrets": 0, "scan_duration": "39.073540667s", "trufflehog_version": "3.79.0"}

Dette ser ikke helt lovende ut. Vi vet jo at det ligger både en API-nøkkel, og en privat-nøkkel eksponert i mitt repository. La oss prøve å scanne filene lokalt på maskinen.

shiny-secrets % trufflehog filesystem ./
🐷🔑🐷  TruffleHog. Unearth your secrets. 🐷🔑🐷

2024-07-08T11:49:35+02:00       info-0  trufflehog      running source  {"source_manager_worker_id": "JJU62", "with_units": true}
2024-07-08T11:50:15+02:00       info-0  trufflehog      finished scanning       {"chunks": 60, "bytes": 34901, "verified_secrets": 0, "unverified_secrets": 0, "scan_duration": "39.256069417s", "trufflehog_version": "3.79.0"}

Fremdeles ingenting. Etter litt fundering fant jeg følgende issue. En bug som gjør at private-keys ikke detekteres. Dette illustrerer igjen viktigheten av å kjenne sine verktøy, samt aktivt følge med på oppdukkende utfordringer med de aktuelle produktene man velger å benytte seg av.

Trufflehog har mange bruksmønstre, og er et populært verktøy. Samtidig har det også noen fallgruver man bør være bevisst på. Et godt eksempel er deteksjon av hardkodede brukernavn og passord. Trufflehog støtter ikke dette «rett ut av boksen», men man kan skrive regex regler for den typen deteksjon om ønskelig. Les gjerne mer om det her.

Oppsummering av secret scanning

Jeg håper at leseren sitter igjen med en bedre forståelse for hva secret scanning er, og hvorfor du og din bedrift bør ta et aktivt standpunkt til hvordan dere håndterer secrets i deres kildekode.

Det finnes mange måter å sikre egen kode på, og det som fungerer for deg er ikke nødvendigvis beste løsning for naboen, men gjennom en aktiv bevisstgjøring i teamet, og erfaringsutveksling mellom utviklerne vil man forhåpentlig finne en løsning som fungerer godt.