• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Вооружаемся ASan'ом для поиска 0-day уязвимостей в OpenSource проектах.

weaver

31 c0 bb ea 1b e6 77 66 b8 88 13 50 ff d3
Забанен
Регистрация
19.12.2018
Сообщения
3 301
Решения
11
Реакции
4 622
Депозит
0.0001
Пожалуйста, обратите внимание, что пользователь заблокирован
1714484700674.png


Интро​

В процессе серфинга интернета, я наткнулся случайно на одну вакансию, на позицию vulnerability researcher'а. Всё как обычно, обычная вакансия, за исключением требовался человек, который преимущественно понимает алгоритмы работы AddressSanitizer (ASan), а так же знает технологии DBI (Dynamic Binary Instrumentation, DBI).

Вот частичное описание этой вакансии (не реклама)
1714484729275.png


Если с DBI всё понятно, но ASan? Как можно не знать и не понимать как он работает? ... Многие наверно слышали об этом инструменте, некоторые знают о нём и используют его, а другие и вовсе не знают. Так или иначе сегодня мы будем говорить об Asan'е. Это очень мощный инструмент, который помогает искать ЖИРНЫЕ баги. Сегодня я расскажу, как с помощью Asan'а можно найти 0-day уязвимости в OpenSource проектах, но найдете ли вы уязвимости или нет зависит только от вас. От себя же, я покажу простейший метод, с помощью которого можно искать баги в самых разных проектах. В общем предлагаю сегодня погрузится в тему баг-хантинга, ПОЕХАЛИ!!!

Что такое AddressSanitizer?​

1714484750025.png


Это быстрый динамический анализатор кода, для детектирования ошибок связанных с памятью - во время исполнения, для программ написанных на С\С++.

AddressSanitizer (ASan) разработала компания Google, как инструмент поика уязвимотей повреждения памяти, ASan обнаруживает ошибки в форме неопределенного или подозрительного поведения с помощью компилятора, вставляющего инструментальный код во время компиляции.

Впервые ASan был представлен на конференции USENIX в 2012 году, как более универсальный детектор ошибок в отличие от существующих на тот момент, по скольку большинство из них либо работали медленно, либо обнаруживали ограниченный набор ошибок, либо то и другое...

Вот ссылка на это событие, там же можно посмотреть запись выступления "AddressSanitizer: A Fast Address Sanity Checker", а так же прочитать статью и посмотреть слайды.

Событие

Видео

Слайды

Статья

С момента реализа этого инструмента было обнаружено 300+ уязвимостей в Chromium, только за первые 10 месяцев его использования. И это не считая другие проекты, такие как Firefox, FFmpeg, FreeType, MySQL итд. Поскольку инструмент показал себя эффективным с точки зрения обнаружения багов, его быстро стали интегрировать, добавлять во все компиляторы.

AddressSanitizer теперь является частью LLVM, начиная с версии 3.1, и частью GCC, начиная с версии 4.8. А так же Xcode с версии 7.0. А с 2019 года он был интегрирован в Visual Studio начиная с версии компилятора (MSVC) 16.9, как дополнительный установочный компонент.

Правда в Windows он всё еще бета, по крайне мере для меня.

Какие баги он определяет?​

1714484781326.png

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

Примеры репортов


Собственно ASan умеет определять следующие баги.
Stack Buffer Overflow
Stack Buffer Underflow
Dynamic Stack Buffer Overflow
Stack-Use-After-Return
Stack-Use-After-Scope
Global Buffer Overflow
Alloc-Dealloc Mismatch
Allocation size too Big
Calloc parametrs Overflow
Container Overflow
Invalid Allocation Alignment
Memcpy parametr Overlap
Strncat parametr Overlap
New & Delete type Mismatch
Use After Poison
Heap Buffer Overflow
Heap Use-After-Free
Double Free
Initialization Order Bugs
Memory Leaks

Из этого списка я выделил самые ЖИРНЫЕ баги, которые может обнаружить ASAN.

CWE-121: Stack-based Buffer Overflow

CWE-122: Heap-based Buffer Overflow

CWE-416: Use After Free

В любом случае при обнаружение других багов из списка в процессе тестирования ПО это всё равно уcпех. Но в первую очередь нас будет интересовать именно эти баги, а пока перейдем к процессу работы самого ASan'a.

Как его использовать?​

1714484863694.png


Если уж говорить совсем простыми словами, то ASan работает по принципу "доступа за пределами границ" (out-of-bounds access). Аналогично с защитой стека - стековой куки, стек канарейкой. Когда в стеке у нас перезаписывается кука, мы знаем, что произошло переполнение. Другими словами, когда у нас что-то выходит за пределы и перезаписывается, ASan это детектит. В асане для это существует red зона и зона карантина. Red zone для отлова OOB, карантин для UAF.

ASan находит внешний доступ к памяти используя специальный аллокатор и используя инструментацию кода, тем самым обнаруживая доступ за пределы границ для стека, кучи и глобальных объектов.

