Gå til innhold

Sikkerhetsissues - Finn og post eksempler


Anbefalte innlegg

Tenkte det kunne være moro med en sikkerhetstråd, der man poster og finner sikkerhetsissues i forskjellig kode.

Tanken er at man kan få litt hjernetrim, og samtidig kan andre lære av det. Språk valgfritt, men jo mer obskurt, jo mindre respons naturligvis :p

Starter lett med denne gamle C-klassikeren:

 

#include <string.h>
void foo (char *bar)
{
 char c[12];
 strcpy(c, bar);
}
int main(int argc, char* argv[])
{
 foo(argv[1]);
}

 

Hva er problematisk her?

Lenke til kommentar
Videoannonse
Annonse

Stackoverflow om argv[1] er > 12 bytes. I værste fall kan det føre til at man kan putte inn kjørbar kode inn på stacken og samtidig overskrive EIP-pekeren på stacken slik at den kaller koden du ga som input når funksjonen returnerer.

Lenke til kommentar

Riktig! Fyll gjerne på med eksempler om du har noen :)

 

Nok en sak fra C-verdenen:

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
int x, y, z=0x00000001;
char *table = NULL;
if(argc<2) _exit(1);
x=atoi(argv[1]);
if(x>0) {
  table = (char *)malloc(x * sizeof(char *));
  if(table == NULL) _exit(2);
}
for(y=0; y<x; y++)
  table[y]=z++;
for(y=0; y<x; y++)
  printf("tab[y]=0x%x\n", table[y]);
return 0;
}

Lenke til kommentar

Du mener så bortsett fra at den ene linjen skulle vært: table = (char *)malloc(x * sizeof(char)); ?

Sånn første øyekast er at x,y,z, er integere, mens tabellen er en char-table. og siden char ofte er 1 byte, og int 4 bytes så vil du hele tiden overskrive deler av tabellen hver gang du setter inn ting i den.

Lenke til kommentar

Du mener så bortsett fra at den ene linjen skulle vært: table = (char *)malloc(x * sizeof(char)); ?

Sånn første øyekast er at x,y,z, er integere, mens tabellen er en char-table. og siden char ofte er 1 byte (...)

 

sizeof(char) er definert til å være 1 byte (alltid). Derfor er det heller ikke nødvendig å skrive sizeof(char) i malloc().

Lenke til kommentar

sizeof(char) er definert til å være 1 byte (alltid). Derfor er det heller ikke nødvendig å skrive sizeof(char) i malloc().

men han skrev sizeof(char *), når det skulle være sizeof(char), som gjør at han i de fleste systemer setter av mye mer minne enn han trenger.
Lenke til kommentar

men han skrev sizeof(char *), når det skulle være sizeof(char), som gjør at han i de fleste systemer setter av mye mer minne enn han trenger.

Altså, slik jeg ser det (uten C-erfaring), så vil sizeof(char *) være størrelsen på adressen. Du vil da altså allokere 4 eller 8 byte (kommer ann på om det er 32 eller 64 bit OS)? :-)

Da ved å gjøre:

>>> table = (char *)malloc(x * sizeof(char *));

Så vil han allokere nok plass til en eller to 32bit-integers (4, eller 8 byte), men hvert element kan kun romme 8 bit, så resultatet er at han har allokert 4, eller 8 ganger så mange elementer/chars.

 

