Buffer overflow (HowTo)

14 отговора 745 прегледа
#1

Buffer overflow (HowTo)

Постоянно чувам за Buffer Overflow бъгове в разни програми.
Та въпроса ми е следният:
Как да предпазя собственият си код от такива бугове?
Сещам се само за input checking...
Има ли нещо друго?
Който знае да си признава...

Отговор
в отговор на star(old) #2

Re: Buffer overflow (HowTo)

Ако допуснем, че питаш за Visual C++, защото никъде не става ясно, бих ти препоръчал да видиш в MSDN какво пише за StringCbPrintf(), StringCchPrintf() и т.н. - това са заместители на много често използваните sprintf(), wsprintf() и т.н.

Лично аз не съм ги ползвал, но в описанието на wsprintf() например, има хващащо окото каренце със Security Alert - Micro$oft предупреждават, че тези функции могат да доведат до сериозни проблеми .

Always Outnumbered - Never Outgunned
Отговор
в отговор на star(old) #3

Re: Buffer overflow (HowTo)

Ами зависи за конкретния буфер, но в общия случай нямаш шансове. Има специални методи за оразмеряване на буфери, но в тях винаги се работи с "вероятност за препълване".

Общата задача е все оная от шести клас: Един басейн се пълни през две тръби, едната с дебит А, другата с дебит Б. Празни се с кофи с обем В и честота Г. Гледаш да празниш по-бързо отколкото се пълни, и да не паднеш в басейна.

В свободен превод, разбирай: Имаш памет която се пълни през DMA-то едновременно по модем със скорост А и LAN със скорост Б, обработваш блокове с дължена В през време Г. Гледаш да празниш по-бързо отколкото се пълни, и да нямаш бъгове.

Толкоз. Единственият начин да нямаш опасност от buffer overflow е като нямаш буфер. Иначе винаги има вероятност да забравиш да се изпразниш навреме.

Мечтата е мисъл, мисълта е идея, всяка идея се реализира. Аз не мечтая, а реализирам идеите си.
Отговор
в отговор на Duncan Griffin #4

Re: Buffer overflow (HowTo)

Или се майтапиш, или нямаш никаква представа за какво говориш. Да предположим, че искаш потребителя да въведе стринг. Сравни:
char *gets (char *s); /* опасна функция */
със
char *fgets (char *s, int n, FILE *stream); /* безопасна функция */

В първия случай не си предвидил, че някой ще ти вкара повече символи отколкото си заделил за буфера, ще ти помаже стека и ако ги е изчислил добре, ще си изпълни каквото пожелае.

Във втория случай си задал колко най-много да се помести в буфера и ако лузърът се опитва да ти направи paste на 10 MB в полето за името му, просто няма шанс.

Колко бързо някой ще тропа по клавиатурата е без всякакво значение.

Същото се отнася за strcpy/strncpy, sprintf/snprintf и пр. Когато входът е отвън, трябва да приемеш, че може и да не са "добрите" от другата страна.

Отговор
в отговор на star(old) #5

Re: Buffer overflow (HowTo)

Ще ти предложа да прочетеш една отлична книга - "Как да пишем надеждни програми на C" на Стив Магуайър. Издадена е на български през 1993г. Макар че не е много нова, книгата е изключително актуална и то не само за програмистите на С/С++. Книгата е практически насочена, с много примери, в систематизиран и стегнат стил и за сравнително неголемия си обем от нея могат да се почерпят много знания и опит.

Отговор
в отговор на star(old) #6

StackGuard

Povecheto exploiti izpolzwat fakta che dosta buferi sa wuw steka kojto se izpolzwa i za lokalnite promenlivi i za adresa na wrushtane ot podprogramata (ili funckiata). Da lazhem imash


int test( char *src )
{
char buf[ 200 ];
while( *src ) *buf++=*src++;
}


Tuj kato steka "raste" nadolu. To preminawajki zad 200-nia simwol na buf (ili zad poslednia za kojto e otdelena pamet (ako e alignata)) - to direktno otivash tam kudeto e zapisan adresa za wrushtane ot test() (wse pak zawisi ot arhitekturata, kompilatora i tipa na wikane po razlichen nachin se zapiswa).

Prosto ideata tuka e da slozhish svoi danni (ot src) wuw buf s namerenieto da namazhesh return addressa.

Taka ili inache tova si e bugav kod, i ne e pravilno napisan - no ima sumati takuv. I problema ne e bil chesto tova dali programata shte raboti pravilno ili ne - ami dali njakoi njama da wzeme kontrol wurhu neja (da kazhem e nekakuv mail server).

Edin variant da se spasish ot tova e StackGuard.

