21
Page 1 of 21 Уязвимости в ядрото на Linux 2.4.x Доклад по дисциплината “Мрежова сигурност 2 – сигурен код” Факултет по Математика и Информатика Софийски Университет “Св. Климент Охридски” Летен семестър 2003/2004 година Георги Христов Георгиев ([email protected] ) фак. номер: 43447, II курс Информатика Александър Евгениев Илиев([email protected] ) фак. номер: 43381, II курс Информатика

Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

  • Upload
    others

  • View
    24

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 1 of 21

Уязвимости в ядрото на Linux 2.4.x

Доклад по дисциплината “Мрежова сигурност 2 – сигурен код”Факултет по Математика и Информатика

Софийски Университет “Св. Климент Охридски”Летен семестър 2003/2004 година

Георги Христов Георгиев ([email protected]) фак. номер: 43447, II курс Информатика

Александър Евгениев Илиев([email protected]) фак. номер: 43381, II курс Информатика

Page 2: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 2 of 21

Въведение ........................................................................................................................ стр. 3

1. Уязвимост в i2c драйвера позволява на локални потребители да добият...повишени права

стр. 3

2. Локален DoS чрез функция с вграден (inline) асемблер................................... стр. 4

3. Уязвимост в Linux Kernel STRNCPY. Възможно изтичане на.......................информация

стр. 6

4. SCTP_SetSockOpt Integer Overflow уязвимост................................................... стр. 6

5. Уязвимост в Linux Kernel Panic функцията от Buffer Overflow..................... стр. 8

6. Setsockopt MCAST_MSFILTER integer overflow................................................ стр. 9

7. Локална Sigqueue Blocking DoS уязвимост......................................................... стр. 10

8. do_mremap VMA уязвимост в увеличение на локалните права.................... стр. 10

9. Грешка при копирането на памет към ядрото в USB драйвера на Vicam... стр. 11

10. Уязвимост в Linux Kernel execve() при деформиран ELF файл води до........възможност от локален DoS

стр. 12

11. Локално повишаване на привилегиите чрез do_mremap().............................. стр. 12

12. Локална уязвимост в проверката на границите във функцията do_brk...... стр. 13

13. Уязвимост в XDR Packet Handler за NFSv3 водеща до отдалечен DoS.......... стр. 15

14. Грешка в '/proc/self' може да разкрие важна информация на локалния.......потребител

стр. 15

15. Чрез '/proc/tty/driver/serial' може да разкрие информация за паролите на...локалния потребител

стр. 16

16. Уязвимост в Linux Kernel FPU/SSE Environment Restoration MXCSR..........Register

стр. 16

17. Уязвимост в Linux Kernel Fragment Reassemble, която може да доведе до...отдалечен DoS

стр. 17

18. DoS поради проблеми в routing кеша................................................................... стр. 17

19. Грешка в ioperm() дава достъп на локални потребители до портове с..........ограничен достъп

стр. 18

20. Чрез ptrace() може локални потребители да се сдобият с root права............. стр. 19

21. Уязвимост в d_path() при прекалено дълги пътища (path) и тяхното...........отрязване

стр. 19

Page 3: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 3 of 21

Въведение:Този доклад е курсов проект на Георги Георгиев и Александър Илиев по

дисциплината “Мрежова Сигурност 2 – сигурен код”. Негова цел е да изброипоследните 20 (представяме ви 21) уязвимости в ядрото на Линукс версия 2.4.х – дапокаже проблемите, които могат да възникнат, да посочи причината за тезипроблеми и възможностите за тяхното разрешение. Опитали сме се да подберем по-съществени проблеми в ядрото на Линукс в периода 2002-2004.

Дата : 17 Юни 2004Наименование : Уязвимост в i2c драйвера позволява на локални потребители дадобият повишени праваТип : Грешка в проверка на границитеЗасегнато ядро : 2.4 до 2.4.20 и 2.5.х; незасегнати: 2.4.21 и нагоре, 2.6Резюме : В драйвера i2c има възможност за integer overflow, която да позволи налокален потребител да crash-не ядрото и да се сдобие с привилегии с нивото наядрото.Подробности : Има потенциална възможност от integer overflow, което може да сеслучи по време на алокиране на памет, при парсване на I2C_RDWR опцията вi2cdev_ioctl(). Ето и уязвимия код:

case I2C_RDWR:if (copy_from_user(&rdwr_arg, (struct i2c_rdwr_ioctl_data *)arg, sizeof(rdwr_arg)))

return -EFAULT;

rdwr_pa = (struct i2c_msg *) kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), GFP_KERNEL);

if (rdwr_pa == NULL) return -ENOMEM;

Поради липса на проверка, в аритметичната операция (rdwr_arg.nmsgs *sizeof(struct i2c_msg)) в kmalloc()може да възникне integer overflow и такада се задели прекалено малко памет. Понеже rdwr_arg.nmsgs е подаден отпотребителя, то при едно подходящо изчисление и съответната подадена стойност,може да се стигне до integer overflow.

След kmalloc() идва for() цикъл, който ползва copy_from_user, за дапопълни заделената памет, но поради integer overflow-а, подадената от потребителяинформация може да се запише извън прекалено малкото заделена памет.

Това са копиращите извиквания:

for( i=0; i<rdwr_arg.nmsgs; i++ ) {if(copy_from_user( &(rdwr_pa[i]), &(rdwr_arg.msgs[i]), sizeof(rdwr_pa[i]))) {

res = -EFAULT; break; }

rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);if(rdwr_pa[i].buf == NULL) {

res = -ENOMEM;

Page 4: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 4 of 21

break; }

