飞不高 发表于 2024-5-29 13:49:29

掌握这些代码安全检视方法,提拔你的代码质量

本文分享自华为云社区《代码的安全检视》,作者:Uncle_Tom。
1. 熵的故事

熵的概念最早劈头于物理学,用于度量一个热力学体系的无序水平。热力学第二定律,又称“熵增定律”,表明了在自然过程中,一个孤立的体系总是从最初的集中、有序的分列状态,趋向于分散、混乱和无序;当熵到达最大时,体系就会处于一种静寂状态。
普通的讲:体系的熵增过程,就是由原始到殒命的过程。“熵” 是 “生动” 的反义词,代表负能量。
物质总是向着熵增演化:

[*]屋子不摒挡会变乱;
[*]手机会越来越卡;
[*]耳机线会凌乱;
[*]热水会慢慢变凉;
[*]太阳会不断燃烧衰变
[*]… …
[*]直到宇宙的尽头 – 热寂。
自然界除了自然风化的作用,也少不了人为的因素。
1982年3月,詹姆士·威尔逊(James Q. Wilson)及乔治·凯林(George L. Kelling)发表一篇题为《Broken Windows》的文档,提出了犯罪学的一个理论 – 破窗效应。此理论以为环境中的不良征象如果被放任存在,会诱使人们仿效,甚至变本加厉。
一个房子如果窗户破了,没人去修补,隔不久,其他的窗户也大概莫名奇妙地被人打破。环境可以对一个人产生强烈的暗示性和诱导性。
这个理论从另一个侧面说明了对一个体系需要及时维护,以减少人为的熵增征象。古人云:勿以恶小而为之,勿以善小而不为。
对于我们创造的代码,也是一样,大家制定了编码规范,以期尽量减缓熵增,从而到达延长软件的生命周期。
2. 代码检视的意义

代码检视一直被以为是提高代码质量的重要手段,同时也是发现潜在标题的重要途经。代码检视有以下重要意义。
2.1. 编写易于理解的代码

代码检视是确保代码质量的重要环节,它有助于开发人员编写易于理解的代码。
微软和谷歌等公司在代码检视中积累了丰富的履历,夸大了代码的可读性对于团队协作的重要性。今世码清晰、布局良好时,其他开发人员能够更快地理解代码的功能和目的,从而提高团队的整体效率。此外,良好的代码可读性也有助于新成员快速融入团队,因为他们可以更容易地理解现有的代码库。
史蒂夫·迈克康奈尔的《代码大全》,被福布斯技能委员会(Forbes Technology Council)誉为“有史以来最好的软件开发基础书” 。
《代码大全》书中提到了提高代码可读性的多种方法,包罗利用故意义的变量名、避免嵌套过深的语句、利用函数和模块、面向对象编程、避免重复代码、利用设计模式、编写解释和文档、利用调试工具、进行代码审查、学习和利用更高级的编程语言和技能等等。
软件工程的焦点就是管理复杂度。规模更大的项目,如果不对复杂性做出限制,那么项目的每个步骤都大概瓦解失控。以往,无数大型项目都在砸下巨量资金后失败了,缘故原由就是其过于复杂,已经无人能理解毕竟发生了什么,就如同过于庞大的巨兽被自身重量所压垮。
复杂性其实贯穿于软件开发的各个阶段,复杂性在编码过程中,如果底层代码的质量不好,超大规模体系也大概就由此瓦解。所以必须立足底层,立足细节抓代码质量,关注每个语句、例程和类,步步为营,以此为基础才能扩大规模,同时继续保持代码质量,即在设计和架构层级控制复杂性,对复杂性控制要广泛而深入地体如今软件开发的各个阶段。
唐纳德·克努特(Donald Knuth),他在编程界被广泛以为是“计算机程序设计艺术”的首创人之一。克努特曾说过:“Programs are meant to be read by humans and only incidentally for computers to execute.” 这句话夸大了代码的可读性对于人类的重要性,意味着代码首先应该是为了让人理解而编写的,而机器执行只是其次。
https://bbs-img.huaweicloud.com/blogs/img/20240526/1716719615025904107.png
这是《A practical guide to object-oriented metrics》中的一个统计图,作者分析了一个数据库体系,黄色柱状体是缺陷的百分比,红色柱状体是代码的比例,横坐标标识了不同圈复杂度。最左边代码圈复杂度在0-5的时候,代码量占了总量的40%,缺陷数占了10%,而最右边圈复杂度为15+, 代码量占比10%,但缺陷数量占了缺陷总数的40%+。从左向右的可以看到代码的圈复杂度越高,缺陷的比例也越高。
通常我们不能一次性编写出完全满足需求的代码;或者需求在不断的变化;维护代码的人往往不是原始开发的人员,这些都要求我们编写的代码是可被另一个人所理解和修改的。
2.1.1. 维护规范