StackGuard-a prosto e tehnika kojato slaga edin magicheski UINT32 ili UINT64. Da kazhem neka stoinostta e 'COOK' (ot cookie). Edinstwenoto koeto sega kompilatora trjabwa da napravi e da generira kod kojto da zapishe COOKIETO (magicheskata duima) sled return address (t.e. predi nego tuj kato steka raste nadolu) i wuw EPILOGUE chastta na funckiata (tova e chastta kojato podgotwja izlizaneto ot funckiata - t.e. wrushtane ot podprograma) da proveri dali sudurzhanieto na tova COOKIE e sushtoto (t.e. dali e 'COOK').

Razbira se mozhe da se izluzhe i tozi metod kato prosto exploita pravi taka che da izluzhe i cookieto (kato slaga 'COOK' wutre). Za tova po-dobur nachin e da se generira dadeno chislo - basirano da kazhem na tekushtia adress na steka - i po-kusno da se proveri dali e sushtoto.

Za poveche info potursi w google StackGuard.

MSVC7 naprimer ima StackGuard i dori imashe nekakuv spor che sa slozhili tazi tehnologia wutre bez da pitat originalnia avtor (toj e izplolzwal gcc, ne msvc za da probva ideite si).

ta tova.

Inache naj-dobre e kakto ti kazaha drugite da izpolzwash safe string ili buffer funckiite

snprintf a ne sprintf
strncpy a ne strcpy

i prochie da ne pishesh kod kato gore posochenia (wupreki che e burzo reshenie)

i wse pak ako securityto ne e na kritika, a razmera na koda ili skorostta sa - to togava ne se pritesnjawaj da polzwash i "po-loshite" funckiii.

Редактирано от malkia на

Отговор
в отговор на star(old) #7

Re: Buffer overflow (HowTo)

Благодаря за бързите отговори :)
Не казах какво използвам, щото си мислех че няма значение, нали само принципи ми трябваха... Ама все пак ползвам Делфи.
Сигурно трябваше тоя постинг да е в онзи клуб, ама вече се почна тук.

Та ако можете да ми кажете каквъв е риска за програма писана на Делфи да бъде атакувана чрез препълване-на-буфер принципа.
Където във формата ми има да се попълва текст, съм сетнал "max length"...
Притеснението ми идва само от, хмм "array of".

И още нещо...
Сигурно много смешно ви звучи, но нямам идея как да си направя един QA тест на проектчето... Няма ли някакъв инструмент, линк...

Отговор
в отговор на star(old) #8

Re: Buffer overflow (HowTo)

май, никой не го засегна този въпрос.
съвсем прав си, че вероятността за препълване на буфера е различна при различните езици.
в С/С++ където масивите са просто указатели, тя е значително по-голяма, отколкото в езици, където се пази информация за границите на масива.
във втория случай при опит за работа с данни извън границите, възниква exception или run time error.
все пак, в езици където има указатели, винаги е възможно да помажеш паметта.
подобен номер може да ти изиграе и включването на различни оптимизации.

та в заключение, в делфи можеш да избегнеш някои от най-идиотските начини за омазване на паметта, обаче не си 100% застрахован.

Отговор
в отговор на star(old) #9

Re: Buffer overflow (HowTo)

Та ако можете да ми кажете каквъв е риска за програма писана на Делфи да бъде атакувана чрез препълване-на-буфер принципа.
Където във формата ми има да се попълва текст, съм сетнал "max length"...


Ako govorim za ataka i za GUI prilozhenie to malko nejasno stava. Kakvo imash predvid tuka pod ataka? Taka ili inache ako njakoi ti ima EXE-to mozhe da naburka prilozhenieto ti i da go atakuva (razbiwane na paroli?)

T.e. wuprosa e kakvo tzelish sus tova da se predpazish ot buffer-overflow:
1. Zashtitata ot ataka pri koeto ako budesh atakuvan prilozhenieto ti wednaga raportuwa ili da izelze
2. Zashtitata ot nevalidni danni ili potrebitelski whod? Kato tzelta e prosto prilozhenieto ti nikoga da ne blockirwa ili krashwa.

objasni purwo molja

Отговор
в отговор на RunX #10

Re: Buffer overflow (HowTo)

Ще ти предложа да прочетеш една отлична книга - "Как да пишем надеждни програми на C" на Стив Магуайър. Издадена е на български през 1993г. Макар че не е много нова, книгата е изключително актуална и то не само за програмистите на С/С++. Книгата е практически насочена, с много примери, в систематизиран и стегнат стил и за сравнително неголемия си обем от нея могат да се почерпят много знания и опит.

Книгата наистина е добра. Само да не беше унгарската нотация, пуста да опустее...

Отговор
в отговор на star(old) #11

Re: Buffer overflow (HowTo)

Понеже си под win32 имаш голямо разнообразие от възможности.
Предполагам, че работиш в/у някакво секюрити приложение (напр. firewall), което е от критично значение. Страх те е от злостни хакери, които могат да ти крашнат програмата, насипвайки й и някво количество данни, клонящо към +безкр., с тайната надежда някой от буферите вътре да се препълни и програмчето да изгърми.

