代码审计的规范参考

admin 2024年6月8日22:18:31评论8 views字数 14641阅读48分48秒阅读模式

01

基础术语

代码安全审计:一种以发现代码安全缺陷和违反代码安全规范为目标的源代码安全性分析。

隐蔽通道:为系统中不受安全策略控制的信息泄露路径。按信息传递的方式区分,隐藏通道分为隐蔽存储通道和隐蔽定时通道。

SQL注入:利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力。

跨站脚本攻击:恶意攻击者向Web页面里面插入恶意HTML代码,当用户浏览该页面时,嵌入到Web里面的HTML代码会被执行,从而达到恶意用户的特殊目的。

缓冲区溢出:程序向一个已分配内存的固定长度缓冲区写数据,使得数据超出了缓冲区的边界。

线程安全:多线程访问时采用了加锁机制,当一个线程访问该类的某个数据时进行保护,其他线程不能进行访问直到该线程读取完其他线程才可使用。

敏感信息:由权威机构确定的必须受保护的信息,该信息的泄露、修改、破坏或丢失会对人或事产生可预知的损害。

口令:用于身份鉴别的秘密的字、短语、数或字符序列。

02

审计目的

代码安全审计的目的在于提高软件系统的安全性,降低风险。具体而言,通过审计发现源代码层面的安全弱点,但不包含软件分析、设计、测试、应用部署等层面的安全弱点。需说明,鉴于安全漏洞形成的综合性和复杂性,源代码安全审计的弱点主要针对源代码层面风险和质量问题,以及规定形成漏洞的各种脆弱性因素。

最终通过审计给出审计报告,列出源代码中针对审计列表的符合性/违规性条目,提出对源代码修订措施和建议。

03

审计方法

审计最常用的方法是将源代码安全弱点形成审计检查列表,对照源代码逐一进行检查。检查列表应根据被审计的具体对象及应用场景进行调整。

考虑到审计内容的复杂性,审计方法建议以工具审计和人工审计相结合,多种手段综合运用为原则。
首先,采用专业源代码审查工具对代码进行审计,给出审计结果报告,并对审计问题与标准相关审计项逐一用人工核对。由于审计工具的局限性,不可避免存在误报和漏报的问题。针对可能的误报问题,要求通过人工对比审计核查。此外,针对漏报的问题,要求采用多个工具交叉审计。人工审计是对工具审计的必要和有益的补充。人工审计主要针对工具审计漏洞报的问题展开。在人工审计具体实施中,可借助工具对源代码模块、数据流、控制流等逻辑结构进行分析提取,最后逐条比对分析。

在审计实施过程中,要落实多阶段审计工作。如按时间进度或代码编写里程碑划分,按周、月、季度开展审计;按函数、功能模块实施单元审计;按人员分工交叉审计等。

对于审计出来的弱点,可根据弱点的可利用性、造成的影响、弥补代价等因素进行分级排序。

04

代码安全审计过程

1、总体流程

审计过程包括四个阶段:审计准备、审计实施、审计报告、改进跟踪。审计准备阶段,审计员会对待审计的源代码基本情况进行摸底调研,并准备检查清单;审计实施阶段,代码审查会被执行,相关资料会被检查;报告阶段包括审计结果的总结陈述等活动,如有必要进行相关问题的澄清和相关资料说明;改进部分工作由源代码开发团队进行,主要对审计出的问题进行修复。对于安全缺陷代码修改后,会再次进行审计。

2、审计准备

明确审计目的

审计的应用场景可能包括源代码的采购/外包、软件产品的认证测试、公司源代码安全性自查等,在此类场景下对源代码安全性是否符合规范进行评估。

背景调研

初步了解源代码的应用场景、目标客户、开发内容,开发者遵循的标准、流程,查看源代码最近的状态报告。

熟悉代码

通过阅读代码,了解程序的代码结构、主要的功能模块,以及涉及到的编程语言。

初步制定检查列表

结合前面了解到的信息,根据审计人员身份(外部审计或内部审计)、审计目的(采购外包/认证测试/公司自查)等信息,给出源代码安全的审计要点,初步制定源代码安全的检查列表。检查列表包括审计员计划检查的项以及准备提问的问题列表。

3、审计实施

审计入场实施

入场实施环节中,审计员和项目成员(关键代码开发人员等)均应参与。审计员介绍审计的主要目标,要面谈的对象和检查的资料。项目人员介绍项目进展、项目关键成员、项目背景、项目的主要功能以及项目的当前状态。

信息收集

信息收集环节通过面谈等方式获得源代码以及相应需求分析文档、设计文档、测试文档等资料。通过文档资料了解源代码的业务逻辑等信息。

代码安全弱点检测

代码安全弱点检测环节是根据制定的源代码安全的检查项,逐一检查是否存在列表项中的安全弱点。

特殊情形审查

在源代码有软件外包/采用开源软件/合作开发情形下,也应对开源软件或外包部分进行了代码安全性检测。

4、审计报告