代码检视是维护编码规范的关键机制。
代码的可读性、可维护性需要详细的规约来保持。我们往往通过编码规范来维护和保持代码的易于理解和避免一些常见的错误(或被称为最佳实践)。因此各大公司都有了自己的编码规范,比如我们熟知的google的编码规范。同时行业也为了维护行业的同一性,也给出了行业的编码规范,像MISRA C 2012、AUTOSAR C++14 等等。更多的关于规范的信息,可参考《一图看懂软件缺陷检查涉及的内容》。
通过代码检视,可以确保所有代码都遵循了既定的编码标准和最佳实践。这有助于保持代码库的一致性,减少由于风格不一致或不遵循规范导致的维护标题。
目前的编码规范通常会包含两部分:
一致的代码风格。整个项目中保持一致的编码风格,可以减少开发者在阅读不同部分代码时的认知负担,因为他们不需要适应不同的风格。这包罗:

[*]命名规范
利用清晰、故意义的变量名和函数名,可以帮助其他开发者快速理解代码的目的和功能。例如,利用calculateTotalPrice代替cTP,使得函数的作用一览无余。
[*]代码格式化
同一的缩进、括号利用和空白利用,可以使代码布局更加清晰,便于阅读和理解代码的逻辑布局。
[*]解释和文档
得当的解释和文档可以为代码提供上下文信息,解释复杂的逻辑或决策,使得其他开发者能够更快地理解代码的意图和工作方式。
编码实践
每个编程语言都有自己的特点和特定的规约,很多地方往往被开发人员忽略从而埋下潜在的风险。
这部分通常包罗:

[*]声明和初始化
[*]类型转换
[*]表达式
[*]函数或方法
[*]并发
[*]错误和异常处理
[*]面向对象的编程
[*]输入输出
[*]外部输入校验
[*]日志处理
[*]其他
规范的维护还有助于提高代码的可维护性和可扩展性,因为所有开发人员都遵循相同的规则和模式。
目前规范的很多部分都能够被静态分析工具检测到,甚至自动修复。这些工具的告警也会在代码检视的时候得到确认,是否是误报,照旧确实需要修改。对被确认误报的部分会反馈给工具团队,进一步的修正检查工具,起到对工具反馈的作用。
此外,代码检视还可以作为规范更新和改进的反馈机制,团队可以根据实际开发履历,不断调整和完善编码规范,以适应不断变化的开发需求和技能进步。
2.1.2. 学习和教诲

代码检视为开发人员提供了学习和教诲的机会。
在微软和谷歌等公司,代码检视被视为一种学习和知识共享的平台。通过检视他人的代码,开发人员可以学习到新的编程本领、设计模式和最佳实践。
同时,代码的作者也可以从其他开发人员的反馈中学习,了解自己的代码在哪些方面可以改进,这对于个人技能的提拔非常有帮助。代码检视还可以作为一种教诲工具,帮助新员工快速了解公司的代码风格和开发流程。通过参与代码检视,新员工可以更快地融入团队,提高自己的开发能力。
代码检视还可以揭示潜在的设计标题,促进团队成员之间的知识共享,加强团队的凝聚力。通过代码检视,开发人员能够从同事那边得到反馈,学习如何写出更清晰、更高效的代码,这对于个人技能发展和团队协作都是有益的。
2.1.3. 把关和变乱预防

代码检视在把关和变乱预防方面起着至关重要的作用。
代码检视除了确保代码的质量,还可以防止潜在的错误和缺陷进入生产环境。代码检视可以帮助开发人员发现代码中的错误,包罗逻辑错误、性能标题、安全漏洞等,从而在代码发布前进行修复。这不仅可以减少生产环境中的标题,还可以降低维护成本和风险。
固然静态分析工具在缺陷检查上负担了越来越重要的防护作用,可毕竟检查能力在开发框架和第三方调用上,需要很多的人为配置才能使分析工具在很大水平上识别框架上潜在的调用关系和第三方函数的行为。目前静态分析工具在这方面都还有很大的欠缺,这将导致很多的漏报。所以代码检视在防范代码缺陷上照旧不可缺少的检查环节。
随着外部的恶意攻击的增加,缺陷的发现和漏报的矛盾也越发的突出。
检查工具毕竟只是辅助,照旧需要开发人员建立安全防范意识,写出没有缺陷的代码,这个才是安全预防的治本方法。通过代码检视,团队可以建立起一种预防文化,不断提高代码质量,减少变乱发生的概率。
3. 代码检视中需要注意的标题

