《GB/T 34943-2017语言源代码漏洞测试规范》简单解读
这几天正在了解GB/T 34943-2017 C/C++语言源代码漏洞测试规范。该标准是2017年11月1日发布,2018年5月1日正式实施的国家标准。该标准是*国家质量监督检验检疫总局和中国国家标准化管理委员会联合发布。该标准起草时,按照GB/T 1.1-2009给出的规则起草的。该标准主要起草单位有珠海南方软件网络评测中心、珠海中惠微电子有限公司等10家单位联合起草的,里面还有我认识的南京大学的陈振宇教授,倍感亲切。我得好好研究一下。该标准对于安全漏洞的分类参考了MITRE公司发布的CWE(Common Weakness Enumeration)。MITRE公司研究安全漏洞的都了解,这公司就是运营CWE和CVE的主体公司,是被美国国土资源局资助的企业。在该标准中,结合国外的自动化静态分析工具在实践中发现的典型漏洞案例进行举例的。本来这个举例对于标准来说非常好,但是有一点需要诟病的在该标准的附录中,列出了这款工具的名称、测试计划等文档,试想,难道一个国家的标准是按照国外的一款工具中的安全漏洞分类制定的吗?这个标准是否有被国外商业工具绑架的嫌疑。在倡导自主、可控的大环境下,我不知道这样一个标准是如何被批准实施的。这是否也印证了国家在制定标准上的问题呢?
规范中的一些安全漏洞类型还是覆盖比较全面,虽然案例代码稍显老旧,但是可以拿来参考或作为培训资料。于是,我们把里面的部分案例整理出来,使用我们自主、可控的国产化工具是否也能够检测这些安全漏洞呢?
例子1:6.2.3.6 缓冲区溢出
该安全漏洞举例是缓冲区溢出问题。
漏洞描述:对被分配内存空间之外的内存空间进行读或写操作。
漏洞风险:攻击者可利用缓冲区溢出让系统崩溃或者执行恶意代码。
修复或规避建议:在对缓冲区进行读或写时,对读写缓冲区的数据长度进行检查,确保读写内存在被分配的内存空间之内。
void example_fun( ) { //其它代码 char value[11]; //本例中假设只允许用户输入10个以下的字符 print("Enter The Value:"); //攻击者可输入大于10个字符的字符串,覆盖栈原来的返回地址,造成缓冲区溢出 scanf("%s",value); //其它语句 } |
使用自主、可控工具检测结果:
漏洞描述:
给出了引起该问题的跟踪代码行信息:
分析该问题,该漏洞本身不是value数组变量引起的,而是由于在11行使用scanf函数接收用户输入时,没有限定长度,可能导致数据超过数组边界,从而产生内存溢出。
但是这个问题是一个非常老旧的问题,现在很多编译器比原来的编译器在编译时优化了很多,能够发现这些比较初级的编码错误。我在windows 的Visual studio 下编写代码,是以error形式抛出的错误。所以我认为这类问题就没有必要写到标准了。
例子2:7.2.3.8整数溢出
漏洞描述:使用未经验证的整型数据进行算术运算,可能会导致计算结果过大而无法达到系统位宽范围内存储。
漏洞风险:攻击者可输入过大的数据引发软件崩溃或破坏系统重要内存等安全事件。
修复或规避建议:在对来自用户的整型数据做算术运算前进行验证,确保运算结果不会溢出。
unsigned int num; //本例中num值为1000 void example_fun( ) { //其它代码 //本例代码假设是运行在32位的系统中,32位系统中指针占4字节,unsig=1073740825,即mrsp值是0xffffffff unsigned int mrsp = packet_get_int(); //mrsp是来自用户的数据 /* 攻击者可通过让(mrsp+num)值为0xffffffff/4+1=1073741825,即mrsp=1073741825,造成整型溢出 (mrsp+num)*sizeof(char *) 等效于1073741825*4,溢出后求模后值为4,即为response分配了4个字节的空间 循环次数为1073741825次,用户数据将覆盖大量的内存空间 **/ char * response = malloc((mrsp+num)*sizeof(char*)); unsigned int i; for(i=0; i< mrsp; i++) { response[i]=packet_get_string(); //其它语句 } //其它语句 } |
示例1:不规范用法
这个例子指出的问题主要在于mrsp,这个变量的值来自于外部用户输入,攻击者是可以构造非常的大的值,导致出现整数溢出,产生如注释的问题。
使用工具检测结果如下:
漏洞描述如下:
我们再看看标准给出的规范代码示例:
这段代码明显存在一个漏洞,虽然对申请的数组长度进行判断,但是问题在于也不能保证malloc申请堆内存成功,所以下面直接对申请的堆内存直接赋值,是存在安全漏洞,可能产生空指针解引用。所以这个例子本身就是错误的。下面使用我们自主、可控的工具检测看看。
给出的漏洞描述如下:
给出的问题跟踪位置如下:
看还是我们的工具如何呢?不仅能够发现例子中的安全漏洞,还能发现给出的所谓正确示例中的错误。读过这篇对标准的简单解读,您怎么看呢?
-------------------------------------------------------------------
关注安全 关注作者