审计实施结束后,组织现场审计结束会,将初始审计结果提供给被审计项目成员组,提供被审计项目组澄清误解的机会,并允许项目成员提供其他需要补充的信息(如审计员未考虑到的)。项目成员可以立即了解被发现的安全问题并制定修正计划。

根据现场审计结束会上收集到的信息对初始结果进行调整后,审计员准备书面报告。书面报告应突出重大问题,对问题和优点都有所陈述;审计报告包括审计的总体描述,审计结论等部分。审计结论给出每条审计条款的符合/不符合的陈述。审计报告的内容示例见附录A;如果是外部审计,则审计报告的报告对象是组织本次审计的管理人员;如果是内部审计,则按照流程要求进行。

改进跟踪

在审计人员完成审计报告后,项目管理组织源代码开发人员采取措施来解决报告中识别的问题。对于审计发现的问题进行修改;对于未修改的应提供理由。对源代码的有效变更进行记录存档。在某些情况下,可通过跟进审计来确认问题是否解决。

05

可参考的审计细节

对错误会话暴露数据元素

审计指标:代码应避免对错误会话暴露数据元素。

审计人员应检查代码在应用的不同会话之间是否会发生信息泄露,尤其是在多线程环境下。

遗留调试代码

审计指标:代码中不应遗留调试代码。

审计人员应检查部署到应用环境的源代码是否含有调试或测试功能的代码,该部分代码是否会造成意外的后门入口。

数据信任边界的违背

审计指标:代码应避免将可信和不可信数据组合在同一结构体中,违背信任边界。

审计人员应检查源代码是否将来自可信源和非可信源的数据混合在同一数据结构体或同一结构化的消息体中,模糊了二者的边界。

类的错误比较

审计指标:在类进行比较时,不应只使用名称比较。

审计人员应检查代码中当多个类具有相同的名字时,是否仅通过名字比较类。只通过类名称进行比较可能会导致使用错误的类。如Java语言中应该同时使用 getClass() 方法和运算符“==”来比较类。

私有数组类型数据域的不安全操作

审计指标:公开方法中不应返回私有的数组类型的数据域,或将公共的数据赋值给私有数组类型的数据域。

审计人员应检查源代码声明为公开的方法时,是否返回私有数组的引用,如果结果为肯定,数组的数据会有遭到破坏的安全风险。

审计人员应检查源代码是否将公共数据分配给私有数组,如果结果为肯定,则等于给了该数组公众访问权限,数组的数据会有遭到破坏的安全风险。

包含敏感数据类的安全

审计指标:包含敏感数据的类不应可复制和可序列化。

审计人员应检查源代码中包含敏感数据的类的相关行为是否安全,具体要求包括但不限于:

    1. 应检查源代码中包含敏感数据的类是否可复制,如Java语言中的实现了Clonenable接口使类可复制,包含敏感数据的类不应被复制。

    2. 应检查源代码中包含敏感数据的类是否可实现了序列化接口,使类可序列化,包含敏感数据的类不应可序列化。

暴露危险的方法或函数

审计指标:不应暴露危险的方法或函数。

审计人员应检查源代码中的应用程序编程接口(API)或与外部交互的类似接口是否暴露了危险方法或函数,他们本应受到适当的限制。危险方法或函数暴露的形式有如下几种:

  1. 该方法/函数原本设计为非外部用户使用;

  2. 该方法/函数原本设计为部分用户访问,如限定来自基于Internet访问的某网站。

存储不可序列化的对象到磁盘

审计指标:不应将不可序列化的对象存储到磁盘。

审计人员应检查(如J2EE框架中)源代码是否试图将不可序列化的对象写到磁盘中,将不可序列化的对象存储到磁盘上可能导致序列化失败和应用程序崩溃。

参数指定错误

审计指标:函数功能调用应正确指定参数。

审计人员应检查函数/方法调用时参数指定是否正确,是否存在如下情况:

a) 不正确的变量或引用

b) 不正确数量的参数

c) 参数顺序不正确

d) 参数类型不正确

e) 错误的值

以上检查项的任一结果为肯定,则提示存在安全风险。

堆内存释放问题

审计指标:应避免在释放堆内存前清理不恰当而导致敏感信息暴露。

审计人员应检查代码在释放堆内存前是否采用合适的方式进行信息的清理。如C语言中是否使用realloc()调整存储敏感信息的缓冲区大小,如存在该操作,将存在可能暴露敏感信息的风险。realloc()函数不是从内存中删除,而通常是将旧内存块的内容复制到一个新的、更大的内存块,这可能暴露给攻击者使用“memory dump”或其他方法来进行读取敏感数据的“堆检查”攻击。

忽略函数返回值

审计指标:应正确检查函数的返回值,避免忽略函数的返回值。

审计人员应检查代码是否对方法或函数调用的返回值作了检查,如未检查函数的返回值,则提示代码存在无法检测非预期状态的风险。

端口多重绑定

审计指标:不应对同一端口进行多重绑定。

审计人员应检查代码是否有多个套接字绑定到相同端口,从而导致该端口上的服务有被盗或被欺骗的风险。