3.1. 代码检视的文化建设

将代码评审用作团队建设活动,培养对发现缺陷的积极态度。为所有团队成员提供纠正坏习惯、学习新本领和扩展能力的机会。
恭敬和鼓励、礼貌和专业精力;

[*]作为考核人员,保持恭敬的态度,鼓励团队成员参与代码审查;
[*]作为开发人员,放弃负面情绪,将其视为学习和发展的机会。
3.2. 代码检视提交

一次代码提交不易过大
SmartBear对思科体系编程团队的一项研究表明,开发人员一次审查的代码行数不应超过200到400行(LOC)。大脑一次只能有效地处理这么多信息;超过 400 LOC,发现缺陷的能力会减弱。
在实践中,在 60 到 90 分钟内对 200-400 LOC 进行审查应该会产生 70-90% 的缺陷发现。因此,如果代码中存在 10 个缺陷,那么正确进行的审查会发现其中的 7 到 9 个。
https://bbs-img.huaweicloud.com/blogs/img/20240526/1716719651220915379.gif
SmartBear 研究表明,以每小时 500 LOC 的速率快速下降,缺陷密度显着下降。在有限的时间内以合理的速率进行合理数量的代码审查,从而产生最有效的代码审查。
https://bbs-img.huaweicloud.com/blogs/img/20240526/1716719663978684790.gif
在代码提交检视前还需要完成以下工作:

[*]完成当地测试;完成代码的自检,是作为一个合格代码开发人员的基本素质。
[*]每次提交的代码量不易过多,通常在 200 到 400 行代码之间,以保证审查质量;从前面的研究可以看到,太大的代码提交即未便于审阅者快速完成一次提交的审查,也未便于发现错误。关于如何将较大的改动拆分成较小的变动,google 在代码考核中给出很好的建议。
[*]有清晰的代码变更描述。可以包罗:摘要、配景、说明、需求或设计的变更单关联;目前代码审查的平台都提供了很好的辅助,帮助考核人员快速得到考核代码相关的信息,方便考核人员理解被考核代码。
3.3. 代码检视考核的重要内容

代码考核人员在考核过程中重要的考核内容包罗:

[*]利用检查清单是消除常常犯的错误和应对遗漏发现挑衅的最有效方法。清单为团队成员提供了对每种类型审查的明确渴望,并有助于跟踪报告和流程改进目的。
[*]所有内容都利用了明确的名称,代码符合规定的风格指南;
[*]不过分设计,代码并没有比它需要的更复杂;
[*]没有显着的逻辑错误,异常处理完备;
[*]代码具有得当的单元测试,测试是经心设计的。
4. 代码检视中需要注意的安全标题

结合业界的重要安全编码标题,总结了代码检视的安全检查清单如下。
注:下面标题涉及的 CWE 有的是类别,需要包罗下面的子CWE编号。
4.1. 外部输入校验

[ ] 是否有外部输入,例如:http request, 表单输入、配置文件、数据库读?

[*][ ] 是否对输入做了正确的转义?
[*][ ] 是否对输入做了白名单或范围检查?
[*][ ] 是否对外部输入的链接执行了跳转或信息获取?链接是否做了白名单检验?
防范的标题:

[*]CWE-1406:不正确的输入验证
[*]CWE-601:指向未可信站点的URL重定向(开放重定向)
[*]CWE-698:重定向后执行(EAR)
4.2. SQL 检查

[ ] 是否有 SQL 操作?

[*][ ] 是否有外部输入作为 SQL 语句的组成部分?
[*][ ] 是否有拼接 SQL 语句的场景?
[*][ ] 是否有删库、删表、索引变更、改权限的操作?是否合理,并做了条件限制?
[*][ ] 获取的 connection 和 statement 是否关闭?
防范的标题:

[*]CWE-89:SQL命令中利用的特别元素转义处理不恰当(SQL注入)
[*]CWE-772:未释放超过有效生命周期的资源
4.3. 命令执行检查

[ ] 是否有命令操作?

