跳转到内容

安全代码撰写

本页使用了标题或全文手工转换
维基百科,自由的百科全书

安全代码撰写(Secure coding)是依照安全指引开发电脑软件,避免引入漏洞的软件开发实务。设计缺陷、程序错误及逻辑谬误是最常被利用软件漏洞的主要原因[1]。若识别出这些不安全的代码撰写实务,教育程序员改用较安全的软件写法,组织可以有主动的措施,在程序布置之前就消除或大幅减少软件漏洞[2]

有些研究者建议,为了有效的面对网络安全相关的威胁,应该在代码撰写时加入适当的安全性。若在软件设计时就已考虑安全性,这可以避免内部人士的攻击,也减少和应用程式安全有关的威胁[3]

避免缓冲区溢出

缓冲区溢出是常见的软件安全漏洞,若程序要在固定长度的缓冲器存储超过其大小的资料,就会出现此一问题。例如,有8个位置可以存储资料,但程序却试着要存储9个资料,就会出现问题。缓冲区溢出会改写到邻近位置的存储器,造成安全漏洞(栈缓冲器溢出)或是程序中止执行(例如出现存储器区段错误[1]

以下是一个容易出现缓冲区溢出的C语言程序例子


int vulnerable_function(char * large_user_input) {
    char dst[SMALL];
    strcpy(dst, large_user_input);
}

若用户输入的资料比缓冲器的大小要大,就会出现缓冲区溢出。

若要修正此一问题,可以用strncpy来避免缓冲区溢出

int secure_function(char * user_input) {
    char dst[BUF_SIZE];
    // copy a maximum of BUF_SIZE bytes
    strncpy(dst, user_input, BUF_SIZE);
}

另一种作法是用malloc英语malloc指令,在heap里动态分配存储器

char * secure_copy(char * src) {
    size_t len = strlen(src);
    char * dst = (char *) malloc(len + 1);
    if (dst != NULL) {
        strncpy(dst, src, len);
        // append null terminator 
        dst[len] = '\0';
    }
    return dst;
}

在上述的程序片段里,程序设法将src的内容复制到dst,不过也会检查malloc的传回值,确定有足够的存储器可以分配存储器给dst。

避免格式字符串攻击

格式字符串攻击英语Format string attacks是恶意用户在输入一些会提供给格式设置函数(如printf())的资料时,输入特殊的内容,让函数的动作异常。此攻击会破坏性的读取或写入调用堆栈

C语言的printf函数会将输出写到stdout。若其引数的格式有误时,会造成一些严重的安全错误。以下是一个格式字符串攻击的例子。

int vulnerable_print(char * malicious_input) {
	printf(malicious_input);
}

像是"%s%s%s%s%s%s%s"就属于恶意输入,会因为不正确的存储器读取而让程序崩溃。

避免整数溢出

整数溢出会出现在整数运算的结果太大,用规划的存储器空间无法正确表示的情形。若程序没有检查整数运算的结果,设法避免整数溢出,可能会造成软件错误或是漏洞。

以下是C++的函数,原始目的是要确认x和y相加的结果小于等于已定义好的数值MAX:

bool sumIsValid_flawed(unsigned int x, unsigned int y) {
	unsigned int sum = x + y;
	return sum <= MAX;
}

这段程序的问题是在进行整数的加法之后才进行检查。若x和y的和大于unsigned int可以表示的最大值,在进行加法之后就已出现溢出,因此虽然x和y的和大于MAX,但是其溢出后的结果可能会小于MAX。

以下也是检查溢出的程序,加上了检查x和y的和是否有大于等于x,y二个数值的判断,因为x和y是无号数整数,二者的和不会小于其中的任一数字。若是若计算出来的和小于任一数字,就代表已经溢出了。

bool sumIsValid_secure(unsigned int x, unsigned int y) {
	unsigned int sum = x + y;
	return sum >= x && sum >= y && sum <= MAX;
}

避免目录遍历

目录遍历是由不可靠来源提供的路径产生的漏洞,该路径造成了未授权的伺服器目录或是文件存取。

例如,考虑一个接受文件名称,读取文章的脚本,脚本会读文件名称输入,之后进行处理。这样脚本可能会用类似以下的的URL 来找有关dog food的文章。

https://www.example.net/cgi-bin/article.sh?name=dogfood.html

若此脚本没有输入检查,相信用户输入的文件都是有效的,恶意用户可能会产生以下的URL来获取网站伺服器的配置:

https://www.example.net/cgi-bin/article.sh?name=../../../../../etc/passwd

若是在类Unix系统中,这可能会泄漏/etc/passwd档,其中包括了用户ID用户名称家目录路径等。(SQL注入也是类似情境下的攻击)。

相关条目

参考资料

  1. ^ 1.0 1.1 Viega, John; Gary McGraw. Building Secure Software: How to Avoid Security Problems the Right Way. MAddison-Wesley Professional. 2001: 528. ISBN 978-0201721522. 
  2. ^ Taylor, Blair; Azadegan, Shiva. Threading secure coding principles and risk analysis into the undergraduate computer science and information systems curriculum. Proceedings of the 3rd annual conference on Information security curriculum development. InfoSecCD '06. Kennesaw, Georgia: Association for Computing Machinery. 2006-09-22: 24–29. ISBN 978-1-59593-437-6. S2CID 2452783. doi:10.1145/1231047.1231053. 
  3. ^ Russell L, Jones. Secure Coding: Building Security into the Software Development Life Cycle. Information Systems Security. Dec 2004. ProQuest 229507883. 

参考书目

  • Taylor, Art; Brian Buege; Randy Layman. Hacking Exposed J2EE & Java. McGraw-Hill Primis. 2006: 426. ISBN 0-390-59975-1.