不兼容的指针类型

审计指标:不应使用不兼容类型的指针来访问变量。

审计人员应检查代码是否使用不兼容类型的指针来访问变量。通过不可兼容类型的指针修改变量可能会导致不可预测的结果。

利用指针减法确定内存大小

审计指标:应避免使用指针的减法来确定内存大小。

审计人员应检查代码是否采用一个指针减去另一个指针的方式来确定内存大小。如果两个指针不在相同内存块中,那么使用指针的减法来确定内存大小的计算可能会不正确。

将固定地址赋值给指针

审计指标:不应把固定地址赋值给指针。

审计人员应检查代码是否将一个NULL或0以外的固定地址赋值给指针。将固定地址赋值给指针会降低代码的可移植性,并为攻击者进行注入代码等攻击提供便利。

试图访问非结构体类型的域

审计指标:不应把指向非结构体类型指针强制转换为指向结构类型的指针并访问其字段。

审计人员应检查代码是否将指向非结构体类型的指针,强制转换为指向结构类型的指针并访问其字段,如果结果为肯定,则可能存在内存访问错误或数据损坏的风险。

释放一个不在缓冲区起始位置的指针

审计指标:不应释放不在缓冲区起始位置的指针。

审计人员应检查代码是否释放不在缓冲区起始位置的指针。如果是,则存在应用程序崩溃等风险。

指针偏移越界

审计指标:不应使用越界的指针偏移。

审计人员应检查代码在使用指针时是否存在偏移越界的现象,因指标偏移越界可能会造成访问缓冲区溢出风险。

无效指针使用

审计指标:应避免无效指针的使用。

审计人员应检查代码是否存在使用无效指针的现象,因使用无效指针,可能会产生非预期行为。

资源与变量不安全初始化

审计指标:应避免不安全的资源或变量的初始化。

审计人员应检查源代码是否对资源或变量进行了安全的初始化,具体要求包括但不限于:

a) 应检查源代码是否对关键变量进行初始化,未初始化关键变量易导致系统按非预期值执行,如结果为否定,则提示存在安全风险;

b) 应检查源代码是否采用了不安全或安全性较差的缺省值来初始化内部变量。缺省值通常和产品一起发布,容易被熟悉产品的潜在攻击者获取而带来系统安全风险,如结果为肯定,则提示存在安全风险;

c) 应检查源代码中关键的内部变量或资源是否采用了可信边界外的外部输入值进行初始化,如结果为肯定,则提示存在安全风险。

引用计数的更新不恰当

审计指标:应避免引用计数的更新不恰当。

审计人员应检查源代码中管理资源的引用计数是否正确更新,引用计数更新不正确,可能会导致资源在使用阶段就被过早释放,或虽已使用完毕但得不到释放的安全风险。

过期的文件描述符

审计指标:不应使用过期的文件描述符。

审计人员应检查源代码是否在文件描述符关闭后再次使用或访问它。特定文件或设备的文件描述符被释放后,可被重用,但可能引用了其他的文件或设备。

初始化失败后未退出

审计指标:初始化失败后应退出程序。

审计人员应检查源代码在初始化失败后能否安全退出。

异常状态的处理

审计指标:发生异常时,应恢复对象到先前的状态。

审计人员应检查源代码中当异常发生时对象(尤其是关系到系统安全性的对象)能否维持一致的状态。

启用后台线程前主线程未完成类的初始化

审计指标:不应在初始化类时启用后台线程。

审计人员应检查源代码是否确保主线程完成类的初始化后,再启用后台线程,否则提示系统可能存在类初始化死锁的风险。

发布未完成初始化的对象

审计指标:不应发布部分初始化的对象。

审计人员应检查源代码在多线程环境中,是否有初始化尚未完成的对象被公开,使得其在本线程初始化完成前就可被其他线程引用。

资源不安全清理

审计指标:应避免不安全的资源清理。

审计人员应检查源代码中资源清理部分的相关功能,检查项包括但不限于:

  1. 审计人员应检查源代码中当特定错误(如不可恢复逻辑错误)发生时,程序是否在以不可预测的状态继续执行,而导致数据有被损坏的风险,在程序终止时应执行正确的清理动作。

  2. 审计人员应检查源代码在使用资源后是否恰当地执行临时文件或辅助资源的清理,避免清理环节不完整。

错误处理

审计指标:应恰当进行错误处理。

审计人员应检查源代码中错误处理是否安全,具体要求包括但不限于:

  1. 应检查是否对错误进行检查并处理检测到的错误

  2. 应检查是否采用标准化的、一致的错误处理机制来处理代码中的错误;

  3. 应检查错误发生时,是否提供正确的状态代码或返回值来标示发生的错误

  4. 应检查是否确保线程池中正在执行的任务失败后给出提示;

  5. 应检查是否对执行文件I/O的返回值进行检查;

  6. 应检查是否对函数或操作返回值是否为预期值进行了检查;

  7. 应检查是否返回定制的错误页面给用户来预防敏感信息的泄露。

