Titelkort för "Säkerhetsgranskning av kod förklarad" som visar en koddiffpanel med en ursprunglig och en ändrad rad, och tre märkta steg under den: MÖNSTER (deterministisk), sedan PASS, sedan RESONEMANG (modell).
Guides & Insights

Säkerhetsgranskning av kod förklarad: Vad en granskare letar efter i en diff, och varför

Författare

Rowan Sterling

Publiceringsdatum

Senaste modellerna · 20Visa alla modeller →
Benchmarks: Artificial Analysis · uppdateras dagligen
Tillbaka till alla inlägg

En säkerhetskodgranskning är den avsiktliga läsningen av källkod i det specifika syftet att hitta sätt på vilka den kan fås att göra något som dess författare inte avsåg. Den definitionen låter självklar tills man jämför den med vad de flesta team faktiskt kör, vilket är en funktionell granskning med en säkerhetschecklista nära till hands. OWASP Secure Code Review Cheat Sheet drar gränsen exakt: en säkerhetsgranskning skiljer sig från en funktionell granskning genom att inrikta sig på indatavalidering, autentisering, auktorisering, kryptografisk implementering och attackvektorer, i stället för på korrekthet. En diff som fungerar perfekt kan fortfarande ge en angripare en väg in i systemet, och bara en av dessa två granskningar letar efter det.

Det som gör ämnet värt en artikel nu snarare än 2020 är att en språkmodell kan läsa en diff kompetent, billigt och kontinuerligt – vilket förändrar ekonomin i granskningen utan att ändra en enda av de dimensioner som granskas. Checklistan är äldre än modellerna och har inte rört sig. Det som har förändrats är hur ofta du har råd att köra den.

Vad en granskare egentligen letar efter när den läser

OWASP:s cheat sheet organiserar arbetet i sex områden, och det användbara med listan är att varje område är en fråga snarare än en kategori. Kategorier inbjuder till avbockning; frågor leder till fynd.

Card 'What a reviewer is actually looking for' listing six dimensions - input and injection, authn and session, authorization, cryptography, business logic, configuration and secrets - each with the question it answers about a diff.

Indata och injektion. Frågan är inte huruvida koden har en sanitizer; det är huruvida något når en tolk – shell, SQL, mallmotor, uttrycksevaluator – och på vilket lager det kravet förväntas upprätthållas. En diff som lägger till en parameteriserad fråga är bra; en diff som lägger till en parameteriserad fråga i en funktion vars övriga anropare skickar råa strängar är en diff som har flyttat problemet.

Autentisering och session. Vem är anroparen, och hur fastställde koden det? Det återkommande felet är inte en trasig lösenordskontroll, det är en session som överlever en behörighetsändring – en upphöjning sker, token behåller sina gamla anspråk, och en timme senare finns behörigheterna fortfarande kvar.

Auktorisering. Objektnivåkontroller, varje gång, på varje rutt. Det specifika att leta efter i en diff är en ny rutt som inte ärver den skyddsfunktion som dess syskonrutter har, eftersom middleware registreras per router och en rutt som läggs till under en annan router helt enkelt inte täcks.

Kryptografi.Primitiv, läge, nyckellängd och var nyckeln finns. Två frågor fångar de flesta verkliga fynd: kan någon som kan läsa den här kodbasen också läsa nyckeln, och är den här jämförelsen en sådan som inte får läcka timing.

Affärslogik. Huruvida sekvensen kan ordnas om, spelas upp igen eller styras av värden som klienten valde. Ett pris, en kvantitet, en roll eller en tillståndsövergång som kommer från klienten och inte härleds på nytt på serversidan utgör ett fynd oavsett hur den valideras.

Konfiguration och hemligheter. Vad diffen levererar som aldrig borde ha funnits i ett repository, och huruvida standardvärdena är säkra där koden faktiskt körs. En debugflagga som är true som standard är en iakttagelse om produktion, inte om flaggan.

Baslinjegranskning kontra diffgranskning

OWASP skiljer mellan två lägen, och att blanda ihop dem är en vanlig orsak till både slöseri med ansträngningar och falsk trygghet. En baslinjegranskning granskar kodbasen heltäckande, och den är rätt verktyg för en ny applikation eller en större utgåva, för att introducera ett äldre system, för att uppfylla ett efterlevnadskrav eller för att göra analysen efter en incident när något redan har gått fel. En diffbaserad granskning tittar bara på det som har ändrats, och den är rätt verktyg för pull requests, commits, färdigställande av funktioner och kontinuerlig validering.

Åtskillnaden spelar roll eftersom de två leder till olika arbete. En baslinjegranskning slutar med en backlog; en diffgranskning slutar med ett sammanslagningsbeslut. Att köra den första kontinuerligt är oöverkomligt, och att köra den andra på en kodbas som aldrig har haft den första är hur team samlar på sig en falsk känsla av täckning: varje ändring passerar granskning, och den befintliga SQL-konkatineringen ligger där orörd.

Screenshot of the OWASP Cheat Sheet Series index entry for Secure Code Review, showing the introduction describing manual examination of source code for vulnerabilities automated tools miss, the baseline-versus-diff review split with their use cases, and a table of contents covering methodology, patterns, techniques, checklists and tools.

Tekniker och vad var och en fångar

