Я ищу, чтобы узнать, почему strncpy считается небезопасным. Кто-нибудь имеет какую-либо документацию об этом или примеры использования эксплойта?
Почему strncpy небезопасен?
Ответ 1
Взгляните на этот сайт; это довольно подробное объяснение. В принципе, strncpy()
не требует завершения NUL и поэтому подвержен множеству эксплойтов.
Ответ 2
Исходная проблема, очевидно, заключается в том, что strcpy (3) не был безопасная память, так что злоумышленник может предоставить строку длиннее, чем буфер, который будет перезаписывать код в стеке, и, если он будет тщательно организован, может выполнить произвольный код от злоумышленника.
Но strncpy (3) имеет другую проблему, поскольку в каждом случае в пункте назначения он не отправляет нулевое завершение. (Предположим, что длина источника больше, чем целевой буфер.) В будущих операциях может ожидаться соответствие строк с нулевым завершением между буферами одинакового размера и сбоями, расположенными ниже по потоку, когда результат копируется в третий буфер.
Использование strncpy (3) лучше, чем strcpy (3), но такие вещи, как strlcpy (3), еще лучше.
Ответ 3
Чтобы безопасно использовать strncpy, нужно либо (1) вручную вставить нулевой символ в буфер результатов, (2) знать, что буфер заканчивается нулем заблаговременно, а передать (длина-1) на strncpy или (3 ) знают, что буфер никогда не будет скопирован с использованием любого метода, который не свяжет его длину с длиной буфера.
Важно отметить, что strncpy будет заполнять нуль в буфере за скопированной строкой, в то время как другие варианты strcpy, ограниченные по длине, не будут. В некоторых случаях это может быть утечка производительности, но в других случаях это преимущество безопасности. Например, если вы использовали strlcpy для копирования "supercalifragilisticexpalidocious" в буфер, а затем для копирования "it", буфер будет содержать "it ^ ercalifragilisticexpalidocious ^" (используя "^" для представления нулевого байта). Если буфер скопирован в формат фиксированного размера, дополнительные данные могут маркироваться вместе с ним.
Ответ 4
Вопрос основан на "загруженной" предпосылке, которая делает этот вопрос недействительным.
Суть в том, что strncpy
не считается небезопасным и никогда не считался небезопасным. Единственными претензиями на "неуверенность", которые могут быть связаны с этой функцией, являются широкие требования общей незащищенности модели памяти C и языка C. (Но это, очевидно, совершенно другая тема).
В рамках языка C ошибочное мнение о какой-то "неуверенности", присущей strncpy
, вытекает из широко распространенного сомнительного шаблона использования strncpy
для "безопасного копирования строк", то есть что-то, что эта функция не делает и никогда не предназначался для этого. Такое использование действительно сильно подвержено ошибкам. Но даже если вы ставите знак равенства между "склонностью к ошибкам" и "небезопасным", это все еще проблема использования (т.е. Проблема отсутствия образования), а не проблема strncpy
.
В принципе, можно сказать, что единственная проблема с strncpy
- это неудачное именование, которое заставляет программистов-новичков предположить, что они понимают, что делает эта функция вместо фактического чтения спецификации. Если посмотреть на имя функции, некомпетентный программист предполагает, что strncpy
является "безопасной версией" strcpy
, тогда как в действительности эти две функции полностью не связаны.
Точно такое же требование может быть сделано против оператора деления, например. Как известно большинству из вас, один из наиболее часто задаваемых вопросов о языке C выглядит следующим образом: "Я предположил, что 1/2
будет оцениваться до 0.5
, но вместо этого я получил 0
. Почему?" Тем не менее, мы не утверждаем, что оператор деления небезопасен только потому, что начинающие языки склонны неправильно истолковывать его поведение.
В другом примере мы не называем функции генерации псевдослучайных чисел "небезопасными" только потому, что некомпетентные программисты часто неприятно удивляются тем, что их вывод не является действительно случайным.
Именно так оно и есть с функцией strncpy
. Так же, как требуется время для начинающих программистов, чтобы узнать, что на самом деле делают генераторы псевдослучайных чисел, требуется время, чтобы узнать, что на самом деле делает strncpy
. Требуется время, чтобы узнать, что strncpy
- это функция преобразования, предназначенная для преобразования строк с нулевым завершением в строки фиксированной ширины. Требуется время, чтобы узнать, что strncpy
не имеет абсолютно никакого отношения к "безопасному копированию строк" и не может быть осмысленно использован для этой цели.
Конечно, студенту-языку обычно требуется намного больше времени, чтобы узнать цель strncpy
, чем разобраться с оператором деления. Однако это является основанием для любых претензий "отсутствия безопасности" в отношении strncpy
.
P.S. Документ CERT, связанный в принятом ответе, посвящен именно тому, что: для демонстрации неуверенности типичного некомпетентного злоупотребления функцией strncpy
как "безопасной" версии strcpy
. Это никоим образом не означает, что сам strncpy
как-то небезопасен.
Ответ 5
Путь Git 2.19 (Q3 2018) обнаруживает, что слишком сложно использовать функции API системы, такие как strcat()
; strncpy()
;... и запрещает эти функции в этой кодовой базе.
См. Фиксацию e488b7a, фиксацию cc8fdae, фиксацию 1b11b64 (24 июля 2018 года) и совершение c8af66a (26 июля 2018 года) Джеффом Кингом (peff
).
(Слияние с Юнио С Хамано - gitster
- в совершении e28daf2, 15 августа 2018 года)
banned.h
: markstrcat()
как запрещенФункция
strcat()
имеет все те же проблемы с переполнением, что иstrcpy()
.
И в качестве бонуса легко оказаться случайно квадратичным, так как каждый последующий вызов должен пройти через существующую строку.Последний
strcat()
ушел в f063d38 (демон: используйте cld-> env_array при повторном появлении, 2015-09-24, Git 2.7.0).
В общем случае,strcat()
может быть заменен либо динамической строкой (strbuf
илиxstrfmt
), либоxsnprintf
если вы знаете, что длина ограничена.
Ответ 6
Худшая ситуация возникает, когда ваша буферная память источника и получателя перекрывается друг с другом. Поэтому избегайте использования strncpy, если вы чувствуете, что в вашей программе может возникнуть ситуация перекрытия. Вместо strncpy вы можете использовать функцию memmove в сценарии перекрытия.
Ниже я описываю простой пример, описывающий strncpy в перекрывающемся сценарии.
#include <stdio.h>
#include <string.h>
int main() {
char aszMessage[10] ="12345"; //Source Buffer
short siLen=4; // Length of byte you want to copy
strncpy(aszMessage + 2,aszMessage+1,siLen);//Here memory overlap
printf("\n\n\tMessage = %s\n",aszMessage);
return 0;
}
Здесь я принимаю, выход должен быть 122345, но здесь выдается 122222, то есть самый большой резервный сценарий strncpy.
Эта проблема может быть решена с помощью функции memove.
#include <stdio.h>
#include <string.h>
int main() {
char aszMessage[10] ="12345"; //Source Buffer
short siLen=4; // Length of byte you want to copy
memmove(aszMessage + 2,aszMessage+1,siLen);//Here memory overlap
printf("\n\n\tMessage = %s\n",aszMessage);
return 0;
}
Теперь я получаю выход 122345 желания.
Для более подробной информации вы можете увидеть эту ссылку http://aticleworld.com/how-to-use-strncpy-and-how-to-write-your-own-strncpy/
Ответ 7
Опасности strncpy, _snprintf и wcsncpy должны быть одинаково хорошо известны, но, по-видимому, это не так. Эти функции позволяют указать размер буфера, но - и это действительно важно - они не гарантируют нулевое завершение. Если вы попросите эти функции написать больше символов, чем заполнить буфер, то они остановятся - таким образом, избегая переполнения буфера, но они не будут завершать нуль буфера. Чтобы правильно использовать эти функции, вам нужно сделать такую ерунду.
Пожалуйста, обратитесь к следующей ссылке для справки!!!
https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/