Edit: Fjernet litt tekst, da jeg tro jeg PLUTSELIG forsto noe (=

Endret av warpie
Lenke til kommentar

Dere er inne på noe, har med malloc'en å gjøre.

Hint: Hva skjer om man sender inn 1073741824 som argument?

 

Edit: Antar 32-bit kode i dette tilfellet, burde kanskje spesifisert det tidligere..

Endret av Paull
Lenke til kommentar

... Hva skjer om man sender inn 1073741824 som argument?

Summen du viser til er (2^31)/2 (eller 2^30), så summen er 30 bits, men størrelsen på hvert element i table er for liten - hendelse avhengig av hvordan C fungerer, men tenker noe slik:

Sett att hvert element er størrelsen av en char (8 bit), så vil vel summen bli redusert til max 255, kan tenke meg at kun de 3 første tallene vises: 107. Er usikker på om at tallet vil forsette inn i neste element, men det er irrelevant.

 

Men, jeg ser ikke hvorfor det er nødvendig å poengtere den mere, det er da ingen som får noen form for hjelp ved å lese dette. Det er klare FEIL i koden, hvorfor i all verden skulle en pakke 32 bit integer i en Char-array?

>>> int *table = NULL;

>>> ...

>>> table = (int *)malloc(x * sizeof(int));

Er vel korrekt, eller noe i den duren.

Endret av warpie
Lenke til kommentar

Greit nok, å endre fra char* til int* har egentlig ikke noe å si i dette tilfellet.

 

Poenget er i alle fall at multiplikasjonen x * sizeof(..) overflower. Siden både sizeof(char *) og sizeof(int) er 4 for 32-bit kode, så vil 1073741824 * 4 == 0. Dermed blir det malloc(0), som er implementasjonsavhengig og skumle ting skjer når man følger pekeren.

Poenget var i alle fall integer overflowen.

 

La oss se på litt Python:

def validate_password(actual_pw, typed_pw):
if len(actual_pw) <> len(typed_pw):
 return 0
for i in len(actual_pw):
 if actual_pw[i] <> typed_pw[i]:
  return 0
return 1

Endret av Paull
Lenke til kommentar

Altså, slik jeg ser det (uten C-erfaring), så vil sizeof(char *) være størrelsen på adressen. Du vil da altså allokere 4 eller 8 byte (kommer ann på om det er 32 eller 64 bit OS)? :-)

Da ved å gjøre:

>>> table = (char *)malloc(x * sizeof(char *));

Så vil han allokere nok plass til en eller to 32bit-integers (4, eller 8 byte), men hvert element kan kun romme 8 bit, så resultatet er at han har allokert 4, eller 8 ganger så mange elementer/chars.

Edit: Fjernet litt tekst, da jeg tro jeg PLUTSELIG forsto noe (=

Han prøver å lage et array av chars, hvor man ønsker adressen til det første elementet i arrayet. Siden det er et char-array er det størrelsen på chars * antall_elementer som er interesant, ikke å allokere av størrelsen på pekeren, det hadde i så fall vært et array med pekere (og altså da en dobbelt-peker merket med char **table)

videre vil det da si at siden det er merket som et char-array, så vil man ved dinne koden få uønsket oppførsel:

int x=10, y=20;
table[0] = x;
table[1] = y;
printf("%d %d\n", table[0], table[1]);

 

Jeg er litt usikker på detaljene på hva som vil skje der, har ikke testet selv akkurat nå - men var den første feilen jeg så som ville skape problemer. Men ser jo nå, etter det ble forklart, at det er helt klart integer-overflowen som er det kritiske problemet her.

 

Men om koden hadde gitt mening, altså man hadde brukt sizeof(char) i stede for sizeof(char *), så hadde ikke problemet eksistert.

 

Men la oss endre koden til noe som gir mening, la oss bruke en "int"-tabell i stede for chars.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
   int x, y, z=0x00000001;
   int *table = NULL;
   if(argc<2)
    return(1);
   x=atoi(argv[1]);
   if(x>0) {
    table = (int *)malloc(x * sizeof(int));
    if(table == NULL)
	    return(0);
   }

   for(y=0; y<x; y++)
    table[y]=z++;
   for(y=0; y<x; y++)
    printf("tab[y]=0x%x\n", table[y]);

   free(table);
   return(0);
}

 

Her vil du framprovosere en segmentation-fault i tilfellene hvor x*4 > int_max grunner integer overflow.

Endret av etse
  • Liker 1
Lenke til kommentar

men han skrev sizeof(char *), når det skulle være sizeof(char), som gjør at han i de fleste systemer setter av mye mer minne enn han trenger.

 

Desto større grunn å bruke den kanoniske:

 

T *ptr = malloc(N * sizeof *ptr);

 

... for en vilkårlig type T.

Lenke til kommentar

Verdens vanskeligste:

 

include($_GET[$file]);

?file=../../../../../../../../../etc/passwd

og man har plutselig litt større innsyn enn man burde i mange tilfeller.

?file=../../../../../../../etc/passwd%00

null-byte, oopps

?file=data://text/plain;base64lololololol=

om include_over_url eller hva det eheter er aktivert kan jeg selv velge koden som kjøres.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...