Sårbarheder får Microsoft til at droppe udbredt funktionskald i C

Microsoft sender senere på året hukommelsesfunktionen memcpy() på pension. Funktionskaldet kunne udnyttes til hackerangreb.

Microsoft vil ikke længere leve med potentielle sikkerhedshuller i softwaren forårsaget af C-funktionen memcpy(). Derfor bliver funktionen føjet til listen over ?forbudte? C-funktioner senere på året, fremgår det af et indlæg på MSDN-bloggen The Security Development Lifecycle (SDL).

Funktionen memcpy() bruges til at kopiere et antal bytes mellem to ikke-overlappende områder i hukommelsen. Den er defineret i header-filen string.h i standardbiblioteket for programmeringssproget C.

Problemet med memcpy() - og flere andre funktionskald som for eksempel strcpy() og strcat() - er, at funktionerne kan give anledning til buffer overflow, hvilket kan udnyttes i hackerangreb.

Memcpy() får følgeskab af funktionerne CopyMemory() og RtlCopyMemory() og erstattes af funktionen memcpy_s(), der ikke skulle lide under samme sårbarhed.

»Fordi vi har set mange sårbarheder i sikkerheden i produkter fra Microsoft og mange andre, og fordi vi har en funktionsdygtig erstatning (memcpy_s(), red.), er jeg 'stolt' af at kunne annoncere, at vi tilsigter at tilføje memcpy() til listen senere på året,« lyder det på SDL-bloggen.

Der opfordres samtidig til, at alle udviklere sætter memcpy() stolen for døren og tilføjer følgende kode i fælles header-filer:

#pragma deprecated (memcpy, RtlCopyMemory, CopyMemory)

Programmøren vil så modtage følgende advarsel:

warning C4995: 'memcpy': name was marked as #pragma deprecated

Microsoft-udviklerne påpeger, at det er relativt smertefrit at skifte fra memcpy() til memcpy_s(). Den nye funktion tager et ekstra argument, som er størrelsen på destinationsbufferen. Dermed tvinges programmøren til at tænke over, hvor meget data skal kopieres hvorhen, hvilket skulle reducere risikoen for buffer overflows.

Blogindlægget på Security Development Lifecycle kan findes via det eksterne link herunder.

Tips og korrekturforslag til denne historie sendes til tip@version2.dk
Kommentarer (10)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
#1 Peter Valdemar Mørch

Fra "man 3 memcpy"

SYNOPSIS #include <string.h> void *memcpy(void *dest, const void *src, size_t n);

Det er den samme definition man finder i http://en.wikipedia.org/wiki/String.h hvor der står "string.h is the header in the C standard library for the C programming language"

Fra http://msdn.microsoft.com/en-us/library/dswaw1wk(VS.80).aspx har vi:

void *memcpy( void *dest, const void *src, size_t count );

"n" fra standarden hedder "count" i Windows, men der er stadig en størrelsesparameter med. (Hvor'n faen skulle den ellers kunne virke?)

Er der endnu en string.h og definition af memcpy under windows?

Hvordan kan dette give anledning til buffer overflow med mindre n/count er forkert?

Peter

  • 0
  • 0
#3 Torben Mogensen Blogger

... men C har stadig alt for mange sikkerhedshuller, der skyldes lageroperationer uden check.

C bør kun bruges til indlejret programmering, hvor programmøren skal have præcist styr på ressourceforbrug, og er villig til at være ekstra omhyggelig med sin kode for at sikre, at den ikke laver snavs. At bruge C til applikationsprogrammering (browsere, tekstbehandling, osv.) er en misforståelse. Sproget er ikke designet til det, og det ses tydeligt i dets totale uegnethed til dette formål.

  • 0
  • 0
#4 Poul-Henning Kamp Blogger

Problemet er at hardware folkene har fået lov til at køre løbet med at definere protection-architecture, helt uden hensyn til hvad der faktisk er brug for nu om dage.

Objecter bør være hardware-implementerede, således at den størrelse de nu en gang er givet, bliver håndhævet af hardwaren.

Ikke alene kan det lade sig gøre, det er blevet gjort:

http://en.wikipedia.org/wiki/Rekursiv

det er vejen frem, at bandlyse memcpy(3) er svarer til at beep'e grimme ord ud på TV.

Poul-Henning

  • 0
  • 0
#5 Jonas Finnemann Jensen

numberOfElements: Size of the destination buffer.

Okay, så nu kommer udviklerne til at tænke over om der rent faktisk også er plads til de bytes man vil kopier i dest... - Det er der jo ingen der har tænkt over før :)

Jeg er enig i at C ikke skal bruges til applikations udvikling... Men de steder hvor ydelse er kritisk eller man arbejde embedded, er C da et godt alternativ til assembler...

  • 0
  • 0