Как я уже сказал выше AddressSanitizer уже встроен во многие компиляторы, и чтобы его задействовать достаточно указать специальный ключик при компиляции программы. Тогда проект соберется с Asan'ом, т.е. будет проинструментирован проверками.

Например у нас есть такой код.
C:
/*
* stack-buffer-overflow.c
* CWE-121: Stack-based Buffer Overflow
* https://cwe.mitre.org/data/definitions/121.html
*/

#include <stdio.h>
#include <string.h>

#define BUFSIZE 100
 
int main(int argc, char *argv[])
{
    char array[BUFSIZE];
 
    /* vulnerability */
    strcpy(array, argv[1]);
 
    printf("string: %s\n", array);
 
    return 0;
}

Компилируем

Код:
gcc stack.c -o stack -fsanitize=address

И запускаем с рандомными аргументами

Код:
./stack 1
./stack 1dasd

Программа не падает, и даже не определяет переполнение буфера в программе. Но если мы повторно запустим программу и передадим ей большую строку.

Код:
./stack AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...

То программа сразу упадет.

1714485086549.png


Всё дело в том, что Asan не анализирует программу, он анализирует исполнение программы. Как видно из скриншота, ASan любезно нам предоставил лог падения со всеми подробностями.

Пользоваться таким инструментом достаточно просто, вызываем (триггерим) баг и получаем лог от Asan'a.

Лог асана кстати можно улучшить, добавив такой ключик как "-g". Чтобы компилятор добавил отладочные символы. А так же для лучшей эффективности свяжем библиотеку асана статически, флагом "-static-libasan".

Код:
gcc stack.c -o stack -fsanitize=address -static-libasan -g

Ниже скриншот улучшенного лога асана. Улучшение заключается в том, что помимо оффсетов, нам указавают еще номер строки в исходном коде где находится сама уязвимость это очень удобно.

1714485140967.png


Еще пару примеров...

heap buffer overflow
C:
/*
* heap-buffer-overflow.c
* CWE-122: Heap-based Buffer Overflow
* https://cwe.mitre.org/data/definitions/122.html
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 100
 
int main(int argc, char *argv[])
{
    char *ptr = malloc(BUFSIZE);
 
    /* vulnerability */
    strcpy(ptr, argv[1]);
 
    printf("string: %s\n", ptr);
 
    free(ptr);
 
    return 0;
}

1714485197834.png


use after free
C:
/*
* use-after-free.c
* CWE-416: Use After Free
* https://cwe.mitre.org/data/definitions/416.html
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main(int argc, const char *argv[])
{
    char *array = malloc(100);
    free(array);
 
    /* vulnerability */
    strcpy(array, argv[1]);
 
    printf("string is: %s\n", array);
 
    return 0;
}

1714485285286.png


Объединим два примера выше.

C:
/*
* example_vuln.c
* heap overflow & use-after-free
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main(int argc, char *argv[])
{
    char *array = malloc(100);
 
    /* vulnerability - heap overflow */
    strcpy(array, argv[1]);
    printf("string: %s\n", array);
 
    free(array);
    printf("Input: ");
    /* vulnerability - use after free */
    scanf("%s", array);
 
    printf("string is: %s\n", array);
 
    return 0;
}

Тестируем

1714485379088.png


Как видно из этого скриншота мы обнаружила переполние буфера в куче, но не обнаружили UAF.

Протестируем еще раз

1714485407722.png


Тут мы успешно обнаружили использование памяти после освобождения, но не обнаружили heap buffer overflow.

Этот пример наглядно демонстрирует, то о чем я говорил ранее. Asan не анализирует программу, он анализирует исполнение программы. Другими словами если мы не вызовим баг мы не узнаем о существование уязвимости. В иделе асан должен применяться с фаззерами на основе покрытия (сoverage-guided). Чтобы как раз и находит подобные случаи.

Иногда при ручном тестировании или фаззинге нужно оптимизировать работу приложения, чтобы ускорить его на определенном участке. Как это сделать? Ведь ASan замедляет работу приложения в 2 раза. Всё на самом деле очень просто, для этого были добавлены опции игнорирования определенных функций, которые не нужно инструментировать.

Ниже пример макроса, при добавление которого можно указать какую функцию игнорировать при инструментировании кода.

