ISO/IEC TS 17961 [taintformatio]

Используя испорченное значение, чтобы записать в объект с помощью отформатированной функции ввода или вывода

Описание

Управляйте определением

Используя испорченное значение, чтобы записать в объект с помощью отформатированного ввода или вывода function.[1]

Реализация Polyspace

Это средство проверки проверяет на эти проблемы:

  • Переполнение буфера от неправильного спецификатора формата строки.

  • Целевое переполнение буфера в обработке строк.

  • Недопустимое использование стандартной библиотечной подпрограммы.

  • Недопустимое использование стандартной библиотеки представляет стандартную программу в виде строки.

  • Испорченный NULL или не пустая отключенная строка.

  • Испорченный спецификатор формата строки.

  • Недопустимое использование стандартной библиотеки представляет стандартную программу в виде строки.

  • Использование опасной стандартной функции.

Примеры

развернуть все

Проблема

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

Риск

Если спецификатор формата задает точность, которая больше размера буфера памяти, переполнение происходит. Переполнение может вызвать неожиданное поведение, такое как повреждение памяти.

Фиксация

Используйте спецификатор формата, который совместим с размером буфера памяти.

Пример - переполнение буфера памяти
#include <stdio.h>

void func (char *str[]) {
    char buf[32];
    sscanf(str[1], "%33c", buf);
}

В этом примере, buf может содержать 32 char элементы. Поэтому спецификатор формата %33c вызывает переполнение буфера.

Коррекция — использует меньшую точность в спецификаторе формата

Одна возможная коррекция должна использовать меньшую точность в спецификаторе формата.

#include <stdio.h>

void func (char *str[]) {
    char buf[32];
    sscanf(str[1], "%32c", buf);
}
Проблема

Целевое переполнение буфера в обработке строк происходит, когда определенные функции обработки строк пишут в свой целевой буферный аргумент при смещении, больше, чем buffer size.

Например, при вызове функционального sprintf(char* buffer, const char* format), вы используете постоянную строку format из большего размера, чем buffer.

Риск

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

Фиксация

Одно возможное решение состоит в том, чтобы использовать альтернативные функции, чтобы ограничить количество записанных символов. Например:

  • Если вы используете sprintf чтобы записать отформатированные данные в строку, используйте snprintf, _snprintf или sprintf_s вместо этого осуществлять управление длиной. В качестве альтернативы используйте asprintf автоматически выделить память, требуемую для целевого буфера.

  • Если вы используете vsprintf чтобы записать отформатированные данные от списка аргументов переменной до строки, используйте vsnprintf или vsprintf_s вместо этого осуществлять управление длиной.

  • Если вы используете wcscpy чтобы скопировать широкую строку, используйте wcsncpy, wcslcpy, или wcscpy_s вместо этого осуществлять управление длиной.

Другое возможное решение состоит в том, чтобы увеличить buffer size.

Пример - переполнение буфера в sprintf Использование
#include <stdio.h>

void func(void) {
    char buffer[20];
    char *fmt_string = "This is a very long string, it does not fit in the buffer";

    sprintf(buffer, fmt_string);
}

В этом примере, buffer может содержать 20 char элементы, но fmt_string имеет больший размер.

Коррекция — использует snprintf Вместо sprintf

Одна возможная коррекция должна использовать snprintf функция, чтобы осуществить управление длиной.

#include <stdio.h>

void func(void) {
    char buffer[20];
    char *fmt_string = "This is a very long string, it does not fit in the buffer";

    snprintf(buffer, 20, fmt_string);
}
Проблема

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

Риск

Недействительные аргументы к стандартной библиотечной функции приводят к неопределенному поведению.

Фиксация

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

Смотрите примеры мер ниже.

Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.

Пример – вызов printf Без строки
#include <stdio.h>
#include <stdlib.h>

void print_null(void) {

  printf(NULL); 
}

Функциональный printf берет только входные параметры строки или спецификаторы формата. В этой функции входным значением является NULL, который не является допустимой строкой.

Коррекция — использует совместимые входные параметры

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

#include <stdio.h>

void print_null(void) {
    char zero_val = '0';
    printf((const char*)zero_val); 
}
Проблема

Недопустимое использование стандартной стандартной программы строки библиотеки происходит, когда библиотечная функция строки вызвана недействительными аргументами.

Риск

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

Фиксация

Фиксация зависит от стандартной библиотечной функции, вовлеченной в дефект. В некоторых случаях можно ограничить аргументы функции перед вызовом функции. Например, если strcpy функция:

char * strcpy(char * destination, const char* source);
попытки скопировать слишком много байтов в целевой аргумент по сравнению с доступным буфером, ограничьте исходный аргумент перед вызовом strcpy. В некоторых случаях можно использовать альтернативную функцию, чтобы избежать ошибки. Например, вместо strcpy, можно использовать strncpy управлять количеством скопированных байтов. См. также Интерпретируют Результаты Bug Finder в Пользовательском интерфейсе Рабочего стола Polyspace.

Смотрите примеры мер ниже.

Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.

Пример - недопустимое использование стандартной ошибки стандартной программы строки библиотеки
 #include <string.h>
 #include <stdio.h>
 
 char* Copy_String(void)
 {
  char *res;
  char gbuffer[5],text[20]="ABCDEFGHIJKL";

  res=strcpy(gbuffer,text); 
  /* Error: Size of text is less than gbuffer */

  return(res);
 }

Строка text больше в размере, чем gbuffer. Поэтому функциональный strcpy не может скопировать text в gbuffer.

Коррекция — использует допустимые аргументы

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

#include <string.h>
 #include <stdio.h>
 
 char* Copy_String(void)
 {
  char *res;
  /*Fix: gbuffer has equal or larger size than text */
  char gbuffer[20],text[20]="ABCDEFGHIJKL";

  res=strcpy(gbuffer,text);

  return(res);
 }
Проблема

Эта проблема происходит, когда строки из незащищенных источников используются в стандартных программах обработки строк, которые неявно разыменовывают буфер строки, например, strcpy или sprintf.

Средство проверки не повышает дефекта для строки, возвращенной от вызова до scanf- семейство variadic функции. Точно так же никакой дефект не повышен, когда вы передаете строку с %s спецификатор к printf- семейство variadic функции.

Риск

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

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

Фиксация

Подтвердите строку, прежде чем вы будете использовать ее. Проверяйте что:

  • Строка не является ПУСТОЙ.

  • Строка отключена пустым указателем

  • Размер строки совпадает с ожидаемым размером.

Пример – получение строки от входного параметра
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define SIZE128 128
#define MAX 40
extern void print_str(const char*);
void warningMsg(void)
{
	char userstr[MAX];
	read(0,userstr,MAX);
	char str[SIZE128] = "Warning: ";
	strncat(str, userstr, SIZE128-(strlen(str)+1));
	print_str(str);
}



void errorMsg(void)
{
	char userstr[MAX];
	read(0,userstr,MAX);
	char str[SIZE128] = "Error: ";
	strncat(str, userstr, SIZE128-(strlen(str)+1));
	print_str(str);
}

В этом примере, строка str конкатенирован с аргументом userstr. Значение userstr неизвестно. Если размер userstr больше доступного пробела, переполнение конкатенации.

Коррекция 1 — подтверждает данные

Одна возможная коррекция должна проверять размер userstr и убедитесь, что строка отключена пустым указателем перед использованием его в strncat. Этот пример использует функцию помощника, sansitize_str, подтверждать строку. Дефекты сконцентрированы в этой функции.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define SIZE128 128
#define MAX 40
extern void print_str(const char*);
int sanitize_str(char* s) {
	int res = 0; 
	if (s && (strlen(s) > 0)) { // Defect only raised here 
		// - string is not null
		// - string has a positive and limited size
		// - TAINTED_STRING on strlen used as a firewall
		res = 1;
	}
	return res; 
}
void warningMsg(void)
{
	char userstr[MAX];
	read(0,userstr,MAX);
	char str[SIZE128] = "Warning: ";
	if (sanitize_str(userstr))	
		strncat(str, userstr, SIZE128-(strlen(str)+1));
	print_str(str);
}
Коррекция 2 — подтверждает данные

Другая возможная коррекция должна вызвать функциональный errorMsg и warningMsg с определенными строками.

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

#define SIZE128 128

extern void print_str(const char*);

void warningMsg(char* userstr)
{
    char str[SIZE128] = "Warning: ";
    strncat(str, userstr, SIZE128-(strlen(str)+1));
    print_str(str);
}

void errorMsg(char* userstr)
{
  char str[SIZE128] = "Error: ";
  strncat(str, userstr, SIZE128-(strlen(str)+1));
  print_str(str);
}

int manageSensorValue(int sensorValue) {
  int ret = sensorValue;
  if ( sensorValue < 0 ) {
    errorMsg("sensor value should be positive");
    exit(1);
  } else if ( sensorValue > 50 ) {
    warningMsg("sensor value greater than 50 (applying threshold)...");
    sensorValue = 50;
  }
  
  return sensorValue;
}
Проблема

Эта проблема происходит когда printf- разработайте использование функций спецификатор формата, созданный из незащищенных источников.

Риск