[*][ ] 是否有外部输入做为命令操作组成部分?
[*][ ] 执行命令是否做了白名单校验?
防范的标题:

[*]CWE-77:在命令中利用的特别元素转义处理不恰当(命令注入)
4.4. 文件操作

[ ] 是否有文件操作?

[*][ ] 文件的路径是否做了归一化和路径校验?
[*][ ] 是否为 XML 文件, 是否做了 XXE 防护?
[*][ ] 是否对 JSON, XML 等做了反序列化操作? 反序列化文件是否安全?
[*][ ] 是否做了写文件操作? 是否写入了敏感信息?敏感信息的存储是否符合规定?
[*][ ] 是否有上传文件? 文件的类型、大小是否做了限定和检查?
[*][ ] 是否有解压缩操作? 是否对解压缩的路径和大小做了校验?
[*][ ] 文件是否采用了 try-with-resource 方式打开?否则是否在 finally 里关闭?
防范的标题:

[*]CWE-22:对路径名的限制不恰当(路径遍历)
[*]CWE-611:XML外部实体引用的不恰当限制(XXE)
[*]CWE-91:XML注入(XPath盲注)
[*]CWE-502:不可信数据的反序列化
[*]CWE-538:文件和路径信息泄漏
[*]CWE-499:可序列化的类中包含敏感信息
[*]CWE-434:危险类型文件的不加限制上传
[*]CWE-772:未释放超过有效生命周期的资源
4.5. 不安全反射

[ ] 是否有反射操作?

[*][ ] 类是否为外部指定? 是否做了白名单校验?
[*][ ] 反射的方法是否为外部指定? 是否做了白名单校验?
防范的标题:

[*]CWE-470:利用外部可控制的输入来选择类或代码(不安全的反射)
4.6. 输出到页面

[ ] 是否有页面输出操作?

[*][ ] 是否有外部输入直接输出到页面?是否做了转义和校验?
[*][ ] 是否有敏感信息?
防范的标题:

[*]CWE-79:在Web页面生成时对输入的转义处理不恰当(跨站脚本)
[*]CWE-202:通过数据查询的敏感数据泄漏
4.7. 输出到日志

[ ] 是否有日志输出操作?

[*][ ] 是否有外部输入直接写如日志? 是否做了转义处理?
[*][ ] 是否有敏感信息输出到日志中? 是否做了匿名化、脱敏处理?
[*][ ] 是否将异常信息直接输出到日志中?是否做了脱敏和屏蔽处理?
防范的标题:

[*]CWE-532:通过日志文件的信息泄漏
[*]CWE-209:通过错误消息导致的信息泄漏
4.8. 数据传输

[ ] 是否有数据传输操作?

[*][ ] 传输协议是否符合规定?
[*][ ] 是否有敏感信息传输?安全防护措施是否符合规定?
防范的标题:

[*]CWE-201:通过发送数据的信息泄漏
[*]CWE-327:利用已被攻破或存在风险的密码学算法
4.9. 安全加密

[ ] 是否有加解密操作?

[*][ ] 是否采用了规定的加、解密函数和处理顺序?
[*][ ] 密钥、随机数的获取是否正确?
[*][ ] 是否存在硬编码密钥的场景(包罗密钥写在解释中)?
防范的标题:

[*]CWE-327:利用已被攻破或存在风险的密码学算法
[*]CWE-325:缺少必要的密码学步骤
[*]CWE-330:利用不充分的随机数
[*]CWE-547:利用硬编码、安全相关的常数
[*]CWE-259:利用硬编码的口令
[*]CWE-321:利用硬编码的密码学密钥
4.10. 权限控制

[ ] 是否有权限验证、设置、变更操作?

[*][ ] 验证步骤是否符合规范?
[*][ ] 是否存在逻辑绕过的大概?
防范的标题:

[*]CWE-1211:身份验证错误
[*]CWE-255:凭证管理
[*]CWE-275:权限标题
[*]CWE-1212:授权错误
5. 参考


[*]Mark Schroeder, “A practical guide to object-oriented metrics”, IT Pro, Nov/Dec 1999
[*]Google的工程实践文档
[*]Modern Code Review A Case Study at Google
[*]Software Engineering at Google
[*]Code Reviews at Google are lightweight and fast
[*]How Code Reviews work at Microsoft
[*]CWE
 
点击关注,第一时间了解华为云新鲜技能~
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 掌握这些代码安全检视方法,提拔你的代码质量