C:
#if defined(__clang__) || defined (__GNUC__)
# define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
#else
# define ATTRIBUTE_NO_SANITIZE_ADDRESS
#endif
...
ATTRIBUTE_NO_SANITIZE_ADDRESS
void ThisFunctionWillNotBeInstrumented() {...

Посмотрим как это выглядит на практике. Напишем простую программу с уязвимостью.

C:
#if defined(__clang__) || defined (__GNUC__)
# define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
#else
# define ATTRIBUTE_NO_SANITIZE_ADDRESS
#endif

#include <stdio.h>
#include <string.h>

int vuln_func(char *s);

int main(void)
{
    char *param = "AAAAAAAAAAAAAAAAAAAA";
    int result=0;

    result = vuln_func(param); /* no instrumentation */
    printf("Len: %d\n", result);

    return 0;
}


//ATTRIBUTE_NO_SANITIZE_ADDRESS
int vuln_func(char *s)
{
    int len=0;
    char buff[40];

    strcpy(buff, s);
    printf("Buffer: %s\n", buff);

    len = strlen(buff);
    return len;
}

1714485536608.png


В примере 1 - обычное выполнение с инструментированием кода, но без длинной строки.
В примере 2 - передается большая строка и игнорируется уязвимая функция (которая не была инструментирована)
В примере 3 - так же передается большая строка, но происходит инструментирование всего кода.

В примере 2 видно, что мы можем отключать инструментирование определенных фунций, это выгодно, когда вы разобрали какую-то определенную функцию и вам известно, что в данной функции уж точно не будет багов и накладные вычислительные расходы вам не нужны при тестах. Или же чтобы выйграть в борьбе за ресурсы, мы можем тестировать ПО частями. Так как инструментированный код ASan'a в среднем съедает в 2 раза больше ресурсов.

Так же можно игнорировать сразу целый список функций не копаясь в сорцах, правда этот вариант доступен только для clang.

Код:
-fsanitize-blacklist=my_ignores.txt

Список команд GCC можно посмотреть тут.
gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html

Список команда для Clang
clang.llvm.org/docs/UsersManual.html#controlling-code-generation
clang.llvm.org/docs/ClangCommandLineReference.html#compilation-options

MSVC
learn.microsoft.com/en-us/cpp/sanitizers/asan?view=msvc-170#command-prompt
learn.microsoft.com/en-us/cpp/sanitizers/asan?view=msvc-170#ide-msbuild
learn.microsoft.com/en-us/cpp/sanitizers/asan?view=msvc-170#ide-cmake

XCode
developer.apple.com/documentation/xcode/diagnosing-memory-thread-and-crash-issues-early

1001 зиродей​

1714485588759.png


Теперь я думаю самое время рассмотреть реальные кейсы... Пока коллеги играют с веб запросами через curl, мы будем играть с исходниками и асаном. И так, чтобы протестировать ПО на предмет багов идем на гитхаб или любой другой хостинг проектов и выбираем любой проект который написан на С\С++. Собираем его из исходников с асаном и пытаемся в ручном режиме уронить программу. На вход программе подаём некорректные данные. Т.е в любом месте где программа обрабатывает данные мы пихаем на вход большую строку типа AAAAAAAAAAAAAAAAAA..... Короче говоря любыми всевозможными способами пихаем в программу некорректные данные.

Тут стоит сказать вот что... По хорошему мы должны скомбинировать какой-либо фаззер и наш асан для теста ПО. Но так, как эта статья посвящена конкретно инструменту AddressSaninizer мы исключим использование фаззеров =/

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

От вас требуетсялишь навык сборки и компиляции программ, разбираться во всяких confugure, make, cmake править мейки и добавлять флаги -fsanitize=address -static-libasan -g

Ниже я приведу несколько примитивных примеров, по некоторым соображениям... Которые должны дать вам пищу для размышления, о том, что вполне можно скачать любой понравившийся вам проект, затем собрать его с асаном, далее щупать его в эрогенных зонах.

Minitox клиент

/add TOX_ID AAAAAAAAAAA.......

1714485636210.png


лог
==20030==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x615000000280 at pc 0x55b92c934b51 bp 0x7fff37a8b510 sp 0x7fff37a8b500
WRITE of size 1 at 0x615000000280 thread T0
#0 0x55b92c934b50 in arepl_readline /home/weaver/test/software/minitox/minitox.c:502
#1 0x55b92c93a2b8 in repl_iterate /home/weaver/test/software/minitox/minitox.c:1263
#2 0x55b92c93ae4d in main /home/weaver/test/software/minitox/minitox.c:1344
#3 0x7fb3f2c29d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#4 0x7fb3f2c29e3f in __libc_start_main_impl ../csu/libc-start.c:392
#5 0x55b92c85c764 in _start (/home/weaver/test/software/minitox/minitox+0xd764)

0x615000000280 is located 0 bytes to the right of 512-byte region [0x615000000080,0x615000000280)
allocated by thread T0 here:
#0 0x55b92c8ec4b7 in malloc (/home/weaver/test/software/minitox/minitox+0x9d4b7)
#1 0x55b92c933452 in setup_arepl /home/weaver/test/software/minitox/minitox.c:390
#2 0x55b92c93add0 in main /home/weaver/test/software/minitox/minitox.c:1335
#3 0x7fb3f2c29d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/weaver/test/software/minitox/minitox.c:502 in arepl_readline
Shadow bytes around the buggy address:
0x0c2a7fff8000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff8010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a7fff8020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a7fff8030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a7fff8040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c2a7fff8050:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fff8060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a7fff8070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a7fff8080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a7fff8090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a7fff80a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==20030==ABORTING
Чем не зиродей? Хотя я уже показывал этот баг. Когда был шум с токсом. Да, можно сказать, что уязвимость находится в простой поделке, однако мы нашли уязвимость в чужом коде!!!


Smallchat

Пропускаем ввод никнейна в клиенте /nick и просто вводим "А"

1714485731545.png


лог
=================================================================
==79261==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000037 at pc 0x55d3589834e9 bp 0x7ffc069f0fe0 sp 0x7ffc069f0758
READ of size 8 at 0x602000000037 thread T0
#0 0x55d3589834e8 in printf_common(void*, char const*, __va_list_tag*) (/home/weaver/test/software/smallchat/smallchat-server+0x434e8)
#1 0x55d358985135 in vsnprintf (/home/weaver/test/software/smallchat/smallchat-server+0x45135)
#2 0x55d3589853c6 in __interceptor___snprintf_chk (/home/weaver/test/software/smallchat/smallchat-server+0x453c6)
#3 0x55d358949c1b in snprintf /usr/include/x86_64-linux-gnu/bits/stdio2.h:71
#4 0x55d358949c1b in main /home/weaver/test/software/smallchat/smallchat-server.c:255
#5 0x7fbe5f229d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#6 0x7fbe5f229e3f in __libc_start_main_impl ../csu/libc-start.c:392
#7 0x55d35894a074 in _start (/home/weaver/test/software/smallchat/smallchat-server+0xa074)

0x602000000037 is located 0 bytes to the right of 7-byte region [0x602000000030,0x602000000037)
allocated by thread T0 here:
#0 0x55d3589d9dc7 in malloc (/home/weaver/test/software/smallchat/smallchat-server+0x99dc7)
#1 0x55d358a2099c in chatMalloc /home/weaver/test/software/smallchat/chatlib.c:137

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/weaver/test/software/smallchat/smallchat-server+0x434e8) in printf_common(void*, char const*, __va_list_tag*)
Shadow bytes around the buggy address:
0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa 00 00 fa fa[07]fa fa fa fa fa fa fa fa fa
0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==79261==ABORTING
Далее мне попался код какого-то амера, который на ютубе делал уроки по использованию сокетов. Опять видим, что нам удалось найти баг, при чем в узком месте.