如上检查项的任一结果为否定,则提示存在安全风险。

关键状态数据外部可控

审计指标:应避免关键状态数据被外部控制。

审计人员应检查源代码中是否将与用户信息或软件自身安全密切相关的状态信息,存储在非授权实体都可以访问的地方,如结果为肯定,则系统可能有关键状态数据能被外部访问或篡改的安全风险。

隐蔽通道

审计指标:应避免隐蔽通道。

审计人员应检查源代码中是否有隐蔽通道如隐蔽时间通道,如结果为肯定,则提示系统存在信息暴露的安全风险。

隐蔽时间通道通过随着时间推移调节某些方面的系统行为来传递信息,接收到信息的程序能够监测系统行为并推断出受保护的信息,从而造成信息暴露。

未加限制的外部可访问锁

审计指标:应对外部可访问锁加以限制,不允许被预期范围之外的实体影响。

审计人员应检查源代码中的锁是否可被预期范围之外的实体控制或影响,如结果为肯定,则系统存在易受到拒绝服务攻击的安全风险。

会话过期机制缺失

审计指标:应制定会话过期机制。

审计人员应检查源代码中会话过程是否存在会话过期机制,如结果为否定,则提示源代码存在保护机制被绕过的风险。

将资源暴露给错误范围

审计指标:不应将资源暴露给错误的范围。

审计人员应检查源代码是否将文件和目录等资源暴露给错误的范围,如果存在,则提示源代码存在信息暴露等风险。例如,一个程序本来意图只是向特定的用户提供某些私密文件,防止攻击者访问这些私密文件。如果文件权限是不安全的,那么特定用户以外的其他用户就有可能访问这些文件。

未经控制的递归

审计指标:应避免未经控制的递归。

审计人员应检查源代码是否避免未经控制的递归,未控制递归发生的数量可造成预防资源消耗过多的安全风险。

无限循环

审计指标:执行迭代或循环应恰当地限制循环执行的次数,应避免无限循环。

审计人员应检查源代码中软件执行迭代或循环,是否充分限制循环执行的次数,以避免无限循环的发生或避免攻击者占用过多的资源。

信号错误

审计指标:应正确使用信号处理函数。

审计人员应检查源代码中信号处理函数的使用,具体要求包括但不限于:

  1. 应检查源代码中如果信号处理函数不可中断,那么信号处理函数在执行时是否已屏蔽该信号,如果结果为否定,则提示存在安全风险;

  2. 应检查源代码中信号处理函数代码序列是否包含非异步安全代码序列,如果结果为肯定,则提示存在安全风险。

共享资源的并发安全问题

审计指标:应对共享资源使用正确的并发处理机制。

审计人员应检查源代码中共享资源的使用及并发处理的过程,具体要求包括但不限于:

  1. 应检查源代码在多线程环境中对共享数据的访问是否为同步访问,如果结果为否定,则提示存在安全风险;

  2. 应检查源代码中线程间共享的对象是否声明正确的存储持续期,如果结果为否定,则提示存在安全风险;

  3. 应检查源代码中是否在并发上下文中使用不可重入的函数,如果结果为肯定,则提示存在安全风险。

  4. 应检查源代码中是否避免了检查时间与使用时间资源冲突。

  5. 应检查源代码中多个线程中等待彼此释放锁的可执行片段是否避免了死锁情况发生,如果结果为否定,则提示存在安全风险;

  6. 审计人员应检查代码对共享资源执行敏感操作时是否检查加锁状态,如果结果为否定,则提示存在安全风险;

  7. 审计人员应检查代码是否将敏感数据存储在没有被锁定或被错误锁定的内存中,(将敏感数据存储于加锁不恰当的内存区域,可能会导致该内存通过虚拟内存管理器被写入到在磁盘上的交换文件中,从而使得数据更容易被外部获取),如果结果为肯定,则提示存在安全风险;

  8. 应检查源代码中是否存在互斥体被锁定时删除它们的情况,如果结果为肯定,则提示存在安全风险;

  9. 应检查源代码中是否存在关键资源多重加锁,如果结果为肯定,则提示存在安全风险;

  10. 应检查源代码中是否存在关键资源多重解锁,如果结果为肯定,则提示存在安全风险;

  11. 应检查源代码中是否存在对未加锁的资源进行解锁,如果结果为肯定,则提示存在安全风险;

  12. 应检查源代码中在异常发生时是否释放已经持有的锁,如果结果为否定,则提示存在安全风险;

不安全的临时文件

审计指标:应正确使用临时文件

审计人员应检查源代码中临时文件是否安全,预防因临时文件造成的敏感信息泄露,具体要求包括:

  1. 应检查源代码中是否创建或使用不安全的临时文件,如果结果为肯定,则提示存在安全风险;

  2. 应检查源代码中临时文件是否在程序终止前移除,如果结果为否定,则提示存在安全风险。

  3. 应检查源代码中是否在具有不安全权限的目录中创建临时文件,如果结果为肯定,则提示存在安全风险。

符号名称未映射到正确对象

审计指标:符号名称应映射到正确对象。

