软件代码缺陷概述

编写进度

软件供应链安全分析

源代码缺陷

 在SDL(Security Development Lifecycle)中的编码阶段产生的缺陷。

产生缺陷的原因

  • 开发人员的经验和能力限制
  • 引入某些开源项目
  • 产品发布前未进行安全测试,仅进行功能测试和性能测试

缺陷的类型

输入验证类

从安全角度来看,一切外部来源的数据均应视为不可信数据
任何输入内容均应在经过严格过滤或验证后,再进行相应的逻辑处理或存储

常见输入验证类缺陷

  • SQL注入
  • XSS
  • LDAP注入
  • XPath注入
  • OS命令注入
  • XML外部实体注入

缺陷成因

输入数据=(特殊字符、编码、数字) => 注入载体(Payload)

Payload= (几乎任何)外部数据源<环境变量、所有类型的用户参数、外部Web服务等>

程序未对 输入数据 进行有效验证所导致的缺陷

防范措施

通用的解决方式 :对输入进行验证,对输出进行编码

  • 输入验证

    1. 对所有输入明确字符集,如UTF-8
    2. 对Request进行数据验证,如数据是否包含超出预期字符,数据范围,数据长度,数据类型
  • 输出编码

    1. 通过语意输出编码方式,对所有返回到客户端的来自应用程序信任边界之外的数据进行编码,净化所有不可信的数据输出
    2. 在基本字符不满足业务规则时,需要对危险字符(<、>、\、、%、\、、)进行输出编码,使用特定的安全API

资源管理类

   指因程序对内存、文件、流、密码等资源的管理或使用不当而导致的缺陷。

常见资管管理类漏洞

  • 缓冲区上益/下溢
  • 资源未释放
  • 内存泄漏
  • 硬编码密码

缺陷成因

内存资源使用不当
内存资源的不当使用通常会导致程序运行破坏、提升权限等危害
  • 缓冲区溢出:
      针对程序设计缺陷,向程序源缓冲区写入使之溢出的内容(超过缓冲区能保存的最大数据量的数据), 从而破坏程序运行或趁着中断之际获取程序乃至系统的控制权,根据溢出边界不同分为缓冲区上溢和下溢。
  • 越界访问
      当程序访问一个数组中的元素时,如果索引值超过数组的长度,就会导致访问数组之外的内存,出现越界情况。
内存、文件、流等资源管理不当
缺陷名称 定义
内存泄漏 动态申请的内存未进行有效的释放
释放后使用 申请的内存被释放后继续被使用的情况
二次释放 对已经释放后的内存进行重复释放
错误的内存释放对象 释放的对象并非动态分配的内存
密码的管理不当
程序中硬编码会带来敏感信息泄漏、维护困难等问题,弱加密不能有效保护密码

防范措施

  1. 对不可信数据进行输入和输出控制。
    在进行内存操作时,检查缓存大小,以确保不会出现超出分配空间大小的风险
  2. 在内存、文件、流等资源使用完毕后应正确释放资源
    多次资源分配且未合理释放会耗尽资源,导致拒绝服务攻击
  3. 所有进程和线程都应遵循相同的锁定^1步骤
    若未严格遵循这些步骤,那么其他进程和线程可以以原始进程不可见或无法预测的方式修改共享资源,导致数据或内存损坏、拒绝服务等
  4. 为防范对随机数据的猜测攻击,应当使用加密模块中已验证的随机数生成器生成所有的随机数、随机GUID和随机字符串。保护主要秘密信息免受未授权的访问并使用相关的政策和流程以实现加、解密的密钥管理,使用AES加密算法更安全。同时避免使用硬编码密码的方式存储密码。

代码质量类

指由于代码编写不当所导致的缺陷,低劣的代码质量会导致不可预测行为的发生。

缺陷成因

整数问题
整数分为有符号整数和无符号整数,且有各自的取值范围。当值超出各自的取值范围时会发生回绕
空指针解引用
指针存储的是它指向的变量的地址
解引用就是引用它指向的变量的值

当指针的值为NULL或未初始化时,对其进行解引用,会导致程序异常崩溃或者出现其他未定义的行为。

初始化问题
根据未初始化变量的位置的不同可分为
- 返回值未初始化
- 参数未初始化
- 赋值未初始化等

变量在使用前应该被初始化,如果没有进行初始化,那该变量默认值时不确定的,使用此默认值可能导致出现未定义的行为
若此变量时指针类型且没有初始化的情况下进行了解引用,那么会导致空指针解引用

不当的循环终止
在循环语句中,循环体被重复执行的次数由循环条件所控制。它是一个标量表达式
若控制表达式的值不等于0,循环条件为true;反之循环条件为false。
当循环条件设置不当时,会导致死循环的产生。

防范方法

  • 在使用整数时,要避免操作结果超出整数的取值范围
  • 在使用指针时,要判断其是否为空
  • 变量在定义或声明时进行初始化,养成良好的编码习惯
  • 描述循环问题时,要注意设置恰当的循环条件

发现缺陷的方法

人工审计