Alpha-Chat

./client 127.0.0.1 AAAA

1714485878748.png

лог
=================================================================
==105401==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffebf4bd7c8 at pc 0x55e962e69523 bp 0x7ffebf4bd510 sp 0x7ffebf4bccb8
WRITE of size 1000 at 0x7ffebf4bd7c8 thread T0
#0 0x55e962e69522 in memset (/home/weaver/test/software/Alpha-Chat/client+0x1e522)
#1 0x55e962f29e1d in get_username /home/weaver/test/software/Alpha-Chat/client.c:64
#2 0x55e962f2a1e8 in connect_to_server /home/weaver/test/software/Alpha-Chat/client.c:108
#3 0x55e962f2b37f in main /home/weaver/test/software/Alpha-Chat/client.c:309
#4 0x7f2aaac29d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#5 0x7f2aaac29e3f in __libc_start_main_impl ../csu/libc-start.c:392
#6 0x55e962e54414 in _start (/home/weaver/test/software/Alpha-Chat/client+0x9414)

Address 0x7ffebf4bd7c8 is located in stack of thread T0 at offset 88 in frame
#0 0x55e962f2b1e4 in main /home/weaver/test/software/Alpha-Chat/client.c:299

This frame has 2 object(s):
[48, 88) 'connection' (line 300)
[128, 256) 'file_descriptors' (line 301) <== Memory access at offset 88 partially underflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/home/weaver/test/software/Alpha-Chat/client+0x1e522) in memset
Shadow bytes around the buggy address:
0x100057e8faa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
0x100057e8fab0: f1 f1 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057e8fac0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057e8fad0: 00 00 00 00 00 04 f3 f3 f3 f3 f3 f3 f3 f3 00 00
0x100057e8fae0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
=>0x100057e8faf0: f1 f1 f1 f1 00 00 00 00 00[f2]f2 f2 f2 f2 00 00
0x100057e8fb00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f3 f3
0x100057e8fb10: f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057e8fb20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057e8fb30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057e8fb40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==105401==ABORTING
Этот пример просто кривого чата, который и вовсе не запустился, даже если на вход подать нормальные входные данные. На этот чат я не стал тратить свое время. Но баг есть баг, при чём это чужой код.



C-Chatroom

nc 127.0.0.1 8888 AAAAAAAAAAAAAA......

1714485975217.png


