编写安全的C和安全英汉习语 [英] Writing Secure C and Secure C Idioms

查看:108
本文介绍了编写安全的C和安全英汉习语的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  

一般的男人不希望是免费的。他只是想是安全的。 - H. L.曼肯


我试图写的很安全的C.下面我列出一些我用​​的技术,并要求他们是因为我认为他们是安全。请不要犹豫,我撕code / preconceptions撕成碎片。该发现即使是最微不足道的漏洞,或者教我一个新的想法会的高度重视任何回答

从流中读取:

按照 GNU C编程教程函数getline:


  

getline函数会
  自动放大块
  根据需要,经由realloc的存储器
  功能,所以从来没有短缺
  空间 - 一个原因是函数getline
  那么安全。 [..]注意函数getline可以
  安全地处理您的输入线,无
  不管有多长。


我认为应该函数getline,所有输入,prevent一个缓冲区溢出从流读取时发生的。

malloc的失败则返回NULL:

如果的malloc遇到错误的malloc返回NULL指针。这presents安全风险,因为人们仍然可以申请指针运算为NULL(为0x0)的指针,因此维基百科建议

  / *为int型的十个元素的数组分配空间。 * /
为int * PTR =(INT *)malloc的(10 * sizeof的(INT));
如果(PTR == NULL){
    / *内存无法分配,程序应该处理
       在这里的错误是适当的。 * /
}

安全sscanf的:

在使用 sscanf的我已经得到了在分配的大小的习惯要被提取字符串输入字符串的大小希望避免溢出的可能性。例如:

 为const char * inputStr =a01234b4567c;
为const char * formatStr =A%[0-9] B%[0-9] C:
字符* STR1 [strlen的(inputStr)];
字符* STR2 [strlen的(inputStr)];sscanf的(inputStr,formatStr,STR1,STR2);

由于str1和STR2是inputStr的大小和不超过的strlen(inputStr)更多的字符可从inputStr被读取,它似乎是不可能的,因为所有可能的值作为inputStr引起缓冲区溢出?


  • 我是正确的?在那里我没有想到的?
  • 奇怪的角落案件
  • 是否有更好的方式来写这个?有图书馆已经解决了吗?

一般问题:

虽然我已经张贴了大量的问题,我不希望任何人来回答他们。这些问题是更多指引到各种各样的答案,我要寻找的。我真的想学习安全Ç心态。


  • 还有什么其他安全英汉习语是那里?

  • 请我需要什么样的角落情况下的总是检查

  • 如何编写单元测试来执行这些规则?

  • 如何执行在可测试性约束或可证明正确的方式?

  • 任何建议静态/动态分析工艺或工具对C?

  • 安全ç的做法,你遵循什么,你如何证明他们对自己和他人?

资源:

许多资源的从该答案借


解决方案

  1. 从一个流中读取

这是函数getline()将根据需要自动放大的内存块,这意味着,这可能被用作拒绝服务攻击,因为它将是微不足道产生输入,这是这么长时间它会耗尽的进程可用内存(或者更糟,系统!)。一旦内存外的一个条件时,其他漏洞也可能会发挥作用。 code在低/无记忆的行为是很少漂亮,也很辛苦,以predict。恕我直言,这是安全的一切合理设置上限,特别是在安全敏感的应用。

此外(如你所提到的特殊字符预测),函数getline()只给你一个缓冲;它不会使任何保证对缓冲区的内容(作为安全是完全依赖于应用程序)。所以消毒的输入仍然处理的一个重要组成部分,并验证用户数据


  1. 的sscanf

我会倾向于preFER使用正前pression库,并已非常狭窄用于用户数据定义的正则表达式,而不是使用的sscanf 。这样,您就可以在输入时进行验证的一个很好的协议。


  1. 一般性意见


    • 模糊测试工具可生成该随机输入(有效和无效),可以用来测试你的输入处理

    • 缓冲区管理是至关重要的:缓冲区溢出,下溢,出内存不足

    • 比赛条件中另有安全code被利用

    • 二进制文件可以被操纵,以注入无效值或超大值代入头,所以文件格式code必须是坚如磐石的,不承担二进制数据是有效的

    • 临时文件往往是安全问题的来源,必须谨慎管理

    • code注射液可用于替换恶意版本的系统或运行时库调用

    • 插件提供了一个攻击向量巨大

    • 作为一般原则,我建议有明确定义的接口,其中用户数据(或应用程序之外的任何数据),假设无效的,敌对的,直到它被处理,消毒和验证,并为用户数据输入的唯一途径应用


