ISO/IEC TS 17961 [taintsink]

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

Описание

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

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

Реализация Polyspace

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

  • Испорченный размер массива переменной длины.

  • Разыменование указателя с испорченным смещением.

  • Доступ к массиву с испорченным индексом.

Примеры

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

Проблема

Испорченный размер массива переменной длины обнаруживает массивы переменной длины (VLA), размер которых получен из небезопасного источника.

Риск

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

Если размер не положителен, поведение VLA не определено. Ваша программа работает не так, как ожидалось.

Если размер не ограничен, VLA может вызвать истощение памяти или переполнение стека.

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

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

Пример - Входной параметр, используемый как размер VLA
#include<stdio.h>
#inclule<stdlib.h>
#define LIM 40

long squaredSum(int size) {

	int tabvla[size];
	long res = 0;
	for (int i=0 ; i<LIM-1 ; ++i) {
		tabvla[i] = i*i;
		res += tabvla[i];
	}
	return res;
}
int main(){
	int size;
	scanf("%d",&size);
	//...
	long result = squaredSum(size);
	//...
	return 0;
}

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

Коррекция - Проверяйте размер VLA

Одной из возможных коррекций является проверка переменной size перед созданием массива переменной длины. Этот пример проверяет, больше ли размер 0 и меньше 40, перед созданием VLA

#include <stdio.h>
#include <stdlib.h>
#define LIM 40

long squaredSum(int size) {
	long res = 0;
	if (size>0 && size<LIM){
		int tabvla[size];
		for (int i=0 ; i<size || i<LIM-1 ; ++i) {
			tabvla[i] = i*i;
			res += tabvla[i];
		}
	}else{
		res = -1;
	}
	return res;
}
int main(){
	int size;
	scanf("%d",&size);
	//...
	long result = squaredSum(size);
	//...
	return 0;
}
Проблема

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

Эта проверка фокусируется на динамически выделенных буферах. Для статических смещений буфера смотрите Array access with tainted index.

Риск

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

  • Подземный поток буфера/андеррайт или запись в память перед началом буфера.

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

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

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

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

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

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

Пример - Массив указателей на размежевание
#include <stdio.h>
#include <stdlib.h>
enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};
extern void read_pint(int*);

int taintedptroffset(void) {
    int offset;
    scanf("%d",&offset);
    int* pint = (int*)calloc(SIZE10, sizeof(int));
    int c = 0;
    if(pint) {
        /* Filling array */
        read_pint(pint);
        c = pint[offset];
        free(pint);
    }
    return c;
}

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

Коррекция - Проверяйте индекс перед дереференцией

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

#include <stdlib.h>
#include <stdio.h>
enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};
extern void read_pint(int*);

int taintedptroffset(void) {
    int offset;
    scanf("%d",&offset);
    int* pint = (int*)calloc(SIZE10, sizeof(int));
    int c = 0;
    if (pint) {
        /* Filling array */
        read_pint(pint);
        if (offset>0 && offset<SIZE10) {
            c = pint[offset];
        }
        free(pint);
    }
    return c;
}
Проблема

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

Риск

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

  • Buffer underflow/underwrite - запись в память перед началом буфера.

  • Переполнение буфера - запись в память после окончания буфера.

  • Перечитывание буфера - доступ к памяти после окончания целевого буфера.

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

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

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

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

Пример - Используйте индекс для возврата значения буфера
#include <stdlib.h>
#include <stdio.h>
#define SIZE100 100
extern int tab[SIZE100];
static int tainted_int_source(void) {
  return strtol(getenv("INDEX"),NULL,10);
}
int taintedarrayindex(void) {
	int num = tainted_int_source();
    return tab[num];  
}

В этом примере индекс num обращается к массиву tab. Функция не проверяет, если num находится внутри области значений tab.

Коррекция - Проверяйте область значений перед использованием

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

#include <stdlib.h>
#include <stdio.h>
#define SIZE100 100
extern int tab[SIZE100];
static int tainted_int_source(void) {
	return strtol(getenv("INDEX"),NULL,10);
}
int taintedarrayindex(void) {
	int num = tainted_int_source();
	if (num >= 0 && num < SIZE100) {
		return tab[num]; 
	} else {
		return -1;
	}
}

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

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

[1] Выдержки из стандарта «Техническая спецификация ISO/IEC TS 17961 - 2013-11-15» воспроизводятся с согласия АФНОР. Только оригинальный и полный текст стандарта, опубликованный AFNOR Editions - доступный через веб-сайт www.boutique.afnor.org - имеет нормативное значение.