概述
随着流行的缓冲区溢出攻击的增加,越来越多程序员开始使用带有大小,即有长度限制的字符串函数,如strncpy()
和strncat()
。尽管这种趋势令人十分鼓舞,但通常的标准C
字符串函数并不是专为此而设计的。本文介绍另一种直观的,一致的,天生安全的字符串拷贝API
。
当函数 strncpy()
和 strncat()
作为 strcpy()
和 strcat()
的安全版本来使用时,仍然存在一些安全隐患。
- 这两函数以不同的,非直观的方式来处理
NUL
结束符和长度参数,即使有经验的程序员也会混淆。 - 发生字符串截断时,也不容易检查。
strncpy()
函数使用0
来填充剩余的目标字符串空间,以招致性能下降。在所有这些问题之中,由长度参数引起的混淆以及与NUL
结束符相关的问题最严重。在审核OpenBSD
源代码树的潜在安全漏洞时,我们发现strncpy()
和strncat()
猖獗误用的情况。尽管并非所有的误用都会导致可被利用的安全漏洞,但清楚地表明使用strncpy()
和strncat()
来实施安全的字符串操作这一准则已普遍受到误解。两个替代函数strlcpy()
和strlcat()
被提议通过提出一个字符串拷贝安全的API
来解决这些问题(参阅图1 函数原型)。这两函数保证产生包含NUL
的字符串,以长度即字符串按占用字节的数量作为入口参数,并且提供简便的方式来检查是否有字符串截断。两者均不会清零未使用的目标空间。
引言
1996 年年中,笔者和OpenBSD
项目的其它成员一起担任审核OpenBSD
源代码树的工作,以寻找安全问题,并强调缓冲区溢出问题。缓冲区溢出问题最近在论坛上获得广泛的关注,并且也被广泛利用。我们发现大量的溢出是由于使用sprintf()
,strcpy()
和strcat()
而造成无长度界限的字符串拷贝,在循环里操纵字符串时没有显式检查字符串长度也是元凶之一。除此之外,我们也发现在很多场合下,程序员已使用strncpy()
和strncat()
进行安全的字符串操纵,但未能领会这些API
的精妙之处。
因此在审核代码时,我们发现不仅有必要去检查是否使用不安全的函数,如strcpy()
和strcat()
,同时也要检查是是否有函数strncpy()
和strncat()
的不正确使用。检查是否正确使用并非总是显而易见,特别是使用“静态”变量或使用由malloc()
分配的缓冲区时,这些缓冲区总是预先就填满了NUL
结束符。我们得到一个结论:需要十分安全的函数来替代strncpy()
和strncat()
,从根本上简化程序员的工作,同时也使代码审核变得更容易。