Secure C 和大学 - 接受缓冲区溢出培训

发布于 2024-07-13 05:18:05 字数 1453 浏览 6 评论 0原文

我最近完成了大学的 C 课程。因此,我当然缺乏经验。

一些大学倾向于教学生安全编程,或至少一些元素。 甚至还有视频(取自此处)。

据我所知,在 C 中复制字符串需要 strcpy 或 string.h 函数。 在日常编程中如何安全地使用它? 您是否有一些函数可以处理分配以防止缓冲区溢出? 有 CERT 安全编码标准对于C。 它提供了示例和合规解决方案:

int main(int argc, char *argv[]) {
  /* ... */
  char prog_name[128];
  strcpy(prog_name, argv[0]);
  /* ... */
}

他们的替代方案是:

int main(int argc, char *argv[]) {
  /* ... */
  char *prog_name = (char *)malloc(strlen(argv[0])+1);
  if (prog_name != NULL) {
    strcpy(prog_name, argv[0]);
  }
  else {
    /* Couldn't get the memory - recover */
  }
  /* ... */
}

取自此处,第二个示例

但据我所知,这只是更具挑战性,更多的代码,更多的工作。 为什么没有人改变图书馆本身? 或者至少为什么没有人提供一个安全的替代库或函数来以正确的方式处理这个问题?

谢谢阅读, 威希

I recently finished a university course in C. Therefore I lack experience, of course.

Some universities tend to teach their students secure programming, or at least some elements. There's even a video (taken from here).

Being in C, copying strings, requires - as far as I know - strcpy or string.h functions. How do you use it securely in every-day programming?
Do you have some functions, which handle allocation to prevent buffer overflows? There's the CERT secure coding standard for C. It's offering examples and compliant solutions:

int main(int argc, char *argv[]) {
  /* ... */
  char prog_name[128];
  strcpy(prog_name, argv[0]);
  /* ... */
}

And their alternative is:

int main(int argc, char *argv[]) {
  /* ... */
  char *prog_name = (char *)malloc(strlen(argv[0])+1);
  if (prog_name != NULL) {
    strcpy(prog_name, argv[0]);
  }
  else {
    /* Couldn't get the memory - recover */
  }
  /* ... */
}

Taken from here, 2nd example.

But as far as I get it that's just more challenging, more code, more work. Why does no one change the library itself? Or at least why does no one provide a secure alternative library or functions, which handle this in the right way?

Thanks for reading,
wishi

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

原谅过去的我 2024-07-20 05:18:05

用于此目的的 Posix 函数(几乎在每个系统上都可用)是 strdup()。 如果您不想分配新内存并且已经有一个想要使用的缓冲区,则可以使用 strcpy(),但您最好知道该缓冲区有多大以及字符串是否适合其中。 如果您不知道字符串是否适合,可以使用 strncpy() 来复制给定数量的字符。 因此,您可以将复制量限制为缓冲区大小。

除此之外,还有许多 Sting 库以不同的方式管理字符串大小。

由于您将其标记为 C++:有 std::string 可以为您完成所有内存管理,并且不会给您带来这些问题。

The Posix function for this (available on nearly every system) is strdup(). strcpy() is used if you don't want to allocate new memory and already have a buffer you want to use, but then you better known how big that buffer is and if the string fits in it. If you don't know if the string fits, there is strncpy() that just copies a given number of characters. So you can limit the copied amount to your buffers size.

And besides of that, there are lots of sting libraries that manage string sizes in different ways.

And since you tagged it C++: There is std::string that does all the memory management for you and doesn't give you these problems.

み零 2024-07-20 05:18:05

OpenBSD 中的 l(strlcpy、strlcat)函数通常比 n 函数更好,它们更快、更容易安全使用,但是它们是非标准的。 然而,它们是 BSD 许可的,因此您可以在任何程序中包含已知的良好实现,这样您就可以跨平台且安全。

对于Windows,如果不关心可移植性,可以使用*_s函数。

the l (strlcpy, strlcat) functions from OpenBSD are usually better than the n functions, they are both faster and easier to use securely, but they are nonstandard. However, they are BSD licensed so you can include a known good implementation in any program so you can be both cross platform and secure.