审计人员应检查源代码中符号名称是否映射到正确对象,如果结果为否定,则提示存在安全风险。

Web重定向后执行额外代码

审计指标:web应用不应在重定向后执行额外代码。

审计人员应检查web代码是否存在重定向后执行额外代码,如果结果为肯定,则提示存在安全风险。

权限、特权与访问控制问题

审计指标:应确保权限、特权的管理安全以及其他访问控制措施的安全。

审计人员应检查源代码中的权限、特权与访问控制功能相关部分,具体要求包括但不限于:

  1. 应检查是否缺失认证机制,如果结果为肯定,则提示存在安全风险。

  2. 应检查是否缺失授权机制,如果结果为肯定,则提示存在安全风险。

  3. 应检查是否存在会话ID确定,如果结果为肯定,则提示存在安全风险。

  4. 应检查是否违背最小特权原则,以高于功能所需的特权级别(如根用户或管理员用户)在执行一些操作,如果结果为肯定,则提示存在安全风险

  5. 应检查放弃特权后,是否检查其放弃是否成功,如果结果为否定,则提示存在安全风险;

  6. 应检查是否创建具有正确访问权限的文件,如果结果为否定,则提示存在安全风险

7.应检查是否避免关键资源的不正确权限授予,如果结果为否定,则提示存在安全风险

8.应检查是否确保正确的行为次序,避免在解析与净化处理之前进行授权,如果结果为否定,则提示存在安全风险

9.应检查是否限制过多认证尝试,如果结果为否定,则提示存在安全风险。

10.应检查是否避免使用单一因素认证机制,如果结果为否定,则提示存在安全风险

11.应检查是否可避免攻击者使用欺骗、候选名、候选路径/通道、或捕获重放攻击等手段绕过身份认证,如果结果为否定,则提示存在安全风险。12.应检查是否避免不恰当地信任反向DNS,如果结果为否定,则提示存在安全风险

13.对于客户端/服务器架构的产品,应检查是否避免仅在客户端而非服务器端执行认证,如果结果为否定,则提示存在安全风险。

14.应检查是否避免过于严格的账户锁定机制(账户锁定保护机制过于严格且容易被触发,就允许攻击者通过锁定合法用户的账户来拒绝服务合法的系统用户),如果结果为否定,则提示存在安全风险;

15.应检查是否在认证机制中使用口令哈希代替口令,如果结果为否定,则提示存在安全风险;

16.应检查是否未对信道两端的操作者进行充分的身份认证,或未充分保证信道的完整性,从而允许中间人攻击发生,如果结果为肯定,则提示存在安全风险;

17.应检查是否避免通信通道源的验证不当,确保请求来自预期源,如果结果为否定,则提示存在安全风险;

18.应检查是否避免通过用户控制密钥绕过授权机制,如果结果为否定,则提示存在安全风险;

19.应检查通信信道是否正确指定目的地来预防如下风险:攻击者在目的地伪装成受信任的服务器来窃取数据或引起拒绝服务。如果结果为否定,则提示存在安全风险

密码安全问题

审计指标:密码相关功能应符合国家密码相关标准的要求。

审计人员应检查源代码中密码功能是否符合国家密码相关标准的要求,具体要求包括但不限于:

  1. 应检查是否避免在加密中重用密钥;

  2. 应检查是否避免使用已过期的密钥;

  3. 应检查是否避免对敏感数据的明文存储或明文传输;

  4. 应检查是否避免使用已被攻破或存在风险的密码学算法;

  5. 应检查是否选择被业界专家公认比较健壮的算法,未自行开发或定制私有加密算法并定期确认加密算法是否已经过期;

  6. 应检查是否在密码块链接(CBC)加密模式中使用随机初始化向量

  7. 应检查RSA算法是否结合最优非对称加密填充(OAEP)进行使用。

如上检查项的任一结果为否定,则提示存在安全风险。

随机数安全问题

审计指标:应确保产生安全的随机数。

审计人员应检查源代码是否安全产生随机数,具体审计要求包括但不限于:

  1. 应检查是否采用能产生充分信息熵的算法或方案

  2. 应检查是否避免随机数的空间太小;

  3. 应检查是否避免伪随机数生成器(PRNG)每次都使用相同的种子、可预测的种子(如进程ID或系统时间的当前值)或空间太小的种子;

  4. 应检查是否避免使用具有密码学弱点的伪随机数生成器(PRNG)用于加密场景;

如上检查项的任一结果为否定,则提示存在安全风险。

数据真实性验证问题

审计指标:应验证数据的起源或真实性,避免接收无效数据。

审计人员应检查源代码是否对数据的真实性进行验证,具体审计要求包括但不限于:

  1. 应检查是否有数据源或通信源验证错误应检查是否未验证或不正确验证数据的密码学签名;

  2. 应检查是否接受外部混杂在在可信数据中的不可信数据

  3. 应检查是否缺失或进行不恰当完整性检查应检查安全相关的输入是否仅依赖于加密技术而未进行完整性检查;

  4. 应检查是否依赖于文件名或外部提供文件的扩展名而非文件内容进行决策;

  5. 应检查是否信任来自系统事件的信息

  6. 应检查是否依赖未经验证和完整性检查的Cookie进行决策如上检查项的任一结果为肯定,则提示存在安全风险。

