char buffer[1024]; gets(buffer);Hint: hvilken informasjon mangler gets()?
/*****************************************************************************/ /* */ /* File: overflow1.c */ /* */ /*****************************************************************************/ #includemain() { char buffer[8]; printf("Please enter your name:"); scanf("%s",buffer); printf("Your name is: [%s]\n",buffer); Function1(); Function2(); } /*****************************************************************************/ Function1() { char buffer[100]; sprintf (buffer,"Mary had a little lamb whose fleece was white as /bin/sh BadScript ..."); printf("%.22s\n",buffer); } /*****************************************************************************/ Function2() { char buffer[50]; printf("Execute command %s\n",buffer); }
Please enter your name:abcdef Your name is: [abcdef] Mary had a little lamb Execute command /bin/sh BadScript ...Kan du forklare dette?
/*****************************************************************************/ /* */ /* File: overflow2.c */ /* */ /*****************************************************************************/ #includemain() { Function1(); Function2(); } /*****************************************************************************/ Function1() { char buffer[100]; scanf("%[^\n]",buffer); } /*****************************************************************************/ Function2() { char buffer[50]; printf("01234567890123456789001234567890012345678901234567890\n"); printf("Executing command %s\n",buffer); system (buffer); }
Et av de største hodepiner for programmerere som skriver interaktive programmer (inkludert klient-server systemer) er streams. Du har sikkert hørt om streamsbiblioteket for C++, men du må ikke tro at det er noe som ku gjelder for C++ eller sine biblioteker.
En stream eller datastrøm er en kontinuerlig foring av input/output som innholder flere data objekter. Lengden på datastrømmen er ukjent i utgangspunktet, men strømmen er terminert ved en EOF (end of file) markør. Overførsel av data ved hjelp av datastrømmer kan kontrastes med overførsel av datablokker av kjent antall og størrelse.
De bestkjente datastrømmene heter standard-in/stdin og standard-out/stdout. Det er vanligvis keyboard input og konsoll output. Hver gang vi ber en bruker om å skrive noe, åpner vi en kanal til tastaturstrømmen. Inputen avsluttes når brukeren taster ENTER.
Hensikten med denne ukens oppgaver er å kaste lys på noen av problemene omkring stream-programmering. Hvorfor er det vanskelig? Hvorfor er det en av de vanligste feilkildene i interaktivprogrammering. Vi kommer til å kode i både C og C++.
C C++
int a; int a;
scanf("%d",&a); cin >> a;
Disse er blant de vanskeligste og farligste funksjoner å beherske, av to grunner:
#include <stdio.h> #include <iostream>
main() main()
{ int a = 0; { int a = 0;
static char buffer[20] = "rm *"; static char buffer[20] = "rm *";
printf ("Enter [uid] [command]: "); cout << "Enter [uid] [command]: ";
scanf("%d %s",&a,buffer); cin >> a >> buffer;
printf("Okay, executing %s as user %d\n",buffer,a); cout << "Okay, executing " << buffer << " as user " << a << endl;
} }
Prøv å skrive inn følgende som input til programmet:
100 ls 100ls ls 100Kan du forklare resultatene? Anta at dette programmet var en server på en Unix maskin. Hva kunne skjedd i det siste tilfelle?
#include <iostream>
main()
{ char command[40]; // Send command to
int time_of_day; // Avoid replay attack?
cin >> time_of_day >> command;
cout << "Command was " << command << " at time " << time_of_day << endl;
}
og prøv programmet med følgende input:
13 report 13 shoot-to-kill 15 shoot only if they shoot first 12:00 fire
Anta nå at vi lager en løkke rundt dette for å hente ny ordrer, som i en server som lytter kontinuerlig:
#include <iostream>
main()
{ char command[40]; // Send command to
int time_of_day; // Avoid replay attack?
const bool ever = 1;
for ( ;ever; )
{
cin >> time_of_day >> command;
cout << "Command was " << command << " at time " << time_of_day << endl;
}
}
Prøv å taste inn den samme input som før. Ser du hvor lett det er
å utføre en denial of service angrep? Den samme feilen fantes i NT-4,
før Service Pack 2. Problemet er vanskelig å fikse med C++ streams-biblioteket,
men det er lett å fikse med C's I/O bibliotek.
#include <stdio.h>
#define ever 1
main()
{ char command[40]; // Send command to
int time_of_day; // Avoid replay attack?
for ( ;ever; )
{
scanf("%d %[^\n]",&time_of_day,command);
printf("Command %s at time %d\n",command,time_of_day);
}
}
Regulærutrykket %[^\n] matcher et objekt som
består av en hvilken som helst
sammensetning av tegn bortsett fra `end of line'. Dvs, dette matcher
alt fram til slutten av linjen.