лог
=================================================================
==8685==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7f53aadfcc45 at pc 0x560776676eb9 bp 0x7f53aadfc190 sp 0x7f53aadfb908
READ of size 103 at 0x7f53aadfcc45 thread T3
#0 0x560776676eb8 in printf_common(void*, char const*, __va_list_tag*) (/home/weaver/test/software/c-chatroom/server.out+0x42eb8)
#1 0x560776678032 in __interceptor_vsprintf (/home/weaver/test/software/c-chatroom/server.out+0x44032)
#2 0x5607766782b6 in __interceptor___sprintf_chk (/home/weaver/test/software/c-chatroom/server.out+0x442b6)
#3 0x560776713c92 in sprintf /usr/include/x86_64-linux-gnu/bits/stdio2.h:38
#4 0x560776713c92 in client_handler src/server.c:70
#5 0x7f53af294ac2 in start_thread nptl/pthread_create.c:442
#6 0x7f53af32684f (/lib/x86_64-linux-gnu/libc.so.6+0x12684f)

Address 0x7f53aadfcc45 is located in stack of thread T3 at offset 197 in frame
#0 0x56077671341f in client_handler src/server.c:42

This frame has 3 object(s):
[32, 63) 'nickname' (line 44)
[96, 197) 'recv_buffer' (line 45)
[240, 441) 'send_buffer' (line 46) <== Memory access at offset 197 partially underflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
Thread T3 created by T0 here:
#0 0x5607766715b5 in __interceptor_pthread_create (/home/weaver/test/software/c-chatroom/server.out+0x3d5b5)
#1 0x56077663d90c in main src/server.c:141

SUMMARY: AddressSanitizer: stack-buffer-overflow (/home/weaver/test/software/c-chatroom/server.out+0x42eb8) in printf_common(void*, char const*, __va_list_tag*)
Shadow bytes around the buggy address:
0x0feaf55b7930: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0feaf55b7940: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0feaf55b7950: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0feaf55b7960: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0feaf55b7970: f1 f1 f1 f1 00 00 00 07 f2 f2 f2 f2 00 00 00 00
=>0x0feaf55b7980: 00 00 00 00 00 00 00 00[05]f2 f2 f2 f2 f2 00 00
0x0feaf55b7990: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0feaf55b79a0: 00 00 00 00 00 00 00 01 f3 f3 f3 f3 f3 f3 f3 f3
0x0feaf55b79b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0feaf55b79c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0feaf55b79d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==8685==ABORTING
Это пример почти хорошего программирования сокетов. Клиент мне не удалось уронить, как и сервер. Все фильтруется, ник, ввод, символы. Однако хакерская смекалка взяла вверх, по сколько влиять на сервер я мог только используя клиент, я подумал, а почему бы мне не подключится к серверу через netcat (который будет выступать в роли аналога клиента), и тогда я обойду фильтры встроенные в клиенте, чтобы накормить сервер вкусной строкой. Так и случилось, сервер туже секунду рухнул.

Софт для исследования можно брать не только с github, gitlab, но и так же с sourceforge.net.

Все это я делал не подыскивая специально уязвимые примеры т.е. рандомные примеры с асаном, а представьте если это все дело объединить с анализатором сорцов? Или фаззером, я думаю нас ждал бы успех на все 300% процентов. Продолжая разговор о поиске багов, я уже как-то говорил о том, что некоторые исследователи выкладывают скриншоты в свиттере и это действительно так. Возвращаясь к этому обсуждению, стоит сказать, что на различных баг-трек лентах так же встречаются логи асана. Чужие логи дают нам информацию о недавно закрытых багах, в том числе информацию об 0-day уязвимостях.

Искать логи можно например так
vulners.com/search?query=AddressSanitizer
К слову это специальный поисковик который парсит все существующие базы эксплойтов и все отчеты об уязвимостях.

Вот к примеру один из таких отчетов

vulners.com/talos/TALOS-2024-1931

В данном отчете присутствует логи асана и описание найденных уязвимостей в то числе как можно воспроизвести PoC. Кстати DICOM очень интересный формат файла и интересный вектор для атаки.

Еще один отчет

vulners.com/talos/TALOS-2024-1922

Который так же свидетельствует о наличие уязвимости в библиотеке которая отвечает за обработку биомедицинских сигналов =)

И таких отчетов т.е. логов асана в сети целая куча. Логи асана это очень ценная информация. Особенно если ты занимаешься разработкой эксплойтов. Не буду многословен скажу лишь, то что Asan это очень мощный инструмент который помогает отыскать быги в дебрях говнокода. Типичный процесс баг-хантинга выглядит следующим образом. Берем опенсурс продукт С\С++ смотрим его сорцы на предмет опасный функций типа strcpy, gets и тому подобных, определяем места в программе, где обрабатываются данные, т.е. анализируем логику кода, сам же проект собираем с асаном и запускаем какой нибудь фаззер на основе покрытия типа AFL ждем креш = профит. Как итог $$$$ \ CVE который расширяет ваше портфолио.

Заключение​