个人信息保护

审计指标:应确保个人信息保护。

审计人员应检查源代码是否不恰当地阻止个人隐私信息,在未经明确授权或未经数据相关人的默认同意的情况被访问。不当处理私人信息,可能危及用户隐私,并且可能非法。

非预期数据类型处理不当

审计指标:应避免非预期数据类型处理不当。

审计人员应检查代码是否正确处理特定元素并非预期类型时的情形,如预期是数字(0-9),但被提供字母(A-Z),源代码是否正确处理。

数据/内存布局问题

审计指标:不应依赖数据/内存布局。

审计人员应检查代码逻辑是否依赖于对协议数据或内存在底层组织形式的无效假设。当平台或协议版本变动时,数据组织形式可能会发生变化从而带来非预期行为。

绕过净化和验证

审计指标:应防止以大小写混合的方式绕过净化和验证。

审计人员应检查字符串在查找、替换、比较等操作时,是否存在因大小写问题而被绕过的情况。

在字符串验证前未进行过滤

审计指标:不应在过滤字符串之前对字符串进行验证。

审计人员应检查对字符串进行验证之前是否存在对该字符串进行过滤,来防止注入类攻击的发生。

条件比较不充分

审计指标:执行比较时不应部分比较或不充分的比较。

审计人员应检查比较条件是否充分,防止不充分比较造成逻辑绕过风险。

泛型和非泛型原始数据类型

审计指标:不应混用具有泛型和非泛型的原始数据类型。

审计人员应检查代码是否存在泛型和非泛型之间原始数据类型的混用现象,应避免泛型和非泛型原始数据类型的混用。

字节序使用问题

审计指标:应避免字节序使用不正确。

审计人员应检查代码在跨平台或网络通信处理输入时是否考虑到字节顺序,避免字节序使用不正确。

结构体长度

审计指标:不应将结构体的长度等同于其各个成员长度之和。

审计人员应检查代码是否将结构体的长度等同于其各成员长度之和,不应将结构体长度等同于各成员长度之和。结构对象可能存在无名的填充字符从而造成结构体长度与各个成员长度之和并不相等。

数值越界回绕错误

审计指标:应避免越界回绕错误。

审计人员应检查代码是否存在数值赋值超出数值类型范围,应避免赋值越界。

除零问题

审计指标:应避免除零错误。

审计人员应检查代码是否存在除零操作,应避免除零错误。

边界值检查缺失

审计指标:数值范围比较时,不应遗漏边界值检查。

审计人员应检查代码在进行数值范围比较时,是否遗漏了最小值、最大值等边界值检查。

敏感信息暴露

审计指标:应避免敏感信息暴露。

审计人员应检查源代码中是否有敏感信息暴露,重点审查暴露的途径包含但不限于:

  1. 通过发送数据导致的信息暴露;

  2. 通过数据查询导致的信息暴露;

  3. 通过差异性(响应差异性、行为差异性、时间差异性)导致的信息暴露;

  4. 通过错误消息导致的信息暴露;

  5. 敏感数据的不恰当跨边界移除导致信息暴露;

  6. 通过进程信息导致的信息暴露;

  7. 通过调试信息导致的信息暴露;

  8. 在释放前未清除导致信息暴露;

  9. 通过输出流或日志将系统数据暴露到未授权控制的范围;

  10. 通过缓存导致的信息暴露;

  11. 通过日志文件导致的信息暴露;

  12. 通过源代码导致的信息暴露,如测试代码、源代码、注释等;

  13. 敏感信息使用GET请求传递导致信息暴露;

  14. 备份文件导致信息暴露。

信息丢失或遗漏

审计指标:应避免信息丢失或遗漏。

审计人员应检查代码是否未记录或不恰当记录安全相关信息,应避免信息丢失或遗漏。信息丢失或遗漏导致的常见形式:

  1. 截断与安全有关的信息的显示、记录或处理,掩盖攻击的来源或属性;

  2. 不记录或不显示信息(如日志),而该信息对确定攻击的来源或性质,或确定行动是否安全具有重要意义;

  3. 记录安全相关信息时,使用候选名称而非正式规范的名称导致安全相关信息混淆。

数据结构控制域安全问题

审计指标:应避免对数据结构控制域的删除或意外增加。

审计人员应检查代码关于数据结构控制域的操作:

a)应检查代码是否存在对数据结构控制域的删除而导致系统安全风险。因控制数据被删除,可能会引起严重编程逻辑错误,应避免对数据结构控制域删除。

b)应检查代码是否存在对数据结构控制域的意外增加而导致系统安全风险。应避免对数据结构控制域意外增加。

内存缓冲区边界操作

审计指标:应避免内存缓冲区边界操作的限制不恰当。