"The average man does not want to be free. He simply wants to be safe." - H. L. Menken

I am attempting to write very secure C. Below I list some of the techniques I use and ask are they as secure as I think they are. Please don't not hesitate to tear my code/preconceptions to shreds. Any answer that finds even the most trivial vulnerability or teaches me a new idea will be highly valued.

Reading from a stream:

According to the GNU C Programming Tutorial getline:

The getline function will automatically enlarge the block of memory as needed, via the realloc function, so there is never a shortage of space -- one reason why getline is so safe. [..] Notice that getline can safely handle your line of input, no matter how long it is.

I assume that getline should, under all inputs, prevent a buffer overflow from occurring when reading from a stream.

  • Is my assumption correct? Are there inputs and/or allocation schemes under which this could lead to an exploit? For instance what if the first character from the stream is some bizarre control character, maybe 0x08 BACKSPACE (ctl-H).
  • Has any work been done to mathematically prove getline as secure?

Malloc Returns Null on Failure:

If malloc encounters an error malloc returns a NULL pointer. This presents a security risk since one can still apply pointer arithmetic to a NULL (0x0) pointer, thus wikipedia recommends

/* Allocate space for an array with ten elements of type int. */
int *ptr = (int*)malloc(10 * sizeof (int));
if (ptr == NULL) {
    /* Memory could not be allocated, the program should handle 
       the error here as appropriate. */
} 

Secure sscanf:

When using sscanf I've gotten in the habit of allocating the size to-be-extracted strings to the size of the input string hopefully avoiding the possibility of an overrun. For example:

const char *inputStr = "a01234b4567c";
const char *formatStr = "a%[0-9]b%[0-9]c":
char *str1[strlen(inputStr)];
char *str2[strlen(inputStr)];

sscanf(inputStr, formatStr, str1, str2);

Because str1 and str2 are the size of the inputStr and no more characters than strlen(inputStr) can be read from inputStr, it seems impossible, given all possible values for the inputStr to cause a buffer overflow?

  • Am I correct? Are there strange corner cases I haven't thought of?
  • Are there better ways to write this? Libraries that have already solved it?

General Questions:

While I've posted a large number of questions I don't expect anyone to answer all of them. The questions are more of guideline to the sorts of answers I am looking for. I really want to learn the secure C mindset.

  • What other secure C idioms are out there?
  • What corner cases do I need to always check?
  • How can I write unit tests to enforce these rules?
  • How can I enforce constraints in a testability or provably correct way?
  • Any recommended static/dynamic analysis technics or tools for C?
  • What secure C practices do you follow and how do you justify them to yourself and others?

Resources:

Many of the resources were borrowed from the answers.

解决方案

  1. Reading from a stream

The fact that getline() "will automatically enlarge the block of memory as needed" means that this could be used as a denial-of-service attack, as it would be trivial to generate an input that was so long it would exhaust the available memory for the process (or worse, the system!). Once an out-of-memory condition occurs, other vulnerabilities may also come into play. The behaviour of code in low/no memory is rarely nice, and very hard to predict. IMHO it is safer to set reasonable upper bounds on everything, especially in security-sensitive applications.

Furthermore (as you anticipate by mentioning special characters), getline() only gives you a buffer; it does not make any guarantees about the contents of the buffer (as the safety is entirely application-dependent). So sanitising the input is still an essential part of processing and validating user data.

  1. sscanf

I would tend to prefer to use a regular expression library, and have very narrowly defined regexps for user data, rather than use sscanf. This way you can perform a good deal of validation at the time of input.

  1. General comments

    • Fuzzing tools are available which generate random input (both valid and invalid) that can be used to test your input handling
    • Buffer management is critical: buffer overflows, underflows, out-of-memory
    • Race conditions can be exploited in otherwise secure code
    • Binary files could be manipulated to inject invalid values or oversized values into headers, so file format code must be rock-solid and not assume binary data is valid
    • Temporary files can often be a source of security issues, and must be carefully managed
    • Code injection can be used to replace system or runtime library calls with malicious versions
    • Plugins provide a huge vector for attack
    • As a general principle, I would suggest having clearly defined interfaces where user data (or any data from outside the application) is assumed invalid and hostile until it is processed, sanitised and validated, and the only way for user data to enter the application

这篇关于编写安全的C和安全英汉习语的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