На Asan'е не заканчивается история, существуют и другие инструменты. После того, как был написан ASan, люди подумали, а не плохо бы сделать аналогичные инструменты для тестирования. Так и родилась группа инструментов под категорией санитайзеров =) В основном санитайзеры делятся на два типа, те которые работают в ядре, и те которые работают в пользовательском пространстве.

По мимом ASan'а существуют такие инструменты как: HWASan, KASAN, BoKASAN, GWP-ASan, KFENCE, KMSAN, KCSAN, KTSAN, , UBSan (IntSan, BoundSan), MSan, LSan, TSan etc...

Ниже будет краткое описание.

Примечание: Большинство Sanitizer'ов хранятся в репозитории ядра Linux и не размещаютя на github.

HWASan (Hardware-assisted AddressSanitizer) - это тот же самый ASan, но с аппаратной поддержкой. HWAsan доступен только на Android 10 и выше и только на оборудовании AArch64 (ARM64). HWAsan более производительный, чем ASan из-за аппаратной поддержки.
Документация:

KASAN (Kernel Address Sanitizer) - это тот же ASan, но он предназначен для ядра. KASAN добавлен в ядро Linux начиная с v4.0.
Документация:

BoKASAN (Binary-only Kernel Address Sanitizer) - это тот же KASAN, но для работы с закрытым исходным кодом. Он появился в прошлом году (2023) и идеально подходит для тестирования коммерческих ОС c закрытым исходным кодом. Работает на основе DBI.
Событие:
Git:

GWP-ASan (Will Provide Allocation SANity) - это тот же ASAN, но он разработан с учетом промышленной разработки и тестов экосистемы Android. Так же у него более лучшая производительность по сравнению с Asan. Он интегрирован в Android 11 и Chromium. Заточен под user-mode, так же он не требует исходного кода и работает уже с готовыми билдами по принципу DBI.
Документация:

KFENCE (Kernel Electric-Fence) - это еще один санитайзер для ядра. KFENCE создан на основе GWP-ASan, инструмента для пользовательского пространства с аналогичными свойствами. KFENCE добавлен в ядро Linux начиная с v5.12. Ключевые отличия KFENCE от KASAN в производительности. У KFENCE с этим нет проблем и поэтому он применяется в промышленном производстве на рабочих машинах, а не на тестовых. К тому же KFENCE позволяет маштабировать тесты.
Документация:

KMSAN (KernelMemorySanitizer) - этот санитайзер работает с ядром. Задача этого санитайзера заключается в поиске неинициализированного доступа к памяти в ядре Linux. Работает по принципу CTI. Начиная с Linux 6.1+ содержит полностью работающую реализацию KMSAN, которую можно использовать из коробки.

KCSAN (Kernel Concurrency Sanitizer) - это еще один санитайзер для ядра. KCSAN специально нацелен на гонки данных, распространенную проблему в параллельном программировании внутри ядра. Он добавлен в ядро Linux начиная с v5.8. но официально он еще не интегрирован и все еще находится на стадии разработки.
Документация:

KTSAN (Kernel Thread Sanitizer) - это санитайзер так же работает с ядром, и так нацелен поиск состояний гонки (race condition). Аналогично KSCAN так же ищет дата рейсы, но различие их заключается в реализации и подходе к обнаружения гонок.

Примечание
KCSAN:
В первую очередь фокусируется на обнаружении гонок за данными между простым и маркированным доступом . Это означает, что он определяет ситуации, когда один поток обращается к общей памяти без надлежащей синхронизации, в то время как другой поток может читать или записывать в то же место.
KTSAN: Наоборот фокусируется на общих гонках данных, происходящих между любыми потоками, независимо от того, отмечены обращения к памяти или нет. Это обеспечивает более широкий охват для обнаружения состояний гонок.

UBSan (Undefined Behavior Sanitizer) - еще один санитайзер, который состоит из двух дополнительных инструментов IntSan и BoundSan. IntSan (Integer Overflow Sanitizer) как можно понять из названия обнаруживает целочисленные переполнения. А BoundSan (BoundsSanitizer) обнаруживает доступ к памяти за пределами границ (OOB), это всяческого рода проверки массивов. UBSan универсальный инструмент который может работать как с ядром, так и пользовательскоми приложениями. Добавлен в ядро начиная с v4.5
Документация:

MSan (MemorySanitizer) - этот санитайзер проверяет операции чтения из неинициализированной памяти.Неинициализированные значения возникают, когда память, выделенная в стеке или куче, считывается до ее записи. В основном применяется для user-mode приложений, в редкий случаях может применятся для отдельных модулей ядра (но лучше отдать эту задачу KernelMemorySanitizer).

LSan (LeakSanitizer) - это санитайзер применяется для поиска утечек памяти. Работает он c user-mode приложениями. LSan перехватывает функции выделения и освобождения памяти, такие как malloc() и free() и отслеживает их. LSan обычно работает в паре с ASan'ом.

TSan (ThreadSanitizer) - аналогично KTSAN так же применяется для поиска дата рейсов и дедлоков. Но заточен под user-mode приложения.