审计人员应检查代码在内存缓冲区边界操作时是否存在越界现象,因内存缓冲区访问越界可能会造成缓冲区溢出漏洞。

忽略字符串结尾符

审计指标:应保证字符串的存储具有足够的空间容纳字符数据和结尾符。

审计人员应检查代码字符串的存储空间是否能容纳下结尾符,字符串不以结尾符结束会造成字符串越界访问。

对环境变量长度做出假设

审计指标:不应对环境变量的长度做出假设。

审计人员应检查代码在使用环境变量时是否对环境变量的长度做出特定值的假设,因环境变量可由用户进行设置修改,故对环境变量的长度做出假设可能会发生错误。

缓冲区复制造成溢出

审计指标:应避免未检查输入数据大小就进行缓冲区复制。

审计人员应检查代码在进行缓冲区复制时,是否存在未对输入数据大小进行检查的现象,因未检查输入数据大小,可能会造成缓冲区溢出。。

使用错误长度访问缓冲区

审计指标:应避免使用错误的长度值访问缓冲区。

审计人员应检查代码在访问缓冲区时使用长度值是否正确,因使用错误的长度值来访问缓冲区可能会造成缓冲区溢出风险。

路径遍历

审计指标:应避免路径遍历。

审计人员应检查代码是否将由外部输入构造的标识文件或目录的路径名,规范化后限制在受限目录,路径遍历会造成非授权访问资源的风险。

文件访问解析为链接不恰当

审计指标:应避免在文件访问前对链接解析不恰当。

审计人员应检查代码基于文件名访问文件时,是否能恰当避免文件名被识别为链接或者快捷方式。链接或快捷方式可能会解析为意想不到的资源。

非可信环境下命令执行

审计指标:应避免执行的命令或加载的库文件来自非可信源或在非可信环境中执行。

审计人员应检查代码执行的命令或加载的库文件是否来自非可信源,或在非可信环境中执行。如结果为肯定,则应用程序有执行攻击者恶意命令的风险。

循环条件输入导致拒绝服务

审计指标:应检查循环条件输入,避免过度循环导致拒绝服务。

审计人员应检查代码是否存在循环条件输入,因过度循环条件输入可能会导致拒绝服务风险。

外部控制文件名或路径检查

审计指标:应避免文件名或路径的外部可控制。

审计人员应检查文件系统操作中的文件名或路径是否被外部控制。若允许用户输入来控制或影响在文件系统操作中所使用的路径或者文件名,则攻击者可能会访问或修改系统文件或对于应用程序至关重要的其他非预期文件。

外部控制格式化字符串问题

审计指标:应避免外部控制的格式化字符串。

审计人员应检查代码函数接受格式化字符串作为参数,格式化字符串是否来自外部,如果是,则可能有注入类漏洞风险。

对方法或函数参数验证问题

审计指标:应对方法或函数的参数进行验证。

审计人员应检查代码是否存在对方法或函数的参数进行合法性或安全性校验。

URL重定向

审计指标:不应开放不可信站点的URL重定向。

审计人员应检查代码是否存在URL重定向到不可信站点的现象。因重定向到不可信站点,可能会发生跨站伪造请求漏洞风险。

命令行注入

审计指标:应正确处理命令中的特殊元素。

审计人员应检查代码对利用外部输入来构造命令或部分命令时,是否对其中的特殊元素进行了处理,命令注入通常发生在以下情况中:

  1. 数据从非可信源进入到应用程序中;

  2. 数据是字符串的一部分,该字符串被应用系统当作命令来执行的;

  3. 通过执行这个命令,应用程序为攻击者提供了攻击者不应拥有的权限或能力。

SQL执行语句注入

审计指标:应正确处理SQL命令中的特殊元素。

审计人员应检查代码利用用户可控的输入数据构造SQL命令时,是否对外部输入数据中的特殊元素进行处理,如果未处理,那么这些数据有可能被解释为SQL命令而非普通用户的输入数据。攻击者可对此加以利用来修改查询逻辑,从而绕过安全检查或插入可以修改后端数据库的额外语句,可能包括执行操作系统命令。

跨站脚本

审计指标:应避免跨站脚本攻击。

审计人员应检查代码中当用户提供的数据放到在网页中,被送到浏览器进行显示前,是否进行了验证或过滤。

未恰当处理语法形式不完全符合预期规范的输入

审计指标:应恰当处理输入语法形式不完全符合预期规范的输入。

审计人员应检查代码中输入功能的部分:

    1. 审计人员应检查代码是否正确处理当参数被定义但相关的值缺失情形。

    2. 审计人员应检查当超过预期的的值被输入时,源代码是否正确处理。

    3. 审计人员应检查当输入参数未定义或不支持,源代码是否正确处理。

    4. 审计人员应检查代码在函数调用是否对缺失参数的情况进行了处理。

    5. 审计人员应检查代码是否处理超过预期数量的参数,应避免未对多余参数做处理。

    6. 审计人员应检查代码是否正确处理未定义的参数,应避免未对未定义参数做处理。

对输出日志中特殊字符处理问题