#6 Deleted User

Kopiering af memory direkte (uden type og intervalcheck), hører ikke til i et højniveau programmeringssprog. I stedet, skal man tillade de operationer, som programmørerne rent faktisk behøver - og sikre, at de såvel type som interval tjekker. Dette tjek, må aldrig gøres af programmøren ved hjælp af "sikker kodning", men skal gøres af compiler, således funktionerne kan flyttes til hardware uproblematisk, når det kommer - og uden software skal laves om. ADA - og selv pascal - er på flere måder bedre end C, med hensyn til kopiering. I pascal, kan du kopiere hele structs (records) og arrays, med tildelingsoperatoren :=. Dette, naturligvis under forudsætning af, at typerne er ens, så det kan tvinge til en opdeling i structs/records, som tager hensyn til det der er fornuftigt at kunne kopiere. I ADA kan du også kopiere en delarray, som standard i sproget - igen tjekkes for type, dog her kun for enkeltelementer. Det er meget vigtigt, at de kopieringsmuligheder som programmøren har brug for, er del af sproget, således de senere kan implementeres i hardware, når CPU'erne og ram kredsene får indbygget kopieringsmaskine. I hardware, er muligt at indbygge "kopieringsmaskiner", der kan kopiere ekstremt hurtigt med O(log(n)) hvor n er størrelsen af data der skal kopieres.

  • 0
  • 0
#7 Deleted User

Hvis programmøren ikke kan finde ud af at vælge den rigtige størelse når han kalder memcpy, hvad er så chancen for at han kan finde ud af det når han kalder memcpy_s?

Hvis MS vil gøre memcpy forbudt og kun stille memcpy_s til rådighed er løsningen jo åbenlys:

define memcpy(s1, s2, n) memcpy_s(s1, n, s2, n)
  • 0
  • 0
#8 Søren Dreijer

Hvis programmøren ikke kan finde ud af at vælge den rigtige størelse når han kalder memcpy, hvad er så chancen for at han kan finde ud af det når han kalder memcpy_s?

Det er jo netop det, at programmøren skal specificere størrelsen af den buffer, han kopierer ind i, der gør hele forskellen. På den måde bliver han tvunget til at overveje hvor meget data der kan blive proppet ind og om der egentlig er plads til det. Under alle omstændigheder vil der aldrig blive skrevet for meget i bufferen.

Hvis MS vil gøre memcpy forbudt og kun stille memcpy_s til rådighed er løsningen jo åbenlys:

define memcpy(s1, s2, n) memcpy_s(s1, n, s2, n)

Din "løsning" er ret uhyggelig. Du siger, at destinationsbufferen altid er stor nok til at indeholde det data, der bliver kopieret (dvs. n), hvilket jo netop er det memcpy_s() forsøger at få folk til at forstå ikke passer.

  • 0
  • 0
#9 Rasmus Nielsen

Selvfølgelig kan man gøre noget ved at indtænke nogle procedurer, som mindsker risikoen for fejl, men f.eks. at tvinge alle til at bruge memcpy_s i stedet for memcpy virker lidt mærkeligt.

En ting er at det ikke ville komme bag på mig hvis Anders Borchs definition ovenfor ender med at blive flittigt brugt, om ikke eksplicit, så inden i hovedet på diverse programmører.

Noget andet er at det er en styrke ved C, at det er op til programmøren at beslutte hvornår og hvor ofte parametre skal valideres. Som C-programmør ved man at de basale elementer i sproget som udgangspunkt er helt uden validering. Det må man så selv finde en strategi for. Den mest basale er at indføre en wrapper-funktion med ekstra check. memcpy_s er blot en sådan funktion.

  • 0
  • 0
#10 Rasmus Nielsen

At sige at C er uegnet til applikationsprogrammering er for mig at se en misforståelse, men det er rigtigt, at hvis man benytter C til applikationsprogrammering, så vil man i velskrevet kode sjældent se C funktioner benyttet direkte i applikationskoden.

Det er blot et spørgsmål om at opbygge et abstraktionslag, der understøtter det niveau man vil programmere på. Herefter programmeres applikationen uden unødvendige hensyn til resurser, der håndteres under abstraktionslaget.

I nogle tilfælde kan man finde et sprog, der allerede fra fødslen tilbyder et passende sæt abstraktioner, og så vil det være mere effektivt, men i andre tilfælde vil det være en fordel selv at kunne definere disse og at have mulighed for at gå ned i "maskinrummet" når det er nødvendigt. At C er ganske velegnet i dette tilfælde er grunden til at C er et ualmindeligt sejlivet sprog.

Med dette udgangspunkt synes jeg, at memcpy_s er overflødig som en standardfunktion i C.

  • 0
  • 0
Log ind eller Opret konto for at kommentere