Вопросы о KASAN и других санитайзерах можно всегда задать в списке рассылки kasan-dev@googlegroups.com.

На последок хочу сказать, что поиск багов это не такое уж и сложное занятие, главное в этом деле смекалка и упорство. А комбинация различных методов и инструментов в совокупности помогают действительно отыскать поистине уникальные баги. Из этой статьи можно сделать следующий вывод, что бинарный баг-баунти не такой уж и сложный. Надеюсь вам понравился мой рассказ об AddressSanitizer'е и да прибудит с вами темная сила =)

Ссылки

Combining compile-time and run-time instrumentation for testing tools

swsys.ru/index.php?page=article&id=3593&lang=en

Finding Memory Bugs with Google Address Sanitizer (ASAN) on Microcontrollers
mcuoneclipse.com/2021/05/31/finding-memory-bugs-with-google-address-sanitizer-asan-on-microcontrollers

AddressSanitizer, или как сделать программы на C\С++ надежнее и безопаснее
youtube.com/watch?v=vKtNwALHb2k

Анатомия AddressSanitizer
youtube.com/watch?v=7WyBAUJ8UA8


Автор: weaver
Написано специально для xss.pro (с)
 
держи предварительный лайк, а вникать буду позже, тут на неделю вдумчивого чтения :D
 
Пожалуйста, обратите внимание, что пользователь заблокирован
держи предварительный лайк, а вникать буду позже, тут на неделю вдумчивого чтения :D
Да ну брось, я максимально упростил статью. Без перепечатывания документации, но документация как по мне скудная что у гугла, что шланга. Могли бы сделать НОРМАЛЬНУЮ.

А все что нужно знать, так это то, что Asan состоит из двух компонентов инструментального модуля и runtime библиотеки. Задача инструментального модуля заключается в том, чтобы изменить код для проверки теневого состояния при каждом доступе к памяти, а задачей runtime библиотеки является управление теневой памятью.

Ну и то, что

Подобный код вида
C:
*address = 0x41414141;  // или int getAddress = *address;

Инструментируется следующим образом

C:
if (IsPoisoned(address)) {
  ReportError(address, kAccessSize, kIsWrite);
}
*address = 0x41414141;  // или int getAddress = *address;

Если адрес не валидный, т.е. память отравлена, тогда репортуем ошибку. ASan инструментирует код перед каждой операцией c указателем.

А ключевой концепт asan'a это теневая память.

виртуальное адресное пространство разделено на две части.

1) Основная память приложения, эта память используется обычным кодом приложения (где приложение хранит свои данные).
2) Теневая память это копия основной памяти, которая хранит состояние этой памяти.

Эти две области памяти расположены рядом друг с другом, и они не пересекаютя между собой.

Всё это в документации написано, я просто не стал это объяснять еще раз. Главное это git clone .... + test asan
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Нужна еще подробная статья как скомпилировать Asan, вот это было бы кстати.
Нужен был пример, где человек условно берет любой чужой код, пусть даже это будет студенческий проект и находит в нём баг. Важен сам факт, что мы может взять любой опенсурс проект и собрать его с асаном, а дальше ловим баги.
 
Нужен был пример, где человек условно берет любой чужой код, пусть даже это будет студенческий проект и находит в нём баг. Важен сам факт, что мы может взять любой опенсурс проект и собрать его с асаном, а дальше ловим баги.
Так вот и не хватает информации, что нужно скачать для винды Visual Studio , Clang как импортировать чужой код и куда записать строку AdressSanitazera , если используем андройд, то нужно скачать Android Studio как туда вставить чужой код, как править потом bullid.grandle. В youtube нет на русском инструкции по компиляции. Да и как подружить его с фаззерами.

UPD за такое обучение даже не жалко денег отдать ))
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Так вот и не хватает информации, что нужно скачать для винды Visual Studio , Clang как импортировать чужой код и куда записать строку AdressSanitazera , если используем андройд, то нужно скачать Android Studio как туда вставить чужой код, как править потом bullid.grandle. В youtube нет на русском инструкции по компиляции. Да и как подружить его с фаззерами.

UPD за такое обучение даже не жалко денег отдать ))
Компиляция и сборка программ это отдельный вид искусства... Для Visual Studio асан устанавливается как отдельный компонент. А дальше надо просто в проекте галочку поставить, прежде чем его собирать. Я обычно нахожу какой нибудь Makefile и редактирую его. Что касается Android то с ним не работал, хотя по андройду у меня есть одна задумка для статьи. Главное, что в обще есть документация, хоть на китайском, дело, как мне кажется в примерах и скудной документации. Просто сегодня я вскрыл так сказать, то о чем многие знают, но особо не говорят, что можно искать уязвимости просто компилируя сорцы и подавая некорректный ввод.

