C和C++安全编码(原书第2版)
上QQ阅读APP看书,第一时间看更新

2.3.1 被污染的数据

例2.3是一个简单的程序,它检查用户密码(应考虑被污染的数据),并授权或拒绝访问。

例2.3 IsPasswordOK()程序


01  bool IsPasswordOK(void) {
02    char Password[12];
03  
04    gets(Password);
05   r eturn 0 == strcmp(Password, "goodpass");
06  }
07  
08  int main(void) {
09    bool PwStatus;
10  
11    puts("Enter password:");
12    PwStatus = IsPasswordOK();
13    if (PwStatus == false) {
14      puts("Access denied");
15      exit(-1);
16    }
17  }

该程序仅仅是用来演示字符串是如何被误用的,并非密码检查之范本程序。这个IsPasswordOK()程序从main()函数开始执行。执行的第一行代码是调用puts()打印出一段字符串字面值。在C标准中,puts()函数被定义为字符输出函数,它在<stdio.h>中声明,其功能是在由stdout所指向的输出流中写入一个字符串并且以换行符('\n')结尾。IsPasswordOK()函数紧接着被调用,从用户那里获取一个密码。该函数返回一个布尔值,如果密码有效将返回true,如果无效则返回false。后面的程序检测PwStatus的值,以决定是否给用户授权或者拒绝用户访问。

IsPasswordOK()函数使用gets()函数从(stdin所指向的)输入流中读取字符,存储到由Password所指向的数组中,直到遇见文件结束(end-of-file,EOF)标志或者换行符。任何换行符都将被丢弃,并且当最后一个字符被读入数组后,立即会加上一个用作结尾的空字符。<string.h>头文件中定义的strcmp()函数将由Password所指向的字符串和字符串字面量“goodpass”作比较,如果两者相同,它将返回一个值为0的整数,如果两者不同,则返回值不为0。IsPasswordOK()函数在用户输入的密码等于“goodpass”时返回true,main()函数以此为依据决定是否授权用户访问。

在程序第一次运行中(参见图2.2),用户输入正确的密码,因此被授权访问。

第二次运行中(参见图2.3),用户输入的密码不正确,因此系统拒绝用户的访问。

遗憾的是,该程序包含一个安全缺陷,该缺陷允许攻击者绕过密码保护逻辑,直接获得对程序的访问权限。你能识别出这个缺陷吗?

图2.2 用户输入正确的密码,因此被授权访问

图2.3 用户输入的密码不正确,因此被拒绝访问