近日,CNCERT发布了《开源软件代码安全缺陷分析报告——人工智能类开源软件专题》。本期报告聚焦国内外知名机器学习、人工智能类开源软件安全开发现状,通过分析多款知名人工智能类开源软件产品的安全缺陷,评估开源项目的代码安全控制情况。360代码卫士团队为本期报告提供了技术支持。
以下是报告全文:
开源软件源代码安全缺陷分析报告
——人工智能类开源软件专题
1、概述
随着软件技术飞速发展,开源软件已在全球范围内得到了广泛应用。数据显示,99%的组织在其IT系统中使用了开源软件。开源软件的代码一旦存在安全问题,必将造成广泛、严重的影响。为解开源软件的安全情况,CNCERT持续对广泛使用的知名开源软件进行源代码安全缺陷分析,并发布季度安全缺陷分析报告。
“人工智能”近年来发展迅猛,已成为高精尖科技创新的代名词。本期报告聚焦国内外知名机器学习、人工智能类开源软件安全开发现状,通过分析多款知名人工智能类开源软件产品的安全缺陷,评估开源项目的代码安全控制情况。选取关注度高的开源项目,结合缺陷扫描工具和人工审计的结果,对各开源项目安全性进行对比。
2、被测开源软件
综合考虑用户数量、受关注程度以及更新频率等情况,选取了20款具有代表性的人工智能(以下简称AI)类开源软件。表1列出了本次被测的开源人工智能类软件项目的概况。本次检测的软件涵盖了C++,C#,Java,Python等编程语言。这些开源软件项目都是国际、国内知名的,拥有广泛用户的软件项目,其中不乏由知名软件公司开发的软件。由于这些软件大多具有巨大的用户群体,软件中的安全缺陷很可能会造成严重的后果。
表1 被测开源软件项目概览
项目名称 | 版本号 | 主要编程语言 | 功能说明 | 代码行数 |
---|---|---|---|---|
叮当(dingdang-robot) | 0.2.1 | Python | 工作在 Raspberry Pi上的中文语音对话机器人 | 6,574 |
Serenata de Amor | 1.0.0 | Python | 公共社会管理的AI项目 | 11,877 |
Snake | 1.0.0 | Python | AI的贪吃蛇游戏 | 3,123 |
Simple AI | 0.8.1 | Python | AI算法工具包 | 5,963 |
EasyAI | 1.0.0 | Python | 一个AI游戏框架 | 3,487 |
Mycroft | 0.8.5 | Python | 可编程的开源语音助手 | 27,236 |
AI_Challenger | 1.0 | Python | 开放数据集和编程比赛的AI挑战平台 | 198,422 |
OpenNERO | 1.0.0 | C++ | 面向AI研究和教育的开放平台 | 234,302 |
Polyworld | 2.6.0 | C++ | AI仿人工生命系统 | 49,673 |
AIKIDO | 0.2.0 | C++ | 一个解决机器人运动规划和决策问题的C++库 | 32,830 |
Quackle | 1.0.3 | C++ | 填字游戏的AI分析工具 | 13,908 |
Caffe | 0.9999 | C++ | 一个深度学习开发框架 | 92,761 |
SUSI.AI Server | 2.1.0 | Java | 一个智能开源个人助理程序 | 37,400 |
gdxAi | 1.8.1 | Java | 基于libGDX的游戏开发框架 | 35,200 |
onyx | 1.1.4 | Java | 一个使用人工智能,机器学习和深度学习等技术的android库,可让开发人员了解他们在应用中显示的内容 | 15,100 |
AIMA3e-Java | 3.0.0 | Java | Russell和Norvig的AI算法的Java实现 | 97,600 |
ABAGAIL | 1.0.0 | Java | 机器学习和人工智能的算法包 | 26,700 |
Malmo | 0.35.6 | Java | 一个基于Minecraft的AI实验和研究平台 | 54,100 |
OCR_densenet | 1.0.0 | Java | 采用densenet的图片文字识别软件(第一届西安交通大学人工智能实践大赛第一名) | 5,267 |
BrainSimulator | 0.6.0 | C# | AI架构的可视化原型设计开发平台 | 295,300 |
3、测试内容
3.1 安全缺陷种类
本次测试涵盖各类常见安全缺陷。根据缺陷形成的原因、被利用的可能性、造成的危害程度和解决的难度等因素进行综合考虑,可以将常见的安全缺陷分为八类:
1.输入验证与表示(Input Validation and Representation)
输入验证与表示问题通常是由特殊字符、编码和数字表示所引起的,这类问题的发生是由于对输入的信任所造成的。这些问题包括:缓冲区溢出、跨站脚本、SQL注入、命令注入等。
2.API误用(API Abuse)
API是调用者与被调用者之间的一个约定,大多数的API误用是由于调用者没有理解约定的目的所造成的。当使用API不当时,也会引发安全问题。
3.安全特性(Security Features)
该类别主要包含认证、访问控制、机密性、密码使用和特权管理等方面的缺陷。
4.时间和状态(Time and State)
分布式计算与时间和状态有关。线程和进程之间的交互及执行任务的时间顺序往往由共享的状态决定,如信号量、变量、文件系统等。与分布式计算相关的缺陷包括竞态条件、阻塞误用等。
5.错误和异常处理缺陷(Errors)
这类缺陷与错误和异常处理有关,最常见的一种缺陷是没有恰当的处理错误(或者没有处理错误)从而导致程序运行意外终止,另一种缺陷是产生的错误给潜在的攻击者提供了过多信息。
6.代码质量问题(Code Quality)
低劣的代码质量会导致不可预测的行为。对于攻击者而言,低劣的代码使他们可以以意想不到的方式威胁系统。常见的该类别缺陷包括死代码、空指针解引用、资源泄漏等。
7.封装和隐藏缺陷(Encapsulation)
合理的封装意味着区分校验过和未经检验的数据,区分不同用户的数据,或区分用户能看到和不能看到的数据等。常见的缺陷包括隐藏域、信息泄漏、跨站请求伪造等。
8.代码运行环境的缺陷(Environment)
该类缺陷是源代码之外的问题,例如运行环境配置问题、敏感信息管理问题等,它们对产品的安全仍然是至关重要的。
前七类缺陷与源代码中的安全缺陷相关,它们可以成为恶意攻击的目标,一旦被利用会造成信息泄露、权限提升、命令执行等严重后果。最后一类缺陷描述实际代码之外的安全问题,它们容易造成软件的运行异常、数据丢失等严重问题。
3.2 安全缺陷级别
我们将源代码的安全问题分为三种级别:高危(High)、中等(Medium)和低(Low)。衡量级别的标准包括两个维度,置信程度(confidence)和严重程度(severity)。置信程度是指发现的问题是否准确的可能性,比如将每个strcpy()调用都标记成缓冲区溢出缺陷的可信程度很低。严重程度是指假设测试技术真实可信的情况下检出问题的严重性,比如缓冲区溢出(buffer overflow)通常是比空指针引用(null pointer dereference)更严重的安全问题。将这两个因素综合起来可以准确的为安全问题划分级别,如图1所示。
图1 缺陷级别与严重程度、置信程度的关系
4、开源人工智能类软件项目的安全缺陷情况
本部分首先展示从被测项目中检出安全缺陷的数量,由此对被测项目的安全性进行大致的评估。然后进一步讨论被测项目中安全缺陷的分布情况,了解项目中出现较多的、容易被忽略的安全问题。
4.1 安全缺陷情况概览
本部分展示被测项目查出缺陷的数量,由此对被测项目的安全性进行大致的评估。图2分别展示了项目不同级别缺陷的数量,并按照高危缺陷数量对项目进行了排序,图中用蓝色折线图展示了每千行包含缺陷数。
图2 开源软件项目缺陷情况
从中可以看出,本次选取的人工智能类开源软件都存在不同程度的安全问题。本次检测从这些项目中总计发现高危缺陷173个,中危缺陷355个。缺陷数量排名靠前的项目处于极易被攻击者利用的状态,实际使用者需通过安装补丁或者更新版本的方式进行修复和升级。
在所有被测软件中,游戏框架easyAI、可视化AI原型开发平台BrainSimulator和深度学习开发框架Caffe不存在高危缺陷,同时中危缺陷数量也较少,总体安全性较高。
人工智能实验和研究平台Malmo在本次被测的20款软件里高危缺陷居多,包含64个高危缺陷和1个中危缺陷。其中大部分高危缺陷为XML Schema问题,由于未指定元素的最大出现次数(maxOccurs),导致攻击者可构造特定的XML文档以耗尽系统资源。
AI挑战平台AI_Challenger总体风险也较高,包含44个高危缺陷和2个中危缺陷。大多数缺陷为路径遍历问题,由于未对用户可控制的输入做完善的校验,导致攻击者可越权访问受保护的文件。
此外,中高危缺陷总数最多的是AI仿人工生命系统Polyworld,包含8个高危缺陷和138个中危缺陷。绝大部分中危缺陷是由于使用了C++的strcpy、sprintf等不安全的字符串操纵函数,导致存在缓冲区溢出的风险。
考虑到项目的绝对缺陷数量可能与项目大小相关,因此本报告计算了每千行缺陷数,用该数据反映缺陷在项目中的分布密度。根据该数据,代码安全性较好的项目依次是原型设计开发平台BrainSimulator、游戏开发框架gdxAi、深度学习开发框架Caffe和AI算法工具AIMA3e,这些项目平均每一万行代码出现1个以下的中高危缺陷。缺陷分布密度相对较高的项目是AI仿人工生命系统Polyworld、机器人运动库AIKIDO,这些项目平均每一千行代码中就会出现2-3个中高危缺陷。
4.2 高危安全缺陷分布情况
本部分对高危缺陷的分布情况进行分析说明。图3展示了被测项目中高危缺陷大类的分布情况。数据表明,大多数缺陷为“输入验证”类缺陷,该类缺陷主要是由于对用户输入未做充分验证导致的,易造成缓冲区溢出、路径遍历、跨站脚本及各类注入问题,一旦攻击者构造恶意输入,可能造成任意命令执行、任意文件读取等严重安全问题。
图3 被测项目中高危安全缺陷的分布情况(按大类划分)
“代码运行环境”类缺陷也占据了一定份额,主要涵盖脆弱的XML架构方面的问题,攻击者可以利用允许无限制元素的架构,发起拒绝服务攻击。
图4进一步展示了被测项目中各种具体的高危安全缺陷的分布情况。为方便展示,将出现不超过5次的缺陷统一归入“其他”,主要包括空指针解引用、变量未初始化、整数溢出、不安全的随机数等问题。在被测的20个项目中,出现较多的几类具体缺陷是路径遍历(29%,50个)、脆弱的XML架构(26%,45个)和释放后使用(10%,18个)。下面对这三种缺陷进行简要说明,并给出防范建议。
图4 被测项目中高危安全缺陷的分布情况
(按具体缺陷划分)
1.路径遍历(属于输入验证与表示类缺陷)
危害:应用程序对用户可控制的输入未经合理校验,就传送给文件访问API。攻击者可能会使用一些特殊的字符(如“..”和“/”)摆脱受保护的限制,访问一些受保护的文件或目录。
防范:严格验证用户的输入,建议创建合法资源名的列表,并规定用户只能访问其中的文件。
2.脆弱的XML架构(属于代码运行环境类缺陷)
危害:攻击者可以利用允许无限制元素的架构,构造特定的XML文档,导致应用程序耗尽系统资源。
防范:将 maxOccurs 限制在合理的数值。
3.释放后使用(代码质量问题)
危害:如果内存在释放后继续使用,可能会造成无法预测的结果。使用已经释放的内存将会导致合法数据损坏,或者执行任意代码,具体取决于当时的运行状态。
防范:避免释放后再使用问题,可以采取以下几种措施:
(1)在指针被释放后将其设为空值。
(2)确保全局变量仅被释放一次。
(3)谨慎处理循环或条件语句中的释放内存或重新分配内存操作。
4.3 安全缺陷总体分布情况
上文针对被测项目中的高危缺陷的检出情况对项目的安全状况进行了分析。通常来说,与高危缺陷相比,中危缺陷在实际运行环境中的危害相对较小,但仍不容忽视,且能在一定程度上反映出项目的代码质量、开发人员对代码安全问题的重视程度等。为了更全面的了解被测项目的安全状况,本节进一步展示包括中危缺陷在内的安全缺陷的总体分布情况。
图5展示了被测项目中安全缺陷大类的分布情况。与高危级别的缺陷分布情况相比,API误用类、代码质量类缺陷占比大幅提升。项目中使用了相当数量的不安全的字符串处理函数、内存拷贝函数等,可能会导致缓冲区溢出等严重风险。“类的构造函数未对成员进行初始化”、“不当的类型比较”等代码质量类问题可反映出开发者的不良编程习惯;与输入验证类问题相比,这类问题被直接用于发动攻击的可能性较小,但仍然会造成程序运行可能发生不可预知的错误,降低了系统的稳定性,严重情况下也会导致系统运行异常、甚至系统崩溃。建议开发者辅助使用自动化检测工具进行扫描和验证,以减少此类问题的发生。
图5 被测项目中的中高危安全缺陷的分布情况
(按大类划分)
图6进一步展示了被测项目中的各种具体的中高危安全缺陷的分布情况。本次检测结果中有35种出现不超过10次的缺陷,如“Session中存储非序列化对象”、“配置文件中的明文密码”、“Random.setSeed参数为特定值”、“Activity劫持”、 “未设置HttpOnly标记”等,为方便展示,将其统一归入“其他”。在被测的20个项目中,出现较多的缺陷是“不安全的字符串处理函数”(41%,144个)、“类的构造函数未对成员进行初始化”(14%,51个)和“不安全的内存拷贝函数”(9%,33个)。下面对这几种缺陷进行简要说明,并给出防范建议。
图6 被测项目中的中高危安全缺陷的分布情况
(按具体安全缺陷种类划分)
1.不安全的字符串处理/内存拷贝函数(属于API误用类缺陷)
危害:部分C/C++字符串处理函数如strcpy、strcat、strncpy、strncat、strlen等,以及内存拷贝函数如memcpy等未对边界进行检查,导致存在缓冲区溢出等严重风险。
防范:避免使用这些不安全的函数,选用其它更为安全的函数。对于使用Microsoft编译器的用户,考虑使用StrSate库中的函数。对于使用Gcc编译器的用户,考虑使用libssp库。另外可以使用支持C/C++标准的新版本编译器,并使用新的安全标准库函数。
2.类的构造函数未对成员进行初始化(属于代码质量类缺陷)
危害:使用类成员中的未初始化的成员数据,会导致程序运行不可预知的动作,甚至造成安全隐患。
防范:完善类的构造函数实现,确保类的成员都得以正确初始化。
“关于本报告的说明”
一、本报告仅从代码角度进行缺陷分析。本报告中统计的缺陷是指由于代码编写不规范导致的有可能被攻击者利用的安全隐患。在实际系统中,由于软件实际部署环境、安全设备等的限制,部分缺陷可能无法通过渗透测试得到验证。
二、本报告中的缺陷仅适用于表1中列出的特定软件版本。当软件版本有任何更新、修改和优化时,本报告不再适用。
三、本报告由360代码卫士团队提供部分技术支持。
*本文作者:360代码卫士,转载请注明来自FreeBuf.COM