审计指标:应对输出日志中的特殊字符进行过滤和验证。

审计人员应检查代码是否对输出日志中的特殊字符做过滤和验证。因对特殊字符未做过滤,可能会造成信息泄露。

对HTTP头Web脚本特殊字符处理问题

审计指标:应对HTTP头的Web脚本语法中的特殊字符进行过滤和验证。

审计人员应检查代码是否对HTTP头中的Web脚本特殊字符进行过滤处理。因HTTP头中的Web脚本含有特殊字符,可能会导致浏览器执行恶意脚本。

文件描述符穷尽问题

审计指标:不应导致文件描述符穷尽。

审计人员应检查代码是否存在导致文件描述符穷尽情形。具体检查项包括但不限于:

  1. 是否对打开文件描述符未做关闭处理;

  2. 是否到达关闭阶段之前,失去对文件描述符的所有引用;

  3. 进程完成后是否未关闭文件描述符。

内存未释放

审计指标:应及时释放动态分配的内存。

审计人员应检查代码是否有动态分配的内存使用完毕后未释放导致内存泄漏的情形。内存泄漏可能会导致资源耗尽从而带来拒绝服务的安全风险。

对网络消息容量的控制

审计指标:应避免对网络消息容量的控制不充分。

审计人员应检查代码是否控制网络传输流量不超过被允许的值。如果源代码没有机制来跟踪流量传输,系统或应用程序会很容易被滥用于传输大流量(超过了请求值或客户端被允许的值),从而带来拒绝服务的安全风险。

算法复杂度问题

审计指标:应避免算法复杂度攻击。

审计人员应检查代码中算法是否在最坏情况下非常低效,复杂度高,会严重降低系统性能。如果是,则攻击者就可以利用精心编制的操作来触发最坏情况的发生,从而引发算法复杂度攻击。

早期放大问题

审计指标:应遵守正确的行为次序避免早期放大攻击数据。

审计人员应检查代码是否存在允许实体在授权或认证前执行合法但代价高的操作。

子进程访问父进程敏感资源问题

审计指标:在调用子进程之前应关闭敏感文件描述符,避免子进程使用这些描述符来执行未经授权的I/O操作。

审计人员应检查代码是否存在调用子进程之前有未关闭敏感文件描述符的情形。当一个新进程被创建或执行时,子进程继承任何打开的文件描述符,如不关闭则可能会造成未经授权的访问。

堆空间耗尽问题

审计指标:应限制堆空间的消耗,防止堆空间耗尽。

审计人员应检查代码是否有导致堆空间耗尽的情形,具体检查项包括但不限于:

a) 是否存在内存泄漏;

b) 是否存在死循环;

c) 不受限制的反序列化;

d) 创建大量的线程;

e) 解压一个较大压缩文件。

重复释放资源

审计指标:应避免重复释放资源。

审计人员应检查代码是否存在重复释放资源的情形。重复释放资源可能会造成系统崩溃。

访问已释放内存

审计指标:不应引用或访问已被释放后的内存。

审计人员应检查代码是否存在内存被释放再次被访问的情形。内存被释放后再次访问会出现非预期行为。

内存释放指针赋值问题

审计指标:应在内存释放立即把指针设置为NULL或指向另一个合法的对象。

审计人员应检查代码中内存释放后指针是否未置空或指向另一个合法对象。

内存管理函数成对调用

审计指标:应调用匹配的内存管理函数。

审计人员应检查代码调用的内存管理函数是否匹配,如malloc/free来分配或删除资源。当内存管理函数不匹配时,可能带来内存损坏或程序崩溃等风险。

条件语句缺失默认情况问题

审计指标:switch等条件语句中不应缺失默认情况。

审计人员应检查代码switch等条件语句中是否存在缺失默认情况的情形。

无法执行的死代码问题

审计指标:不应包含无法执行的死代码

审计人员应检查代码是否存在无法执行的死代码。

返回栈上变量地址问题

审计指标:不应返回栈上的变量地址

审计人员应检查代码在函数中是否存在返回栈变量地址的情形。因栈变量在函数调用结束后就会被释放,再使用该变量地址时会出现意想不到的结果。

可达断言

审计指标:不应包含可达断言。

审计人员应检查代码在非测试版本中是否包含可达断言。若服务器处理多个并发连接,而断言在其中某个连接中发生,就会导致所有其他连接断掉,从而导致拒绝服务。

实现不一致函数问题

审计指标:不应使用具有不一致性实现的函数或字符。

审计人员应检查代码是否存在使用了在不同版本具有不一致实现的函数或字符。因使用在不同操作系统或不同版本实现不一致的函数,可能导致代码被移植到不同环境时改变行为。

表达式永真或永假问题

审计指标:不应出现表达式永真或永假代码。

审计人员应检查代码是否存在表达式逻辑永真或永假代码的情形。

原文始发于微信公众号(安全架构):代码审计的规范参考

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月8日22:18:31
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   代码审计的规范参考https://cn-sec.com/archives/2825972.html

发表评论

匿名网友 填写信息