Я кстати когда лениво дописывал эту статью, так же тестил и разные библиотеки, компилировал обертку где всячески по разному вызывал API и смотрел как себя поведет код. Из забавных случаев в FreeType постоянно мемори лик был, хотя я правильно всё инициализировал и освобождал...

лог
=================================================================
==34132==ERROR: LeakSanitizer: detected memory leaks

Indirect leak of 1896 byte(s) in 23 object(s) allocated from:
#0 0x55de95be2137 in malloc (/home/weaver/test/software/freetype-2.13.2/fontcrash+0x98137)
#1 0x7f5e8e7455c8 in ft_mem_qalloc /home/weaver/test/software/freetype-2.13.2/src/base/ftutil.c:75
#2 0x7f5e8e7455c8 in ft_mem_alloc /home/weaver/test/software/freetype-2.13.2/src/base/ftutil.c:54

Indirect leak of 400 byte(s) in 1 object(s) allocated from:
#0 0x55de95be2137 in malloc (/home/weaver/test/software/freetype-2.13.2/fontcrash+0x98137)
#1 0x7f5e8e7416ca in ft_mem_qalloc /home/weaver/test/software/freetype-2.13.2/src/base/ftutil.c:75
#2 0x7f5e8e7416ca in ft_mem_alloc /home/weaver/test/software/freetype-2.13.2/src/base/ftutil.c:54
#3 0x7f5e8e7416ca in FT_New_Library /home/weaver/test/software/freetype-2.13.2/src/base/ftobjs.c:5504

Indirect leak of 120 byte(s) in 5 object(s) allocated from:
#0 0x55de95be2137 in malloc (/home/weaver/test/software/freetype-2.13.2/fontcrash+0x98137)
#1 0x7f5e8e749ffa in ft_mem_qalloc /home/weaver/test/software/freetype-2.13.2/src/base/ftutil.c:75
#2 0x7f5e8e749ffa in ft_add_renderer /home/weaver/test/software/freetype-2.13.2/src/base/ftobjs.c:4599
#3 0x7f5e8e749ffa in FT_Add_Module /home/weaver/test/software/freetype-2.13.2/src/base/ftobjs.c:5134

Indirect leak of 32 byte(s) in 1 object(s) allocated from:
#0 0x55de95be2137 in malloc (/home/weaver/test/software/freetype-2.13.2/fontcrash+0x98137)
#1 0x7f5e8e73da71 in FT_New_Memory builds/unix/ftsystem.c:408
#2 0x7f5e8e229d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

SUMMARY: AddressSanitizer: 2448 byte(s) leaked in 30 allocation(s).
 
здесь начало и общее пояснение - как для школьников, очень доступно.

https://ost.51cto.com/posts/16209 - здесь поинформативней, но оригинальный ли код\текст я не смотрела
 
Пожалуйста, обратите внимание, что пользователь заблокирован
здесь начало и общее пояснение - как для школьников, очень доступно.

https://ost.51cto.com/posts/16209 - здесь поинформативней, но оригинальный ли код\текст я не смотрела
Это хреновые статьи. Первая вообще какой-то огрызок. Там один пример с документации гугла и скриншот с whitepaper asan'a. Во второй просто базовые примеры. Обычная шалонная статья.

Изначально искал материалы с конференции ZeroNights где был workshop по ASan'у или нормальную статью, чтобы её перевести и добавить на форум, все эти статьи я видел. Но они не очень. Они все шаблонные. Нормальную я только одну нашел, где показано как применять асан для микроконтроллеров эту статью я добавил в раздел ссылок. По факту во всех статьях показананы примеры компиляции уязвимых примеров, что есть и моей статье, а так же рассказано за теневую память. Мне же нужно было показать это с другой точки зрения, чтобы мы может пойди на любой хостинг проектов взять софт и скомпилировать его для поиска багов. Проще посмотреть 2 видео и прочитать мою статью. А дальше идти на sourceforce, github, gitlab что искать 0-day. Советую всем начинать с не больших проектов.
 
Это хреновые статьи
лол. А народ сетует что у тебя сложно. Ты свой уровень с другими не ровняй. А я время поторатила чтобы другим попытаться помочь, ну и расширить чей-то кругозор.
Как всегда зря. Заебись. Последний раз. Один шлак...
 
Пожалуйста, обратите внимание, что пользователь заблокирован
лол. А народ сетует что у тебя сложно. Ты свой уровень с другими не ровняй. А я время поторатила чтобы другим попытаться помочь, ну и расширить чей-то кругозор.
Как всегда зря. Заебись. Последний раз. Один шлак...
Да какое сложно... Теже базовые примеры... + небольшая практика есть. Документацию не перепечатывал. Чтобы не усложнять. Самое забавное, что в той же первой статье, что ты скинула, не сказано для чего нужно вобще это всё, к примеру не сказано для для чего нужно отключать инструментацию. Пытливые умы сразу поймут для чего нужно. Я же на прямую говорю, для оптимизации, чтобы при фаззинге не хавало много ресурсов.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх