CERT C: Rec. WIN00-C

Будьте специфичны при динамической загрузке библиотек

Описание

Определение правила

Будьте специфичны при динамической загрузке библиотек.[1]

Реализация Polyspace

Эта проверка проверяет на наличие следующих проблем:

  • Загрузкой библиотеки из относительного пути может управлять внешний актёр.

  • Библиотека загружена из пути, управляемого извне.

Примеры

расширить все

Проблема

Загрузкой библиотеки из относительного пути может управлять внешний агент, обнаруживающий стандартные программы загрузки библиотеки, которые загружают внешнюю библиотеку. Если вы загружаете библиотеку с помощью относительного пути или без пути, Bug Finder помечает стандартную программу загрузки как дефект.

Риск

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

Зафиксировать

При загрузке внешней библиотеки задайте полный путь.

Пример - Открыть библиотеку с именем библиотеки
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <stdio.h>

void relative_path()
{
    dlopen("liberty.dll",RTLD_LAZY);
}

В этом примере dlopen открывает liberty библиотеку, вызывая только имя библиотеки. Однако этот вызов библиотеки использует относительный путь для поиска библиотеки, что небезопасно.

Коррекция - используйте полный путь к библиотеке

Одна из возможных коррекций - использовать полный путь к библиотеке, когда вы загружаете ее в свою программу.

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

void relative_path()
{
    dlopen("/home/my_libs/library/liberty.dll",RTLD_LAZY);
}
Проблема

Библиотека, загруженная из пути, управляемого извне, ищет библиотеки, загруженные из фиксированных или управляемых путей. Если непреднамеренные актёры могут управлять одним или несколькими местоположениями на этом фиксированном пути, Bug Finder поднимает дефект.

Риск

Если атакующий знает или управляет путем, который вы используете для загрузки библиотеки, атакующий может измениться:

  • Библиотека, которую загружает программа, заменяющая предполагаемую библиотеку и команды.

  • Окружение, в которой библиотека выполняет, давая злоумышленнику непреднамеренные разрешения и возможности.

Зафиксировать

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

Другое решение - использовать функции, которые требуют явных путей. Для примера, system() не требует полного пути, потому что может использовать PATH переменная окружения. Однако execl() и execv() требуется полный путь.

Пример - Вызов пользовательской библиотеки
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include <limits.h>

enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};

void* taintedpathlib() {
    void* libhandle = NULL;
    char lib[SIZE128] = "";
    char* userpath = getenv("LD_LIBRARY_PATH");
    strncpy(lib, userpath, SIZE128);
    strcat(lib, "/libX.so");
    libhandle = dlopen(lib, 0x00001);
    return libhandle;
}

Этот пример загружает библиотеку libX.so от переменного окружения LD_LIBRARY_PATH. Атакующий может изменить путь к библиотеке в этой переменной окружения. Фактическая библиотека, которую вы загружаете, может отличаться от той, что вы собираетесь.

Коррекция - Изменение и проверка пути

Одна из возможных коррекций - изменить способ получения пути к библиотеке и проверить путь к библиотеке перед открытием библиотеки. Этот пример получает путь как входной параметр. Затем путь проверяется, чтобы убедиться, что библиотека не находится под /usr/.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include <limits.h>

enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};

/* Function to sanitize a string */
int sanitize_str(char* s, size_t n) {
    /* strlen is used here as a kind of firewall for tainted string errors */
    int res = (strlen(s) > 0 && strlen(s) < n);
    return res;
}
void* taintedpathlib(char* userpath) {
    void* libhandle = NULL;
    if (sanitize_str(userpath, SIZE128)) {
        char lib[SIZE128] = "";

        if (strncmp(userpath, "/usr", 4)!=0) {
            strncpy(lib, userpath, SIZE128);
            strcat(lib, "/libX.so");
            libhandle = dlopen(lib, RTLD_LAZY);    
        }
    }
    return libhandle;
}

Проверяйте информацию

Группа: Rec. 51. Microsoft Windows (WIN)
Введенный в R2019a

[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОН И/ИЛИ ЕГО ИНЖЕНЕРНОГО ИНСТИТУТА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ НА БАЗИСЕ «КАК ЕСТЬ». УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБОГО ВОПРОСА, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИЮ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ КОММЕРЧЕСКОЙ ВЫГОДЫ, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Это программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллон или его Институтом программной инженерии.