if(copy_from_user(rdwr_pa[i].buf, rdwr_arg.msgs[i].buf, rdwr_pa[i].len)) {

[...]

Този бъг се намира в i2c драйвера, който е част от ядрата 2.4.20 и по-ранни,като също така и в 2.5.х.

Трябва да се отбележи, че повечето Линукс дистрибуции слагат 0600 правана /dev/i2c-* и така шансовете за експлоатиране на този проблем намаляват, тъйкато тези файлове са разрешени за четене и писане само от super-users. Също такатази проблем е само за системи с инсталирани такива драйвери.Опасност : Тази уязвимост позволява на атакуващия да изпълни код спривилегиите на драйвера, което потенциално води до опасност от повишаване направата и достъп до ring0.Решение: В I2C_RDWR опцията във функцията i2cdev_ioctl(), в i2c-dev.c може дасе добавят следните проверки за справяне с този проблем:

[...]

if(rdwr_arg.nmsgs > 42) rdwr_arg.nmsgs = 42;

if(rdwr_arg.nmsgs < 0) rdwr_arg.nmsgs = 0;

[...]

Препоръчва се обновяване до най-новите версии на ядрото.

Дата : 14 Юни 2004Наименование : Локален DoS чрез функция с вграден (inline) асемблерТип : Грешка в дизайнаЗасегнато ядро : всички от 2.4.18 до 2.6.6 (незасегнати: 2.4.19 и 2.6.7)Резюме : Грешка при FPU операциите може да доведе до зацикляне и забиване нацялата система чрез изпълнение на програма от локален потребител без специалниправа.Подробности : Изпълнение на следната програма под х86 и AMD64 води до този проблем:

#include <sys/time.h>#include <signal.h>#include <unistd.h>

static void Handler(int ignore){ char fpubuf[108]; __asm__ __volatile__ ("fsave %0\n" : : "m"(fpubuf));

Page 5: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 5 of 21

write(2, "*", 1); __asm__ __volatile__ ("frstor %0\n" : : "m"(fpubuf));}

int main(int argc, char *argv[]){ struct itimerval spec; signal(SIGALRM, Handler); spec.it_interval.tv_sec=0; spec.it_interval.tv_usec=100; spec.it_value.tv_sec=0; spec.it_value.tv_usec=100; setitimer(ITIMER_REAL, &spec, NULL); while(1) write(1, ".", 1);

return 0;}

Проблемът е в макросът clear_fpu в include/asm-i386/i387.h и това е поправенатаверсия:

--- 1.15/include/asm-i386/i387.h 2004-06-22 14:04:33 -07:00+++ 1.16/include/asm-i386/i387.h 2004-06-22 14:04:33 -07:00@@ -51,7 +51,7 @@ #define __clear_fpu( tsk ) \ do { \ if ((tsk)->thread_info->status & TS_USEDFPU) { \- asm volatile("fwait"); \+ asm volatile("fnclex ; fwait"); \ (tsk)->thread_info->status &= ~TS_USEDFPU;\ stts(); \ }

Той се извиква в flush_thread() (който се ползва в flush_old_exec() иследователно и sys_execve()), както и в restore_i387_fsave(),restore_i387_fxsave() (които се достигат от sys_sigreturn() иsys_rt_sigreturn()).

Програмата по-горе разваля състоянието на FPU и в частност – някой битовеза изключения в статус думата на FPU. При това си състояние следващата командас плаваща запетая (освен неизчакващите като fnsave и fninit) ще предизвикаизключение и тази команда е точно fwait.

Грешките при плаващите запетаи (FP) се обработват от do_coprocessor_error(), който вика math_error(), който от своя страна извиква save_init_fpu(), а тойзапаметява FPU състоянието в current->thread.i387 и наглася TS флага. След товаmath_error() слага в опашката SIGFPE към приложението и се изключва. Акогрешката е възникнала в потребителското пространство (userspace), то това едостатъчно – по време на връщане сигналът ще бъде забелязан и доставен. Обаче втози случай грешката възниква в код на ядрото и следователно изпълнениетопросто се възстановява от същото място и се опитва да изпълни отново същатаоперация fwait.

Сега обаче TS флага е нагласен и за това получаваме trap 7-device_not_available. Хендлъра на този trap извиква math_state_restore(), койтопочиства TS флага и презарежда FP състоянието от current->thread.i387. След това

Page 6: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 6 of 21

се връща и проблемната инструкция се извиква отново, където сега получавасъщата FP грешка за първи път отново...

Така процесорът се оказва зациклил в безкрайни грешки в режим наядрото...Опасност : Локален потребител може да накара цялата система да забие, като притова тази атака дори няма да присъства в логовете, защото всичко буквалнозамръзваРешение : Налага се да изчистим всички изключения преди да синхронизираме сFPU, тъй като нямаме готовност да обработим FP грешка на този етап в clear_fpu.Показаната горе модификация на макросът поправя проблема, като също такапрепоръчваме обновяване на ядрото до безопасна версия

Дата : 12 Май 2004Наименование : Уязвимост в Linux Kernel STRNCPY. Възможно изтичане наинформация.Тип : Грешка в дизайнаЗасегнато ядро : 2.4.1 до 2.4.22; 2.5.x, 2.6.x не е засегнат.Резюме : Тази уязвимост засяга платформи различни от x86.Подробности : Съобщено е, че ядрото на Линукс е предразположено към изтичанена информация (information leak). Тази публикация е поради libc кодът, койтоимплементира гореспомената функция на платформи различни от x86.Имплементацията на функцията strncpy() може да подравни (pad) върнатия буфер смалки части от паметта на ядрото, вместо подравняване с NULL. Това може дадоведе изтичане на информация, която да доведе до атаки върху засегнатитесистеми или процеси. Опасност: До сега не са известни някакви експлойти върху тази уязвимост.Решение: Upgrade, ако е възможно се препоръчва upgrade към 2.6.x.

Дата : 11 Май 2004Наименование : SCTP_SetSockOpt Integer Overflow уязвимост.Тип : Грешка при проверка на границитеЗасегнато ядро : 2.2.x, 2.4 до 2.4.25Резюме : Открита е уязвимост в системното извикване в ядрото на Линукс нафункцията sctp_setsockopt(). Това се отнася за кода отговарящ заSCTP_SOCKOPT_DEBUG_NAME socket опцията. Проблемът е в функциятаsctp_setsockopt(), в файла net/sctp/socket.c, като поради липсата на достатъчно добравалидация на числата (integer) доставени от потребителя. Тази уязвимост може дадоведе до резервиране на парче памет с размер 0, което води до kernel panic.Подробности :

Този бъг съществува в имплементацията на SCTP който се намира в net/sctp(в дървото на source-а на ядрото). Поради недостатъчна проверка на аргументите нафункцията sctp_setsockopt(), се получава, че тя уязвима от integer overflow, когато

Page 7: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 7 of 21

се използва SCTP_SOCKOPT_DEBUG_NAME socket опцията, водеща до алокацияна памет. Ето и уязвимия код в файла net/sctp/socket.c:

switch (optname) { case SCTP_SOCKOPT_DEBUG_NAME: /* BUG! we don't ever seem to freethis memory. --jgrimm */ if (NULL == (tmp = kmalloc(optlen + 1,GFP_KERNEL))) { retval = -ENOMEM; goto out_unlock; }

if (copy_from_user(tmp, optval,optlen)) { retval = -EFAULT; goto out_unlock; } tmp[optlen] = '\000'; sctp_sk(sk)->ep->debug_name = tmp; break;

Извиква се kmalloc(), за да се резервира optlen, като се прибавя 1, за да сеподсигури достатъчно памет и за optval. Но поради липсата на проверка закоректност на данните може да се даде като стойност на optlen максималната заunsigned int, което след увеличението с 1 да доведе до overflow. Това е уязвимотоизвикване на kmalloc():

if (NULL == (tmp = kmalloc(optlen + 1, GFP_KERNEL))) { retval = -ENOMEM; goto out_unlock; }

Понеже count-а е unsigned, то отрицателните числа се интерпретират като големиunsigned числа, и ако се даде на optlen стойност -1(или 0xffffffff), което емаксималната стойност, която unsigned може да съдържа коректно, следувеличението с 1 се получава integer overflow при което се получава 0. При което серезервира недостатъчно памет, за да се съдържа и optval. При което приизвикването на copy_from_user() което копира голямо количество информация отuser-space (optval), в резервираната памет (която е недостатъчно), това може дадоведе до overwrite на памет на ядрото, т.е. издигане на правата до правата наядрото, ако се експлойтне правилно.Опасност: До момента не са известни някакви експлойти.Решение: Има не официален patch:

--- sctp_vuln.patch ------ socket.orig.c 2004-05-11 18:31:45.000000000+0100+++ socket.c 2004-05-11 18:32:40.000000000 +0100@@ -1516,18 +1516,7 @@

switch (optname) { case SCTP_SOCKOPT_DEBUG_NAME:- /* BUG! we don't ever seem to freethis memory. --jgrimm */

Page 8: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 8 of 21

- if (NULL == (tmp = kmalloc(optlen + 1,GFP_KERNEL))) {- retval = -ENOMEM;- goto out_unlock;- }-- if (copy_from_user(tmp, optval,optlen)) {- retval = -EFAULT;- goto out_unlock;- }- tmp[optlen] = '\000';- sctp_sk(sk)->ep->debug_name = tmp;+ /* do nothing */ break;

case SCTP_SOCKOPT_BINDX_ADD:--- EOF ---

Този проблем е решен в ядрото 2.6 и препоръчително да се upgrade-не до тазиверсия.

Дата : 29 Април 2004Наименование : Уязвимост в Linux Kernel Panic функцията от Buffer Overflow.Тип : Грешка при проверка на границитеЗасегнато ядро : Linux kernel 2.4 до 2.4.25; 2.6.x не е засегнатРезюме : Съобщено е, че има уязвимост в извикването на panic(), като е възможенbuffer overflow.Подробности : Уязвимостта е породена от извикване на неограничен vsprintf() вpanic(), която копира информация предоставена от потребителя в масив сфиксирана дължина. Възможно е да се пише след границата на масива и да сеполучи подправена информация, и понеже тази памет е в kernel паметта, стававъзможно да се изпълни произволен код. Според някой доклади този бъг не еизползваем (not exploitable). Ето и кода от kernel/panic.c:

NORET_TYPE void panic(const char * fmt, ...){

static char buf[1024];va_list args;

#if defined(CONFIG_ARCH_S390) unsigned long caller = (unsigned long) __builtin_return_address(0);#endif

bust_spinlocks(1);va_start(args, fmt);vsprintf(buf, fmt, args);va_end(args);printk(KERN_EMERG "Kernel panic: %s\n",buf);

където се вижда, че в buf се пише без да се проверява колко точно байта се пишат.Използването на vsnprintf() би предотвратило Buffer Overflow.

Page 9: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 9 of 21

Опасност: До момента не са известни никакви експлойти за тази уязвимост.Решение: Turbolinux, Slackware, SuSE, SGI и други vendor-и са публикували кръпкикойто решават този проблем. Upgrade до версия на ядрото 2.6 също решавапроблема.

Дата : 20 Април 2004Наименование : setsockopt MCAST_MSFILTER integer overflowТип : Грешка при проверка на границитеЗасегнато ядро : 2.4.22 до 2.4.25, 2.6.1 до 2.6.3Резюме : Критична уязвимост в сигурността е открита в ядрото на Линукс, в кодана функцията ip_setsockopt(). Подходящото използване на тази уязвимостпозволява локално повишаване на правата, даващи на атакуващия пълни super-userправа.Подробности :

Кодът на функцията ip_setsockopt() се използва в системното извикванеsetsockopt. Тази функция позволява манипулация на множество опции в IP сокета.MCAST_MSFILTER опцията може да бъде използвана за предоставяне на ядротона списък от multicast адреси, които да бъдат приети от сокета. Този код епредоставен с 2.4.22/2.6.1 kernel. Има възможност за integer overflow в кодазанимаващ се с MCAST_MSFILTER socket опциите в частта където се изчислявастойността на IP_MSFILTER_SIZE макроса. Несигурния код е в файлаnet/ipv4/ip_sockglue.c:

case MCAST_MSFILTER:{/* ... */

msize = IP_MSFILTER_SIZE(gsf->gf_numsrc);msf = (struct ip_msfilter *)kmalloc(msize,GFP_KERNEL);

/* ... */for (i=0; i<gsf->gf_numsrc; ++i) {

psin = (struct sockaddr_in *)&gsf->gf_slist[i];if (psin->sin_family != AF_INET)

goto mc_msf_out;msf->imsf_slist[i] = psin->sin_addr.s_addr;

}

Където IP_MSFILTER_SIZE макроса е дефиниран така:

#define IP_MSFILTER_SIZE(numsrc) \(sizeof(struct ip_msfilter) - sizeof(__u32) \+ (numsrc) * sizeof(__u32))

По този начин, докато се изчислява kernel memory space, чрез integer overflow можеда бъде overflown-нат буфера на ядрото с произволни стойности (в кода на forцикъла).Опасност: Подходящото използване на тази уязвимост позволява локалноповишаване на правата, даваща на атакуващия пълни super-user права.Неуспешното използване на тази уязвимост може да доведе до denial-of-serviceатака която да доведе до забиване на системата или незабавно рестартиране.

Page 10: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 10 of 21

Решение: Тази уязвимост е оправена в версии на ядрото 2.4.26 и 2.6.4.

Дата : 12 Април 2004Наименование : Локална Sigqueue Blocking DoS уязвимост.Тип : Грешка в дизайна (несправяне с особени условия)Засегнато ядро : 2.4 до 2.4.25, 2.6 до 2.6.3Подробности : Намерена е уязвимост в ядрото на Линукс, която може да позволина злонамерен локален потребител да предизвика в цялата система условие за DoS.Това може да бъде предизвикано чрез сигнал на ядрото queue (struct sigqueue) иизчерпване на таблицата със системните процеси (system process), коетопредизвиква много нишки да останат зомбирани (поставени в zombie state).Опасност: Може да бъде използвана за DoS.Решение: До сега не са известни някакви patch-ове от големите производители.

Дата : 18 Февруари 2004Наименование : do_mremap VMA уязвимост в увеличение на локалните праваТип : Грешка при проверка на границите (несправяне с изключителни ситуации)Засегнато ядро : 2.2 до 2.2.25, 2.4 до 2.4.24, 2.6 до 2.6.2Резюме : Критична уязвимост в сигурността е открита в кода на мениджъра напаметта (memory manadgement) в ядрото на Линукс, в системното извикванеmremap(), поради непроверена връщана стойност.Подробности :

Ядрото на Линукс пази списък от потребителски адресируеми реални полетапамет за всеки отделен процес. Всеки процес притежава едносвързан списък оттака наречените дескриптори за области виртуална памет (virtual memory areadescriptors - VMAs). Всеки VMA описва началото на реалния блок памет, неговатадължина и множество флагове, като да речем page protection. Системнотоизвикване на mremap() позволява промяна в размера (свиване или разширяване),както и преместването на съществуващи области виртуална памет или кои да ечасти памет по адресното пространство на процеса. За да осъществи множествотооперации do_mremap извиква вътрешната kernel функция do_munmap(). В случая нанепроверен do_munmap в кода mremap, намираме условие, което оставя таблицатасъс страниците (page table entry - PTE) непокрита от VMA. Ето и опасния код (в /mm/mremap.c).

if (old_len >= new_len) {do_munmap(current->mm, addr+new_len, old_len - new_len);if (!(flags & MREMAP_FIXED) || (new_addr == addr))

goto out;}

do_munmap няма да успее ако [addr+new_len, addr+new_len + (old_len-new_len)]отиде в средата на VMA и максималния позволен брой (за момента 65535) на VMAдескриптори вече е бил използван. По надолу в кода част от съответният VMA епреместен и отрязан.

if (!move_page_tables(current->mm, new_addr, addr, old_len)) {

Page 11: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 11 of 21

unsigned long vm_locked = vma->vm_flags & VM_LOCKED;if (allocated_vma) {

*new_vma = *vma;new_vma->vm_start = new_addr;new_vma->vm_end = new_addr+new_len;new_vma->vm_pgoff += (addr-vma->vm_start) >> PAGE_SHIFT;

, но горното работи правилно само ако do_munmap е успяла.Опасност: С други думи може да се получи така, че да вмъкнем каквато и да сиискаме информация във виртуалната памет на друг процес, което означава, чеатакуващия може да придобие пълни super-user права.Решение: Тази уязвимост е оправена във версии 2.4.26 и 2.6.

Дата : 18 Февруари 2004Наименование : Грешка при копирането на памет към ядрото в USB драйвера наVicamТип : Грешка при контрол на достъпаЗасегнато ядро : до 2.4.24 (незасегнато: 2.4.25)Резюме : USB драйвера на Vicam не достъпва правилно потребителската памет(userspace) и така излага на опасност систематаПодробности :

USB драйвера на Vicam не ползва функцията copy_from_user(), за да копираданни от потребителската памет към ядрото (userspace -> kernel space), а ползвадиректно указатели и по този начин се нарушава сигурността и принципите насигурното програмиране, като това може да доведе до DoS (Denial of Service) отлокален потребител. Следният код във /drivers/usb/media/vicam.c :

struct video_picture *vp = (struct video_picture *) arg;

показва как е направено директно преобразуване на типовете. Би трябвалода бъде заменен от:

struct video_picture vp;if (copy_from_user(&vp, arg, sizeof(vp))) { retval = -EFAULT; break;}

със всичките промени по-надолу, които отчитат ползването на структура, ане указател към нея. Тази промяна би предпазила системата от такъв тип атака.Решение : Примерната промяна в кода (и последвалите други промени в кода оттова) поправят тази грешка.

Ние ви препоръчваме да обновите направо ядрото си. Всички версии наядрото след 2.4.25 и 2.6.6 (включително) са с внесени поправки в драйвера, като запотребителите с по-стари версии е най-добре то да бъде обновено.

Page 12: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 12 of 21

Дата : 18 Февруари 2004Наименование : Уязвимост в Linux Kernel execve() при деформиран ELF файлводи до възможност от локален DoS.Тип : Грешка в дизайна (несправяне с особени условия)Засегнато ядро : Linux kernel 2.4 до 2.4.24Резюме : Има възможна уязвимост в execve() функцията, поради неспособността ина се справи с особен случай.Подробности : Съобщено е, че е открита уязвимост, която може да доведе ядротона Линукс до локален DoS поради неспособността на execve() функцията да сесправи с особени условия. Непосредствените последствия от това са, че атакуващияможе на накара ядрото да fail-не, да отказва услуги на легитимирани потребители.Това може да бъде предизвикано от увредено (или деформирано) ELF (ExecutableLinking Format) binary.Опасност: До момента не са известни никакви експлойти за тази уязвимост.Решение: SuSE са пуснали кръпка, upgrade до 2.6.x също оправя проблема.

Дата : 5 Януари 2004 Наименование : Локално повишаване на привилегиите чрез do_mremap()Засегнато ядро : 2.4 до 2.4.23, 2.6.0Тип : Грешка при проверка на границитеРезюме : Критична уязвимост в memory management кода в mremap(2) системнотоизвикване, причинено от грешна проверка на границите, позволява локаленпотребител да повиши правата си.Подробности : Системното извикване mremap позволява увеличаване или намаляване, както ипреместване в адресируемото пространство на съществуващите области отвиртуалната памет (или части от нея) на даден процес.

Обикновено това пространство покрива поне една страница в паметта (4килобайта на i386 архитектурата), но грешка в do_mremap()при проверка награница, когато се прави реалокация на областта с виртуална памет, може да доведедо създаването на област с големина 0 байта.

Този проблем се основава на една основна грешка- реалокирането на 2страници създава дупка в паметта с дължина една страница и допълнителна областвиртуална памет от 2 страници. В случая със заявка за алокиране на нулеваголемина, не се създава дупка в областта с виртуална памет, но се създавадопълнителен дескриптор с 0 байта дължина.

Така променена, тази област от виртуалната памет може да доведе досмущения в работата на други операции по менажиране на паметта, което да доведедо непредвидими последствия.

Ето как би изглеждало подреждането на паметта на един процес с невалиднаобласт от виртуалната памет:

08048000-0804c000 r-xp 00000000 03:05 959142 /tmp/test 0804c000-0804d000 rw-p 00003000 03:05 959142 /tmp/test 0804d000-0804e000 rwxp 00000000 00:00 0 40000000-40014000 r-xp 00000000 03:05 1544523 /lib/ld-2.3.2.so

Page 13: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 13 of 21

40014000-40015000 rw-p 00013000 03:05 1544523 /lib/ld-2.3.2.so 40015000-40016000 rw-p 00000000 00:00 0 4002c000-40158000 r-xp 00000000 03:05 1544529 /lib/libc.so.6 40158000-4015d000 rw-p 0012b000 03:05 1544529 /lib/libc.so.6 4015d000-4015f000 rw-p 00000000 00:00 0[*] 60000000-60000000 rwxp 00000000 00:00 0 bfffe000-c0000000 rwxp fffff000 00:00 0

Където проблемната област е маркирана с [*].

Въз основа на някой допълнителни особености, ще отбележим, че примногократно fork-ване на процес с нулева област виртуална памет, можем даувеличаваме броячът на страницата (page counter). Преди да излезем от childпроцесите, трябва също така да почистим, за да не получим съобщение за грешкаот ядрото.

В крайна сметка чрез множество fork-вания на процес, можем да доведемчрез прехвърляне (overflow) page counter броячът до 1 в child процеса. Ако сегаосвободим областта, то броячът ще бъде 0 и това ще се върне на управлението напаметта в ядрото. Родителския процес все още ще има връзка (reference) къмосвободената страница и така ще може да манипулира памет на ядрото...

Не се изискват специални привилегии, за да се ползва системното извикванеmremap(2)и поради това всеки процес може да се възползва от този проблем. Приподходящи действия, това може да доведе до повишаване на привилегиите,включително и изпълняването на произволен код в ниво на достъп на ядрото.Опасност : Съществува proof-of-concept експлойт, който успешно дава UID 0 шелна уязвими системи.Решение : Препоръчва се възможно най-скоро прилагане на пачовете, издадени отпроизводителя.

Дата : 1 Декември 2003 Наименование : Локална уязвимост в проверката на границите във функциятаdo_brkТип : Грешка при проверка на границитеЗасегнато ядро : 2.4.х, без 2.4.23Резюме : Критичен бъг беше открит в Линукс ядрото в do_brk() функцията, койтоможе да доведе до излагане на риск на цялата система.Подробности :

Както знаем, адресното пространство на една Линукс машина се управлявапо линеен модел. Всеки процес има достъп до паметта от 0 до TASK_SIZE байта(константа на ядрото), а паметта над тази константа е за кода на ядрото и неговитеструктури данни, до които има достъп само привилегирован код (на ядрото).

Функцията do_brk()е вътрешна функция на ядрото, която се викаиндиректно при менажиране на хийпа (heap) на процес, като го разширява илисвива. Тя представлява опростена версия на системното извикване mmap(2) като сегрижи единствено за алокиране на неинициализирани данни. Функцията не правипроверки за границите, в които са получените ù параметри и това позволява да

Page 14: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 14 of 21

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

Така с тази липсваща проверка ние можем да разширим хийпа до надTASK_SIZE и да излъжем мениджъра на паметта на ядрото, че защитената паметна ядрото принадлежи на нашия хийп. Този трик не дава директен достъп до тазипамет, понеже тези страници са защитени от MMU unit-а на централния процесор.Въпреки това, може да се ползват други системни извиквания, за да се оперира снашия разширен хийп и да получим пълни uid 0 привилегии, възможност замодифициране на кода и структурите на ядрото, както и изпълнение на код с нивона ядрото (ring0).

Ето как изглежда едно типично разположение на паметта на един процес:

bash$ cat /proc/self/maps08048000-0804c000 r-xp 00000000 03:02 207935 /bin/cat0804c000-0804d000 rw-p 00003000 03:02 207935 /bin/cat0804d000-0804e000 rwxp 00000000 00:00 040000000-40015000 r-xp 00000000 03:02 207495 /lib/ld-2.3.2.so40015000-40016000 rw-p 00014000 03:02 207495 /lib/ld-2.3.2.so40016000-40017000 rw-p 00000000 00:00 040020000-40021000 rw-p 00000000 00:00 042000000-4212f000 r-xp 00000000 03:02 319985 /lib/tls/libc-2.3.2.so4212f000-42132000 rw-p 0012f000 03:02 319985 /lib/tls/libc-2.3.2.so42132000-42134000 rw-p 00000000 00:00 0bfffe000-c0000000 rwxp fffff000 00:00 0

А ето как би изглеждала алокираната памет на един процес след извикванена функцията do_brk() от ELF и a.out (ELF and a.out loaders) както и от системнотоизвикване brk(2), които ни дават 3 различни подхода към тази атака:

080a5000-c891d000 rwxp 00000000 00:00 0

Опасност : Възможност за изпълнение на код с най-високи привилегии имодифициране на ядрото.Решение : За да се справим с този проблем е достатъчно да добавим проверката:

if ((addr + len) > TASK_SIZE || (addr + len) < addr) return -EINVAL;

Препоръчително е да обновим ядрото си до най-новата версия.

Дата : 29 Юли 2003Наименование : Уязвимост в Linux Kernel 2.4 XDR Packet Handler за NFSv3отдалечен DoS.Тип : Грешка при проверка на границите Засегнато ядро : 2.4.1 до 2.4.20Подробности : Открита е уязвимост в операция отговорна за пренареждането наXDR информация за процедурно извикване на NFSv3. Уязвимостта съществува откакто NFSv3 поддръжката е интегрирана в ядрото. Уязвимостта е мълчаливооправена в 2.4.21. Проблемът е в функцията decode_fh в файла fs/nfsd/nfs3xdr.c.

Page 15: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 15 of 21

static inline u32 *decode_fh(u32 *p, struct svc_fh *fhp){ int size; fh_init(fhp, NFS3_FHSIZE); size = ntohl(*p++); if (size > NFS3_FHSIZE) return NULL;

memcpy(&fhp->fh_handle.fh_base, p, size); fhp->fh_handle.fh_size = size; return p + XDR_QUADLEN(size);}

Където p е пакет от XDR информация, контролирана от атакуващия. Ако размеръте отрицателен проверката е пропусната и злонамерената стойност е предадена наmemcpy. Поради поведението на kernel-ския memcpy, това ще доведе до прекаленоголямо копиране в kernel space, което ще доведе до незабавен kernel panic.Опасност: Има написани експлойти за тази уязвимост. Може да доведе до DoS(Denial of Service).Решение: Обновяване на ядрото до версия над 2.4.20 или 2.6.x, или да се правипроверка дали стойността не е отрицателна.

Дата : 22 Юли 2003 Наименование : Грешка в '/proc/self' може да разкрие важна информация налокалния потребителТип : Грешка при контрол на достъпаЗасегнато ядро : 2.4.20Резюме : Грешка в '/proc/self' може да разкрие важна информация на локалнияпотребителПодробности :

Локалният потребител може да се сдобие с важна информация на машината,ако се възползва от грешка в '/proc' . Ако бъде отворено entry на /proc/self/ и бъдезадържано отворено, докато се стартира setuid програма, то това отворено entry неможе да си промени собствеността от първоначалната, на стойността в setuid. Такатези файлове могат да бъдат видени със setuid привилегии.

Тази техника, обаче, не може да бъде приложена върху /proc/self/mem,защото проверките за права се правят динамично.Опасност : Локален потребител може да види файловете във '/proc/self' със setuidпривилегииРешение : Препоръчваме ви обновяване на ядрото до най-новата версия.

Дата : 22 Юли 2003 Наименование : Чрез '/proc/tty/driver/serial' може да разкрие информация запаролите на локалния потребител

Page 16: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 16 of 21

Тип : Разкриване на информация за аутентикацияРезюме : Чрез грешка в '/proc/tty/driver/serial' може да се разкрие информация запаролите локалния потребителПодробности :

Версиите на Линукс ядрото преди 2.4.21 позволяват '/proc/tty/driver/serial’ даразкрие информация за точния брой символи, преминали през серийните връзки.Локален потребител може да следи тези обекти и да определи дължината напаролата на даден потребител, докато я изписва, както и да определи времетомежду натисканията на отделните клавиши и така да определи с по-голямавероятност кои точно клавиши са били натиснати и точната парола на потребителя.

Опасност : Разкриване характеристики на чужда парола Решение : Препоръчва се ядрата преди 2.4.21 да бъдат обновени до по-новиверсии.

Дата : 3 Юни 2003Наименование : Уязвимост в Linux Kernel FPU/SSE Environment RestorationMXCSR Register.Тип : Грешка в дизайна (несправяне с особени условия)Засегнато ядро : 2.0, 2.2, 2.4 до 2.4.21; 2.4.22 не е засегнат.Резюме : Кодът за Linux Kernel FPU/SSE environment restoration е уязвим, катоможе да доведе до локален DoS.Подробности : Когато ядрото се опита да възстанови предишното FPU/SSEсъстояние на информацията използвайки FXSAVE инструкцията, може да сеполучи особена ситуация, в която съдържанието на MXCSR регистъра да бъденевалидно. Това може да причини запазен бит в регистъра да бъде неочаквано set-нат, ефективно да предизвика general protection fault в ядрото, което на го накара даcrash-не.Опасност: Symantec са потвърдили, че тази уязвимост е използваема.Решение: Mandrake, Red Hat, Debian и други vendor-и са публикували кръпки койтооправят проблема. Обновяване на ядрото до 2.4.22 и нагоре, а също и до 2.6.xоправя проблема.

Дата : 3 Юни 2003Наименование : Уязвимост в Linux Kernel Fragment Reassemble, която може дадоведе до отдалечен DoS.Тип : Грешка в дизайнаЗасегнато ядро : Linux kernel 2.4 до 2.4.20Резюме : Уязвимост в Linux Kernel Fragment Reassemble, която може да доведе доотдалечен DoSПодробности : Съобщено е, че ядрото не третира правилно някой специфичнитипове мрежов трафик. Заради това атакуващия може да причини интензивна

Page 17: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 17 of 21

консумация на ресурси причинена от злонамерени TCP/IP пакети, което може дадоведе до DoS.Опасност: Отдалечен DoSРешение: Red Hat и Debian са пуснали кръпки, който поправят тази уязвимост,upgrade до 2.6.x също оправя проблема.

Дата : 15 Май 2003 Наименование : Отдалечен DoS поради проблеми в routing кешаТип : Атака върху алгоритмичната сложностЗасегнато ядро : преди 2.4.21-rc2Резюме : Уязвимост в Линукс ядрото 2.4 позволява отдалечен потребител дапредизвика колизии в рутиращата хеш таблица на кеша (route cache hash table) катопраща специално подбрани пакети и така да предизвика натоварване на машината,водещо до DoS.Подробности :

Рутиращия кеш (или “dst кешът”, останал поради исторически причини)служи за кеширане на решенията за рутиране на един поток трафик. Потокъттрафик представлява пакети със еднакъв IPv4 source и destination адреси, и TOS в IPхедъра.

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

Рутиращия кеш се реализира чрез хеш таблица, като големината ù сеопределя въз основа на количеството физическа памет при всяко зареждане насистемата. Хеш функцията е GF(2)- линейна (което означава че лесно се правятколизии), а за справяне с колизии се ползва свързан списък. Има garbage collector заподдържане на големината ù.

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

Ефективността от тази атака зависи съществено от максималната големинана кеша, което означава, че пряко зависи от количеството RAM памет на машинатаи следователно машини с повече RAM са по-застрашени от тази отдалечена атака.Опитно атаката е била приложена успешно върху машина с 4GB RAM при поток от400 пакета в секунда, докато при пакети с произволно генериран source адрес енямала никакъв ефект.Опасност : Отдалечен DoSРешение : За да се защитим от такава атака е нужно да ограничим големината нарутиращия кеш и така да ускорим търсенето. Това може да стане чрез /procинтерфейсът чрез следните команди (като root потребител):

# echo 4096 > /proc/sys/net/ipv4/route/max_size

Page 18: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 18 of 21

# echo 2048 > /proc/sys/net/ipv4/route/gc_thresh#

(при повечето системи може да се редактира /etc/sysctl.conf за да бъдатпромените постоянни)

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

Дата : 14 Май 2003 Наименование : Грешка в ioperm() дава достъп на локални потребители допортове с ограничен достъпТип : Грешка при контрол на достъпаЗасегнато ядро : до 2.4.21-rc2Резюме : Локални потребители могат да добият достъп до IO портове, въпрекиограничените си права поради проблем в реализациата на ioperm()Подробности :

Грешка в дизайна на системното извикване 'ioperm' позволява на локаленпотребител да добие достъп за четене и писане на портове с номера под 1024. Същотака е възможно, когато привилегирован потребител извика ioperm(), да не бъдатправилно ограничени привилегиите.

Пример за първия случай е кодът:

if (ioperm(1023, 1, 0) == -1) { perror("ioperm"); return (1); }

(void) printf("0x%02x\n", inb(atoi(port_number)));

който стартиран от потребител с ограничени права, би му позволил да чете(и аналогично може да пише) в портове с адреси под 1024.

А това е пример за втория проблем:

if (ioperm(888, 1, 1) == -1) { perror("ioperm"); return (1); }

(void) printf("0x%02x\n", inb(889));

където този код е изпълнен от привилегирован потребител демонстрира как'ioperm' не успява правилно да ограничи привилегиите.Опасност : Достъп до непозволени портове на машината, разкриване имодификация на системна информация

Page 19: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 19 of 21

Решение : Препоръчва се обновяване на ядрото до версия 2.4.21 или по-нова,където проблема е оправен.

Дата : 17 Март 2003 Наименование : Чрез ptrace() може локални потребители да се сдобият с root праваТип : Грешка при контрол на достъпа при race conditionЗасегнато ядро : до 2.4.20Резюме : Чрез ptrace() може локални потребители да се сдобият с root праваПодробности :

Функцията ptrace() обикновено служи за дебъгване на приложение, като тяпозволява даден процес да се закачи за друг и да го следи и модифицира неговотосъстояние и памет по време на изпълнение.

Когато процес даде заявка за зареждане на модул, ядрото стартира дъщеренпроцес, слага му euid и egid да са 0 и извиква execve("/sbin/modprobe"). Акообаче преди смяната на euid на този дъщерен процес, към него се прикачиатакуващ чрез ptrace() (в което в същност се изявява тази уязвимост на ядрото –позволява такова прикачване (race condition)), то той ще добие контрол върху него.Така атакуващият може да вкара шел код в процеса и да го изпълни с root права ипо този начин да повиши своите права.

Застрашени от такава атака са Операционни Системи с:· ядро версия 2.4.21 pre1 или по-старо· ядрото е компилирано с поддръжка на модули· включено е зареждането на модули (module loader)· извикванията на ptrace() не са блокирани

Опасност : root достъп за локален потребителРешение : Препоръчително е всички потребители, за които по-горните изискванияса изпълнени, да обновят версиите на своите ядра.

Дата : 26 Март 2002Наименование : Уязвимост в d_path() при прекалено дълги пътища (path) итяхното отрязване.Тип : Грешка в дизайна (несправяне с особени условия)Засегнато ядро : до 2.2.20 и 2.4.18Резюме : В случай на много дълги пътища, вътрешната функция на ядрото- d_pathвръща отрязана от към края част, вместо да върне стойност за грешка. Когато тазифункция е извикана от системното извикване getcwd и от функциятаdo_proc_readlink(), лъжлива информация може да бъде върната към user-spaceпроцесите.Подробности : Функцията d_path разрешава параметър за абсолютния път. Пътят(path) е конкатенация последователни path компоненти. Полученото отконкатенацията се запомня в буфер с фиксирана дължина от PAGE_SIZE байта.Ако се превиши дължината от PAGE_SIZE – 1 байта функцията отрязва края ивръща без да съобщава за грешка. Понеже системното извикване getcwd използва

Page 20: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 20 of 21

функцията d_path(), тя може да върне невалиден адрес. Системното извикванеreadlink, извикано от proc файловата система извиква do_proc_readlink(), коятосъщо е уязвима заради, това че използва d_path(). Ето и кода на d_path от файлаfs/dcache.c

char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt,struct dentry *root, struct vfsmount *rootmnt,char *buffer, int buflen)

{char * end = buffer+buflen;char * retval;int namelen;

*--end = '\0';buflen--;if (!IS_ROOT(dentry) && list_empty(&dentry->d_hash)) {

buflen -= 10;end -= 10;memcpy(end, " (deleted)", 10);

}

/* Get '/' right */retval = end-1;*retval = '/';

for (;;) {struct dentry * parent;

if (dentry == root && vfsmnt == rootmnt)break;

if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {/* Global root? */if (vfsmnt->mnt_parent == vfsmnt)

goto global_root;dentry = vfsmnt->mnt_mountpoint;vfsmnt = vfsmnt->mnt_parent;continue;

}parent = dentry->d_parent;namelen = dentry->d_name.len;buflen -= namelen + 1;if (buflen < 0)

break;end -= namelen;memcpy(end, dentry->d_name.name, namelen);*--end = '/';retval = end;dentry = parent;

}return retval;

global_root:namelen = dentry->d_name.len;buflen -= namelen;if (buflen >= 0) {

retval -= namelen-1; /* hit the slash */memcpy(retval, dentry->d_name.name, namelen);

}return retval;

}

Page 21: Уязвимости в ядрото на Linux 2€¦ · Този доклад е курсов проект на Георги Георгиев и Александър Илиев

Page 21 of 21

Опасност: Привилегирован процес може да бъде да бъде измамен, че е впроизволна директория. Други сценарии са възможни ако се използва readlink() отфайлове от proc файловата система (като "/proc/self/exe"). Решение: Следващите версии на ядрото са изчистени от този бъг.

Ползвана литература:

· http://www.isec.pl/vulnerabilities.html · http://www.securityfocus.com/ - основна листа с уязвимостите в Линукс

ядрото· http://www.securitytracker.com/ - допълнителна листа и разширение на

листата и информацията от SecurityFocus· http://www.enyo.de/fw/security/notes/linux-dst-cache-dos.html - Algorithmic

Complexity Attacks and the Linux Networking Code · www.giac.org/practical/GCIH/Sangram_Gayal_GCIH.pdf - Tracing the Ptrace· http://marc.theaimsgroup.com/?l=linux-kernel&m=108681568931323&w=2 -

timer + fpu stuff locks my console race () (inline assembly function DoS)· http://cve.mitre.org/ - Common Vulnerabilities and Exposures· Linux Kernel Sources