Если вы используете внешне управляемые элементы, чтобы отформатировать строку, можно вызвать проблемы представления данных или переполнение буфера. Атакующий может использовать эти элементы форматирования строки, чтобы просмотреть содержимое стека с помощью %x или запишите в стек с помощью %n.

Фиксация

Передайте статическую строку функциям строки формата. Эта фиксация гарантирует, что внешний агент не может управлять строкой.

Другой возможная фиксация должен позволить только ожидаемое количество аргументов. Если возможно, используйте функции, которые не поддерживают уязвимый %n оператор в строках формата.

Пример – получает элементы от ввода данных пользователем
#include <stdio.h>
#include <unistd.h>
#define MAX 40
void taintedstringformat(void) {
	char userstr[MAX];
	read(0,userstr,MAX);
	printf(userstr);   
}

Этот пример распечатывает входной параметр userstr. Строка неизвестна. Если это содержит элементы, такие как %, printf может интерпретировать userstr как формат строки вместо строки, заставляя вашу программу отказать.

Коррекция — печать как строка

Одна возможная коррекция должна распечатать userstr явным образом как строка так, чтобы не было никакой неоднозначности.

#include <stdio.h>
#include <unistd.h>
#define MAX 40
void taintedstringformat(void) {
	char userstr[MAX];
	read(0,userstr,MAX);
	printf("%.20s", userstr);;   
}
Проблема

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

Опасная функцияРискните уровнемБолее безопасная функция
getsПо сути опасный — Вы не можете управлять длиной входа от консоли.fgets
cinПо сути опасный — Вы не можете управлять длиной входа от консоли.Избегайте или вызовы предисловий cin с cin.width.
strcpyВозможно опасный — Если исходная длина больше места назначения, переполнение буфера может произойти.strncpy
stpcpyВозможно опасный — Если исходная длина больше места назначения, переполнение буфера может произойти.stpncpy
lstrcpy или StrCpyВозможно опасный — Если исходная длина больше места назначения, переполнение буфера может произойти.StringCbCopy, StringCchCopy, strncpy, strcpy_s, или strlcpy
strcatВозможно опасный — Если конкатенированный результат больше места назначения, переполнение буфера может произойти.strncat, strlcat, или strcat_s
lstrcat или StrCatВозможно опасный — Если конкатенированный результат больше места назначения, переполнение буфера может произойти.StringCbCat, StringCchCat, strncay, strcat_s, или strlcat
wcpcpyВозможно опасный — Если исходная длина больше места назначения, переполнение буфера может произойти.wcpncpy
wcscatВозможно опасный — Если конкатенированный результат больше места назначения, переполнение буфера может произойти.wcsncat, wcslcat, или wcncat_s
wcscpyВозможно опасный — Если исходная длина больше места назначения, переполнение буфера может произойти.wcsncpy
sprintfВозможно опасный — Если продолжительность выхода зависит от неизвестных длин или значений, переполнение буфера может произойти.snprintf
vsprintfВозможно опасный — Если продолжительность выхода зависит от неизвестных длин или значений, переполнение буфера может произойти.vsnprintf
Риск

Эти функции могут вызвать переполнение буфера, которое атакующие могут использовать, чтобы пропитать вашу программу.

Фиксация

Фиксация зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Bug Finder в Пользовательском интерфейсе Рабочего стола Polyspace.

Смотрите примеры мер ниже.

Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.

Пример - Используя sprintf
#include <stdio.h>
#include <string.h>
#include <iostream>

#define BUFF_SIZE 128


int dangerous_func(char *str)
{
    char dst[BUFF_SIZE];
    int r = 0;

    if (sprintf(dst, "%s", str) == 1)
    {
        r += 1;
        dst[BUFF_SIZE-1] = '\0';
    }
    
    return r;
}

Эта функция, взятая в качестве примера, использует sprintf скопировать строку str к dst. Однако, если str больше, чем буфер, sprintf может вызвать переполнение буфера.

Коррекция — использует snprintf с Buffer Size

Одна возможная коррекция должна использовать snprintf вместо этого и задайте buffer size.

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

#define BUFF_SIZE 128


int dangerous_func(char *str)
{
    char dst[BUFF_SIZE];
    int r = 0;

    if (snprintf(dst, sizeof(dst), "%s", str) == 1)
    {
        r += 1;
        dst[BUFF_SIZE-1] = '\0';
    }
    
    return r;
}

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

Разрешимость: неразрешимый
Введенный в R2019a

[1]  Выписки из стандарта "Техническая характеристика ISO/IEC TS 17961 - 2013-11-15" воспроизводятся с соглашением о AFNOR. Только исходный и полный текст стандарта, как опубликовано Выпусками AFNOR - доступный через веб-сайт www.boutique.afnor.org - имеет нормативное значение.