OWASP listar fyra granskningstekniker, och de skiljer sig åt genom vilka bevis granskaren följer snarare än genom hur grundliga de är. Kodmönsteranalys följer välbekanta mönster: det farliga funktionsanropet, deserialiseringen av obetrodd indata, den saknade längdkontrollen. Det går snabbt och är precis vad ett deterministiskt verktyg gör bra. Dataflödesanalys följer ett värde från där det kommer in till där det används, vilket är det enda sättet att svara på om saneringsfunktionen som tillämpades tre funktioner tidigare fortfarande gäller här. Hotbaserad granskning utgår från en angripares förmåga och arbetar framåt, vilket är hur man fångar gapet mellan två var för sig korrekta komponenter. Granskning av affärslogik läser arbetsflödet i stället för raderna och frågar vilken sekvens av legitima operationer som producerar ett otillåtet tillstånd.

Endast den första av dessa fyra hanteras väl av en skanner, och endast den första och andra hanteras väl av en ostyrd modellgenomgång. Det är inte ett argument mot modeller; det är ett argument för att berätta för granskaren vilken teknik du vill ha, eftersom en prompt som ber om "säkerhetsproblem" tillförlitligt kommer att producera mönsteranalys och sedan stanna.

Vad AI förändrade – och vad det inte förändrade

Forskning om AI-författad kod gjorde granskningsflaskhalsen skarpare i stället för att skapa den. NYU-studien av GitHub Copilot-förslag, publicerad vid IEEE S&P 2022, fann att ungefär 40 % av genererade kodavsnitt innehöll ett exploaterbart mönster inom 18 CWE-kategorier. Stanford-arbetet om utvecklarbeteende, publicerat vid ACM CCS 2023, fann den mer betydelsefulla effekten: utvecklare som använde assistenter var mer övertygade om att deras kod var säker samtidigt som de producerade mätbart mindre säker kod. Mer output plus mer självförtroende är ett granskningsproblem.

En språkmodell som granskare ändrar en variabel i den ekvationen – genomströmning. Den kan läsa varje pull request, till en kostnad per token i stället för per användare, och den kan uttryckligen ställas de sex frågorna ovan. Den ändrar inte frågorna, och den får inte de två egenskaper som gör en granskning pålitlig: determinism och förmågan att köra koden. Samma diff som granskas två gånger kan ge olika fynd, allvarlighetsgrader förskjuts mellan körningar, och granskaren kan inte bevisa att en flaggad sökväg är nåbar.

Screenshot of the OrcaCode Review product page on OrcaRouter headed 'Open engine. Open prompt. Open bill.', describing a pull-request reviewer whose rules and merge gate run on GitHub under an MIT licence and are billed per token, with an example finding about an idempotency key that still varies in time.

OrcaCode Review är den produktifierade formen av den idén, och den är värd att titta närmare på eftersom designvalen avslöjar felmoderna. En granskning som isolerar det felande fallet som en specifik, reproducerbar kommentar – den här nyckeln varierar fortfarande över tid, så en debitering som försöks igen skapar en ny nyckel och kan leda till dubbeldebitering, här är ändringen på en rad – gör det jobb som en granskare gör. En granskning som rapporterar "potentiellt säkerhetsproblem" utan en reproduktion ägnar sig åt mönsteranalys med sämre precision än mönstermatcharen. Och en regel- och grindmotor som publiceras under en öppen licens gör ett implicit påstående som är värt att granska: att även granskarens bedömning bör vara granskningsbar.

Det tvåskiktade arrangemanget som fungerar

Med en deterministisk skanner och en probabilistisk granskare är det upplägg som håller i praktiken att ge var och en det arbete som den faktiskt är bra på. Skannern körs vid varje push: sekunder, ingen modell, ingen varians, fångar hemligheter, farliga API-anrop, osäker deserialisering och hallucinerade importer. Granskaren körs vid varje pull request: minuter, modellbaserad, fångar logiken mellan raderna – om auktoriseringskontrollen körs före hämtningen, om idempotensnyckeln är bunden till ett stabilt värde, om den nya rutten ärvde skyddet.

Sedan kommer lagret som folk hoppar över: grinden. Ett fynd som inte blockerar en merge är en avisering, och aviseringar läses på fredagar. Grinden måste vara smal och den måste vara absolut — kritiska fynd blockerar, allt annat kommenteras — och undantaget måste skrivas ned, eftersom värdet av en grind inte är att den stoppar det första fyndet utan att den gör varje kringgående synligt.

Granskar ändringen, inte kodbasen

Den praktiska disciplinen för en diffgranskning är en kort sekvens, och dess värde är att den kan läras ut på en eftermiddag. Läs diffen utifrån vad den tillför attackytan snarare än utifrån vad den ändrar. För varje ny ingångspunkt, följ indatan ett steg förbi där diffen slutar — sårbarheten finns vanligtvis i funktionen den anropar, som författaren inte har läst. För varje ny rutt, kontrollera skyddsregistreringen. För varje nytt beroende, kontrollera om det finns och om någon annan har publicerat namnet. För varje nytt konfigurationsvärde, fråga vad det har för standardvärde där det faktiskt kommer att driftsättas.

Inget av det kräver att man kan språket väl, vilket är anledningen till att det skalar till granskare som inte är säkerhetsspecialister. Det kräver dock att granskaren ser diffen i stället för filen, eftersom hela metoden bygger på att veta vad som är nytt.

Och den ärliga begränsningen: en diffgranskning kan inte hitta den brist som fanns där före diffen. Om applikationen aldrig har haft en baslinjegranskning är det säkerhetsarbete med högst värde som finns att tillgå inte en bättre granskare — det är en avsiktlig genomgång av kodbasen, inom de områden som rör pengar, identitet och filåtkomst, med de sex frågorna ovan. Efter det skyddar varje efterföljande diffgranskning något som har granskats en gång. Före det skyddar varje diffgranskning något okänt.