人工对源代码进行走查,依据缺陷的特征进行查找和分析,从而确定是否存在缺陷。
优点:
    人工审计优势体现在可以发现与业务逻辑等相关的缺陷
 缺点:
     对审计人员能力要求高,需具备熟悉软件业务,读懂源码,且具有丰富安全知识

工具审计

运行源码缺陷检测工具,自动发现源码中存在的缺陷

自动化检测工具通常内置多种检测规则,在接收到输入内容后,将输入内容转变为易于扫描分析的数据结构,然后使用静态分析技术对其进行分析,从而发现源码中存在符合一定模式的缺陷。
优缺点:
效率高,存在误报漏报问题

  • 奇安信代码卫士
  • 360代码卫士
  • 端玛DMSCA
  • VeraCode静态源代码扫描分析服务平台
  • Fortify SCA 及 Checkmarx产品扫描服务

人工审计与工具审计结合

先通过工具审计的方式获取检测结果,然后再人工对检测结果进行复审,从而发现缺陷。

缺陷处置流程

1.发现并确认缺陷

  • 与开发流程整合
    • 开发人员可以在管理平台中配置好任务计划,检测工具根据任务计划的设定,自动从SVN、Git等代码仓库中获取代码进行检测。检测结束后,可以查看检测结果并进行审计。
  • 安全部门实施测试
    • 在系统上线前,安全部门要对全部源代码进行一次安全检测和审计,对软件源代码的安全状况进行整体把控,并修复发现的安全缺陷,在代码各项指标达到最初设定的安全目标后方可上线发布。

2.修复缺陷

缺陷修复通常由开发和运维人员修复。开发人员需要根据缺陷的具体信息,制定修复方案,确认方案无误后可修改源代码,完成缺陷修复

3.回归测试

需要对修复后的源代码进行回归测试,用于确认缺陷是否已经被修复且未引入新的缺陷。

自动化缺陷检测技术

语法分析技术

语法分析指按照具体编程语言的语法规则处理词法,分析程序产生的结果并生成语法分析树的过程,是编译过程中的重要步骤,也是其他分析的基础。

此过程可以判断程序中是否存在语法错误(是否与BNF范式一致)

类型分析技术

类型分析主要指类型检查,分析程序中是否存在类型错误。
类型错误通常指违反类型约束的操作,

控制流分析技术

控制流分析的输出是控制流图,
通过控制流图可以得到关于程序结构的一些描述,包括条件、循环等信息。

数据流分析技术

数据流分析用于获取有关数据如何在程序的执行路径上流程的信息。
同时污染传播分析也是数据流分析技术的一种应用。

代码安全保障技术趋势

随着开发模式的不断演进和信息安全趋势的变化,人们对代码安全保障技术提出了规模化、自动化、智能化的要求,以期实现软件快速、安全、自动的发布。

基于AI的代码安全分析

人工智能技术和传统代码安全技术的结合是代码安全领域的重要发展趋势之一。

引入人工智能后,我们可以将SAST工具的结果作为输入,不断进行缺陷训练,从而发现误报,
然后系统会输出某个置信水平内的误报列表(或排除误报的列表)。
为了对其进行进一步的改进,可以通过结果的审计,识别出新的误报并反馈到训练集中,计算出新的模型。

面向安全的软件代码成分分析

SCA技术和其他AST技术的深入融合也是代码安全技术发展的趋势之一。

软件代码成分分析(Software Composition Analysis,SCA)技术指通过对软件的组成(如源码、字节码、二进制文件、可执行文件等)进行分析,
识别出软件中使用的开源和第三方组件(如 底层库、框架等),
进一步发现开源安全风险和第三方组件的漏洞。

面向DevSecOps的代码安全测试

能够在代码编写的同时,发现代码中的安全隐患,从而在第一时间修复,成为DevSecOps的基本需求。因此IDE插件、轻量级的客户端快速检测模式也成为下一代代码安全产品的标配。

由于大量应用持续集成,部署在DevOps中,代码安全产品需要与Jenkins、Bamboo等持续集成系统,Bugzilla、Jira等生命周期管理系统进行集成,实现有效的自动化。
同时,提供针对代码安全基线的检测,以及增量分析、审计信息携带等功能,可在少量或没有人工参与的情况下,尽可能快速、有效保证软件的安全性。

交互式应用安全测试

IAST技术结合DAST技术和SAST技术,从而提高测试的准确率,同时对代码的测试覆盖率达到了与SAST相似的水平。

IAST的插桩模式原理:
插桩探针想要分析数据流需要做两件事:

  1. 理解代码
     根据不同语言来区分需要关注哪些函数,这些函数里哪些是污点输入?哪些是污点传播?哪些是污点清洗?以及又有哪些是污点汇聚?这个我们可以根据不同的漏洞原理来做分析.
  2. 捕获关键关键函数的调用情况
     Java提供了一个instrumentation 接口。通过该接口,可以以一种标准的方式,在启动应用时添加javaagent参数来加载插桩探针,通过Agent获取到JAVA的目标代码(字节码)、并修改字节码的方式在程序目标码确定函数执行点,并追踪函数执行过程,分析数据流。从而实现动态数据流污点追踪。

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 askding@qq.com

💰

×

Help us with donation