Първото, всеизвестно и универсално правило е да не се ползват буфери с твърдо зададен размер (статични). Това е много критична точка, особено когато трябва да се въвеждат username/password. Изключение се допуска само в случаите, в които си абсолютно сигурен, че размера на данните няма да надхвърли дадена максимална стойност (напр. при работа с низови полета в БД, работа с файловата система и т.н.).
След това, ако буферът ти идва като параметър и трябва да го пълниш, пък дори и да четеш от него, е добре да се проверява за права на запис/четене с ф-иите IsBadWritePtr() и IsBadReadPtr().
После идва try-catch блока в обработващата ф-я.
И накрая един глобален try-catch блок в main() ф-ята.

Я вышел им наперерез!
Отговор
в отговор на star(old) #12

Re: Buffer overflow (HowTo)

Ако говорим за C++ - може би най-добре е да се мисли не просто за буфер, а за концепция за буфер. Може би е добре тази функционалност (за буфер-а) да се капсулира в клас. И вече в самия клас да дефинираш операции по проверка за край, копиране, максимална дължина и т.н......

Отговор
в отговор на hoopla #13

Re: Buffer overflow (HowTo)

Имам отлична представа за какво говоря, и изобщо не се бъзикам. Просто въпроса беше поставен по много общ начин - как можеш да се предпазиш от препълване на буфер. Отговорът е, че в общия случай не можеш. Не ти говоря за clipboard, не ти говоря за буфер на клавиатурата, не ти говоря за буфера на UART, а ти говоря за общия случай.

Формулите за които говоря са от теория на опашките (в превод от Queueing theory, или Wartenschlangetheorie), на български преведена като "Системи за масово обслужване". Тази теория се занимава именно с това, колко аджеба памет ти трябва. Защото при препълване, последният ти проблем е това че калпав код блокира. Главния проблем е, че следващите данни няма къде да идат и съответно си отиват. От там имаш загуба на данни, връщане на пакети и т.н.

Как смяташ са определени големините на буферите по принцип? Именно със задачата за басейна, като се отчете вероятността да закъснее обработването на постъпилата информация. Такава вероятност винаги има, когато примерно старите (а и по-новите) CD-ROM устройства вдигнат флаг за прекъсване, и след това се окаже че трябва пак да врътнат диска щото забравили да прочетат нещичко. Какво следва?

- Процесорът не може да приключи прекъсването
- Модемът (примерно) пълни данни през DMA
- Буферът се напълва, CD-то още чете
- Overflow, чекай малко
- CD-то още чете
- Overflow, чекай чекай малко
- CD-то още чете
- Too many errors. Цък.
- CD-то още чете
- NO CARRIER.
- Automatic run........ what do you wanna start?
- Dialing.....

Примерно.

Просто въпросът беше как да се предпазиш от препълване на буфер. Отговорът е, че трябва да обработваш заявките по-бързо отколкото те постъпват, но и това не е гаранция, защото дори да имаш 42 мегабайта буфер, цикъла си е цикъл, влезеш ли в безкраен такъв рано или късно буфера се напълва. Това, че при препълване програмата не трябва да ти направи izception, е вече друг въпрос.

Мечтата е мисъл, мисълта е идея, всяка идея се реализира. Аз не мечтая, а реализирам идеите си.
Отговор
в отговор на Duncan Griffin #14

Re: Buffer overflow (HowTo)

Отговорът е, че в общия случай не можеш.

Можеш. Виж какво съм писал по-горе.

Защото при препълване, последният ти проблем е това че калпав код блокира.

"Блокира" на калпава ОС. Стандартния случай е процеса просто да се ликвидира.

Главния проблем е, че следващите данни няма къде да идат и съответно си отиват.

Човека това не го грее. Иска да се предпази от преднамерено убиване на програмата му чрез препълване на някой от буферите вътре. (Виж по-горе)

Това, че при препълване програмата не трябва да ти направи izception, е вече друг въпрос.

Пише се exception, но както и да е. Exception-ните са си много хубаво нещо, както написах по-горе е добър метод да си предпазиш програмата от ликвидиране при опит за запис в област от паметта, дето нямаш право.

Я вышел им наперерез!
Отговор
в отговор на Resurrector #15

Re: Buffer overflow (HowTo)

Аз ти говоря за общ случай, ти ми говориш за операционна система. Говоря ти за теория на опашките, ти ми говориш за win32. Как да се разберем?

Интересно ми е тоя динамичен буфер как ще го разшириш като ти свърши RAMa? Виртуална памет докато ти свърши харда. После перфолента ли ще ползваш?

Блокирането не го коментирам, казах че ти е последния проблем, затова изобщо не съм уточнявал ОС.

Относно убиването на програмата, казах че е друг въпрос дали ще е написана достатъчно добре.

И благодаря, че ми каза, че се пише exception. Никога не бях го чувал. Направо съм изумен как съм направил такава ИЗЦЕПКА.

Мечтата е мисъл, мисълта е идея, всяка идея се реализира. Аз не мечтая, а реализирам идеите си.
Отговор