For Windows, if you don't care about portability, you can use *_s functions.

岁吢 2024-07-20 05:18:05

使用strncpy

#define BUFSIZE 127
int main(int argc, char *argv[]) {
  /* ... */
  char prog_name[BUFSIZE + 1];
  strncpy(prog_name, argv[0], BUFSIZE);
  progname[BUFSIZE]= '\0';
  /* ... */
}

*大多数 str* 函数都有 n* 个版本。

Use strncpy:

#define BUFSIZE 127
int main(int argc, char *argv[]) {
  /* ... */
  char prog_name[BUFSIZE + 1];
  strncpy(prog_name, argv[0], BUFSIZE);
  progname[BUFSIZE]= '\0';
  /* ... */
}

There are *n* versions for most str* functions.

请你别敷衍 2024-07-20 05:18:05

如果我理解正确的话,你真正的问题是为什么 API 函数没有变得更安全。

原因之一是 C 库是遗留的(现在改变它已经太晚了)。

然而,主要原因是该库被设计为简约的,因此它只做最少的事情,并且用户有责任确保它被正确调用。 如果它进行了过多的检查,那么每次调用时都会付出代价,即使用户可以出于其他原因保证不会发生问题。 这在许多 API 中非常常见。

话虽这么说,有足够的库可以提供更安全的替代方案,但它们只是不属于标准库的一部分。 此外,许多从事高级工作的人都使用 C++,C++ 具有用于许多此类工作的标准类库。

If I understand correctly, your real question is why the API functions are not made more secure.

One reason reason is that C library is legacy (too late to change it now).

The main reason, however, is that the library is designed to be minimalistic, so that it does the bare minimum and it is the user's responsibility to ensure that it is called correctly. If it was doing any excessive checks, then a price would be paid every time it is called, even if the user can assure for other reasons that no problem is going to occur. This is very very common in many APIs.

That being said, there are enough libraries that provide safer alternatives, they're just not part of the standard library. Also, many people who do higher level stuff work with C++, that has standard class libraries for many of those things.

尘曦 2024-07-20 05:18:05

事实上,微软确实提供了 CRT 功能的安全替代方案。 我认识的每个人都讨厌它们,并禁用了不应该使用旧函数的警告。 如果你想要安全的东西,也许你应该使用 C++。 然后是 STL 字符串或 Qt 之类的东西。

好吧,或者您使用 .NET 或 Java 等平台,它们通常不会遇到这些问题(您的应用程序可能会崩溃,但无法通过缓冲区溢出将代码注入到您的应用程序中)。

编辑:
启用数据执行保护/NX(Vista 和.NET 的默认设置)后,这对于传统平台来说也不应该成为问题。

Actually, Microsoft did provide secure alternatives to the CRT functions. Everybody I know hates them though and disables the warning that you shouldn't use the old functions. If you want something secure, maybe you should use C++. And then either STL strings or something like Qt.

Well, or you go to platforms like .NET or Java, which usually doesn't suffer from these problems (your app might crash, but no way to inject code into your app through a buffer overflow).

Edit:
With Data Execution Prevention / NX enabled (default for Vista and .NET), this shouldn't be a problem for traditional platforms as well.

り繁华旳梦境 2024-07-20 05:18:05
int main
(
    int argc, 
    char *argV[]
) 
{
   char prog_name[128];
   if (strlen(argV[0]) < sizeof(prog_name))
   {
       strcpy(prog_name, argV[0]);
   }
   else
   {
       printf("%s is too large for the internal buffer\n", argV[0]);
   }

   return 0;
}
int main
(
    int argc, 
    char *argV[]
) 
{
   char prog_name[128];
   if (strlen(argV[0]) < sizeof(prog_name))
   {
       strcpy(prog_name, argV[0]);
   }
   else
   {
       printf("%s is too large for the internal buffer\n", argV[0]);
   }

   return 0;
}
迷爱 2024-07-20 05:18:05

也许您会找到这个问题的有用阅读答案

Maybe you would find useful reading answers to this question

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文