Одним из методов поиска уязвимостей в программном обеспечении является использование анализаторов исходных текстов. В данной посте хочу рассказать об одном из них, а именно о RATS (Rough Auditing Tool for Security). Начать именно с этой утилиты, решил потому что упоминания о ней встречались не раз в уважаемых мной источниках, а именно тут, тут и еще здесь. Однако реального примера использования нигде не было, поэтому я решил рассказать о RATS подробнее.
И так, RATS был создан компанией Fortify, предназначен для поиска ошибок в коде, написанном на C/C++,Perl, Ruby, PHP и Python, и, что важно, распространяется бесплатно. Особых чудес от этой утилиты ждать не стоит, однако, места использования «рискованных» функций мы найдем.
Установка
Начнем с установки RATS, далее пример для ОС Debian (wheezy), пакет RATS можно взять здесь. Качаем deb-пакет wget ftp.us.debian.org/debian/pool/main/r/rats/rats_2.3-1_amd64.deb и устанавливаем sudo dpkg –i /путь/пакет.deb.
Проверим все ли корректно установилось, для этого в консоли набираем rats:
$ rats
Entries in perl database: 33
Entries in ruby database: 46
Entries in python database: 62
Entries in c database: 334
Entries in php database: 55
Total lines analyzed: 0
Total time 0.000010 seconds
0 lines per second
Здесь мы видим, сколько шаблонов типичных ошибок содержится в базе RATS (версии 2.3-1).
Пример 1
Теперь давайте опробуем RATS «в бою». Для этого напишем код заведомо содержащий классическую ошибку переполнения буфера и сохраним его в файл vuln_code1.c:
#include <string.h>
int main (int argc, char **argv)
{
char buffer[10];
strcpy(buffer, argv[1]);
}
Теперь покажем это файл RATS: $ rats vuln_code1.c
Analyzing vuln_code1.c
vuln_code1.c:4: High: fixed size local buffer
Extra care should be taken to ensure that character arrays that are allocated
on the stack are used safely. They are prime targets for buffer overflow
attacks.
vuln_code1.c:5: High: strcpy
Check to be sure that argument 2 passed to this function call will not copy
more data than can be handled, resulting in a buffer overflow.
Total lines analyzed: 7
Total time 0.000154 seconds
45454 lines per second
RATS сообщает нам о двух ошибках, причем обеим он присваивает высокий (high) уровень опасности.
Первая «fixed size local buffer» — использование фиксированного размера буфера в строке 4 — char buffer[10].
Вторая «buffer overflow» — переполнение буфера в строке 5 – при использовании функции strcpy(). Если вместо функции strcpy() использовать gets(), то сообщение RATS будет выглядеть вот так:
vuln_code1.c:5: High: gets
Gets is unsafe!!! No bounds checking is performed, buffer is easily overflowable by user. Use fgets(buf, size, stdin) instead
Пример 2
Проверим как RATS реагирует на код содержащий уязвимость форматной строки, для этого пишем код с дефектом, функция printf получает входную строку, в соответствии с которой функция ожидает, что перед ее вызовом в стек были занесены два аргумента если данную программу запустить со спецификаторами "%x %x" в качестве параметра, можно увидеть содержимое 4 байт стека.
#include <stdio.h>
int main(int argс, char* argv[ ])
{
if(argc > 1)
printf(argv[1]);
return 0;
}
RATS увидел ошибку и сообщил:
vuln_code3.c:5: High: printf
Check to be sure that the non-constant format string passed as argument 1 to
this function call does not come from an untrusted source that could have added
formatting characters that the code is not prepared to handle.
Пример 3
В этом примере используем код содержащий ошибку переполнения буфера при взаимодействии с переменными окружения:
#include <stdlib.h>
int main(int argc, char *argv[ ])
{
char *env;
char buf[100];
env = getenv("PATH");
if ( env == NULL ) { return 0; }
sprintf(buf, "%s", env);
return 0;
}
Здесь RATS нашел 3 ошибки:
vuln_code4.c:5: High: fixed size local buffer
Extra care should be taken to ensure that character arrays that are allocated
on the stack are used safely. They are prime targets for buffer overflow
attacks.
vuln_code4.c:6: High: getenv
Environment variables are highly untrustable input. They may be of any length,
and contain any data. Do not make any assumptions regarding content or length.
If at all possible avoid using them, and if it is necessary, sanitize them and truncate
them to a reasonable length.
Так как переменные окружения могу быть любой длинны, нам стоит внимательно проверять какой длинны буфер мы выделяем для работы с ними.
vuln_code4.c:8: High: sprintf
Check to be sure that the format string passed as argument 2 to this function
call does not come from an untrusted source that could have added formatting
characters that the code is not prepared to handle. Additionally, the format
string could contain `%s' without precision that could result in a buffer
overflow.
Пример 4
Посмотрим, как обстоят дела с другими языками программирования, и протестируем RATS на уязвимом perl-скрипте:
open(f,$filename);
while(<f>)
{
print;
}
если на вход такого скрипта подать «|команда», то команда будет исполнена. В базе RATS такая уязвимость есть, он советует нам внимательно анализировать входные данные при использовании функции open():
test9.pl:1: Medium: open
The filename argument of open should be carefully checked if it is being created with any user-supplied string as a compontent of it. Strings should be checked for occurences of path backtracking/relative path components (../ as an example), or nulls, which may cause the underlying C call to interpret the filename to open differently than expected. It is also important to make sure that the final filename does not end in a "|", as this will cause the path to be executed.
Особенности использования
- в качестве проверяемого объекта можно задавать директорию содержащую исходные тексты, RATS самостоятельно найдет и проверит все вложенные файлы
- флаг -l позволяет принудительно задать язык проверяемого исходника
- флаг -noheader позволяет отключить отображения информационного заголовка
- флаг -h отображает список и описание других флагов
Вывод
За давностью лет не стоит рассматривать RATS как всеобъемлющий анализатор уязвимостей в серьезных проектах, однако как учебный вариант для выявления и понимания хрестоматийных ошибок он вполне пригоден.
Ссылки
Подробнее об уязвимостях переполнения буфера: www.securitylab.ru/contest/212095.php
Хорошая, но сложная книга об анализе и поиске уязвимостей в ПО: www.ozon.ru/context/detail/id/5238324/
Статья, о безопасности в cgi-скриптах: www.getinfo.ru/article358.html
Автор: pabloz