不良的编码模式会导致很大的安全问题......那么我们为什么要鼓励它们呢?

发布日期:2022年11月03日
作者:马蒂亚斯-马杜,博士
案例研究

不良的编码模式会导致很大的安全问题......那么我们为什么要鼓励它们呢?

发布日期:2022年11月03日
作者:马蒂亚斯-马杜,博士
查看资源
查看资源

本文的一个版本出现在 DZone.它已被更新并在此转发。

在这一点上,我们已经讨论了SDLC中的 "左移",从软件开发的一开始就考虑到了安全的最佳实践。DevSecOps是一个巨大的飞跃,这在很大程度上是因为强调了对安全的共同责任,以及有安全意识的开发人员在编写代码时挫败常见漏洞的能力。 

我们也知道--还是那句话,长久以来--选择什么样的安全代码培训来吸引开发人员并提高他们的技能会产生很大的不同。仅仅以法规遵从为动机的低效解决方案并不能培养出未来聪明的安全人才,大多数安全意识的专业人士已经明白了这一点。动态的、与背景相关的学习是最好的,但关键是要理解其中的细微差别。 

如果我们要有对抗威胁者的机会--他们总是在组织中占得先机--开发人员需要一个全面的培训环境,通过分层学习,不断地培养出浸透在最佳实践中的技能。

开发者驱动的防御性安全措施并不是一种自动的胜利。

我们的精神是围绕着开发人员是预防性安全策略的核心,就在代码级别以上。这是必然的,有安全技能的开发人员提供了最简单的途径来挫败那些在不良编码模式中显而易见的常见安全漏洞(如Log4Shell,作为最近的一个毁灭性的例子)。

然而,我们可以参与的提高开发人员技能的防御技术确实不同,即使它们可以正确地存在于同一个培训桶中。 

例如,想象一下,有人告诉你如何烘烤一个蛋糕,只使用基于什么不做的指示。"不要烤过头了","不要忘了鸡蛋",这些都是可以解释的,而且有很大的可能出现错误,最终的结果是适合于 准确无误!.防御性安全教育也是如此;做什么是对话中非常有限的部分,并且没有提供真正以防御性思维行事的实用建议。你可以告诉开发者,"不要错误地配置那个API",但如果不了解什么是正确和安全的配置,就会有很大的错误空间。

开发人员如果不了解漏洞是如何工作的,为什么它们是危险的,什么模式会导致它们,以及什么设计或编码模式能在他们的世界中修复它们,就不会对减少漏洞产生积极影响。一个脚手架式的方法允许各层的知识提供一个完整的画面,即安全编码、保护代码库和作为一个安全意识的开发者站起来意味着什么。是的,分层学习的一部分应该致力于进攻,了解攻击者的心态;这对于磨练横向思维能力至关重要,这在威胁建模和防御策略中是非常宝贵的。 

强化不良的编码模式是一个我们不能忽视的陷阱。

开发者学习的一些方法的一个不幸的现实是,"防御 "部分--即使培训的结构是进攻性技术--也会加强坏习惯,即使他们在技术上验证了代码安全。 

生产高质量的代码应该是所有软件开发的基线,但 "质量 "的定义似乎仍有争议。现实情况是,不安全的代码不能被看作是高质量的代码,即使它在其他方面是功能性的和漂亮的。最重要的是,安全的 代码本身不是高质量的。换句话说,糟糕的编码模式可以解决一个安全问题,但在这样做的时候,会引入另一个问题,或者有可能完全破坏软件。 

让我们来看看一个以修复破损认证的形式出现的劣质代码的例子,以及最佳实践的最安全版本。

使用系统。
使用System.Collections.Generic。
使用System.Linq.Definition.Command.Command.Definition
使用System.Threading.Tasks。
使用Microsoft.AspNetCore.Authorization.Ltd;
使用Microsoft.AspNetCore.Http.Communications.Communications.Communications.Communications
使用Microsoft.AspNetCore.Mvc.Ltd;
命名空间 BadFixesAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AlertsController : ControllerBase
    {
        私人DatabaseContext context = 新的DatabaseContext()。
        [HttpGet(Name = "GetAlerts")]
        // Does not ensure that the user is authenticated 
        public IEnumerable<Alert> Get()
        {
            return context.GetAlerts()。
        }
        [HttpGet(Name = "GetAlerts")]
        // Ensures that the user is authenticated, but does not check any roles
        [授权()]
        public IEnumerable<Alert> GetBadFix()
        {
            return context.GetAlerts()。
        }
        [HttpGet(Name = "GetAlerts")]
        // Ensures that the user is authenticated, AND that they have the "Administrator" role
        [Authorize(Roles = "Administrator")] 。
        public IEnumerable<Alert> GetGoodFix()
        {
            return context.GetAlerts()。
        }
    }
}

在第一个片段中,没有检查验证用户是否经过认证,这是最不安全的。第二个片段,虽然在执行认证检查方面比较好,但未能调查分配的角色以及权限是否足够高,以满足所要求的信息。第三种方法既检查用户的认证,又检查他们是否被分配了 "管理员 "角色。在这个时代,最小权限的访问控制应该是大多数情况下的标准,关键是角色的设置和检查,以确保信息只在需要了解的基础上被访问。 

开发人员最优先考虑的是构建功能,虽然安全问题没有被刻意放在后面,但他们不一定有能力避免导致安全漏洞的不良编码模式,而优秀工程师的基准很少包括安全编码的能力。如果功能足够棒,我们间接地鼓励了这些坏习惯,而这种心态必须改变。问题是,一些学习途径鼓励动手修复代码的方式也有可能强化那些安全但质量不合格的代码。通过应用二进制的 "是的这是安全的/不这是不安全的 "assessment ,而不是深入研究这是否真的是解决错误和维护软件完整性的最佳方法,在细节上有一些魔鬼没有被注意到。 

如果不把开发人员带入整个过程以获得安全编码的完整观点,这种方法会使它试图解决的问题长期存在。想象一下,如果我们都只根据我们将车辆开到目的地的能力来获得我们的执照;即使我们闯了红灯,开过了树篱,险些错过了过马路的行人,也能获得一个合格的标记来到达目的地。我们完成了目标,但我们到达目的地的旅程最重要。 

开发人员需要能够更关心创建安全的软件。

现代的开发人员必须保持很多盘子的旋转,所以他们发现安全培训很无聊也就不足为奇了,特别是当安全培训没有考虑到他们的工作日,并且把他们从他们的最后期限和优先事项中带走的时候。当他们没有从定期的、合适的学习机会和补充工具中积累的技能时,改变他们的关键绩效指标以包括强调安全编码也是完全不公平的。然而,安全软件开发的重要性怎么强调都不为过,让开发人员加入到这个行列是至关重要的。 

作为一个曾经的开发者,一般来说,我们都希望 自己能做得很好,而在质量输出方面被视为比别人高一等,是非常有动力的。激励开发人员参与到持续的安全技能建设中来是没有问题的,而且他们应该因为认识到代码级安全的重要性而得到奖励。安全冠军计划、漏洞赏金和黑客马拉松可以成为建立积极安全文化的绝佳机会,而那些卷起袖子参与其中的人应该得到奖赏。

查看资源
查看资源

作者

马蒂亚斯-马杜博士

马蒂亚斯是一名研究员和开发人员,拥有超过15年的软件安全实践经验。他曾为Fortify Software和他自己的公司Sensei Security等公司开发解决方案。在他的职业生涯中,马蒂亚斯领导了多个应用安全研究项目,并将其转化为商业产品,他拥有超过10项专利。当他离开办公桌时,Matias曾担任高级应用安全培训courses ,并定期在全球会议上发言,包括RSA会议、黑帽、DefCon、BSIMM、OWASP AppSec和BruCon。

马蒂亚斯拥有根特大学的计算机工程博士学位,在那里他研究了通过程序混淆来隐藏应用程序的内部工作的应用安全。

想要更多吗?

在博客上深入了解我们最新的安全编码见解。

我们广泛的资源库旨在增强人类对安全编码技术提升的方法。

查看博客
想要更多吗?

获取关于开发者驱动的安全的最新研究

我们广泛的资源库充满了有用的资源,从白皮书到网络研讨会,让你开始使用开发者驱动的安全编码。现在就去探索它。

资源中心

不良的编码模式会导致很大的安全问题......那么我们为什么要鼓励它们呢?

发布日期:2022年11月03日
作者:马蒂亚斯-马杜,博士

本文的一个版本出现在 DZone.它已被更新并在此转发。

在这一点上,我们已经讨论了SDLC中的 "左移",从软件开发的一开始就考虑到了安全的最佳实践。DevSecOps是一个巨大的飞跃,这在很大程度上是因为强调了对安全的共同责任,以及有安全意识的开发人员在编写代码时挫败常见漏洞的能力。 

我们也知道--还是那句话,长久以来--选择什么样的安全代码培训来吸引开发人员并提高他们的技能会产生很大的不同。仅仅以法规遵从为动机的低效解决方案并不能培养出未来聪明的安全人才,大多数安全意识的专业人士已经明白了这一点。动态的、与背景相关的学习是最好的,但关键是要理解其中的细微差别。 

如果我们要有对抗威胁者的机会--他们总是在组织中占得先机--开发人员需要一个全面的培训环境,通过分层学习,不断地培养出浸透在最佳实践中的技能。

开发者驱动的防御性安全措施并不是一种自动的胜利。

我们的精神是围绕着开发人员是预防性安全策略的核心,就在代码级别以上。这是必然的,有安全技能的开发人员提供了最简单的途径来挫败那些在不良编码模式中显而易见的常见安全漏洞(如Log4Shell,作为最近的一个毁灭性的例子)。

然而,我们可以参与的提高开发人员技能的防御技术确实不同,即使它们可以正确地存在于同一个培训桶中。 

例如,想象一下,有人告诉你如何烘烤一个蛋糕,只使用基于什么不做的指示。"不要烤过头了","不要忘了鸡蛋",这些都是可以解释的,而且有很大的可能出现错误,最终的结果是适合于 准确无误!.防御性安全教育也是如此;做什么是对话中非常有限的部分,并且没有提供真正以防御性思维行事的实用建议。你可以告诉开发者,"不要错误地配置那个API",但如果不了解什么是正确和安全的配置,就会有很大的错误空间。

开发人员如果不了解漏洞是如何工作的,为什么它们是危险的,什么模式会导致它们,以及什么设计或编码模式能在他们的世界中修复它们,就不会对减少漏洞产生积极影响。一个脚手架式的方法允许各层的知识提供一个完整的画面,即安全编码、保护代码库和作为一个安全意识的开发者站起来意味着什么。是的,分层学习的一部分应该致力于进攻,了解攻击者的心态;这对于磨练横向思维能力至关重要,这在威胁建模和防御策略中是非常宝贵的。 

强化不良的编码模式是一个我们不能忽视的陷阱。

开发者学习的一些方法的一个不幸的现实是,"防御 "部分--即使培训的结构是进攻性技术--也会加强坏习惯,即使他们在技术上验证了代码安全。 

生产高质量的代码应该是所有软件开发的基线,但 "质量 "的定义似乎仍有争议。现实情况是,不安全的代码不能被看作是高质量的代码,即使它在其他方面是功能性的和漂亮的。最重要的是,安全的 代码本身不是高质量的。换句话说,糟糕的编码模式可以解决一个安全问题,但在这样做的时候,会引入另一个问题,或者有可能完全破坏软件。 

让我们来看看一个以修复破损认证的形式出现的劣质代码的例子,以及最佳实践的最安全版本。

使用系统。
使用System.Collections.Generic。
使用System.Linq.Definition.Command.Command.Definition
使用System.Threading.Tasks。
使用Microsoft.AspNetCore.Authorization.Ltd;
使用Microsoft.AspNetCore.Http.Communications.Communications.Communications.Communications
使用Microsoft.AspNetCore.Mvc.Ltd;
命名空间 BadFixesAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AlertsController : ControllerBase
    {
        私人DatabaseContext context = 新的DatabaseContext()。
        [HttpGet(Name = "GetAlerts")]
        // Does not ensure that the user is authenticated 
        public IEnumerable<Alert> Get()
        {
            return context.GetAlerts()。
        }
        [HttpGet(Name = "GetAlerts")]
        // Ensures that the user is authenticated, but does not check any roles
        [授权()]
        public IEnumerable<Alert> GetBadFix()
        {
            return context.GetAlerts()。
        }
        [HttpGet(Name = "GetAlerts")]
        // Ensures that the user is authenticated, AND that they have the "Administrator" role
        [Authorize(Roles = "Administrator")] 。
        public IEnumerable<Alert> GetGoodFix()
        {
            return context.GetAlerts()。
        }
    }
}

在第一个片段中,没有检查验证用户是否经过认证,这是最不安全的。第二个片段,虽然在执行认证检查方面比较好,但未能调查分配的角色以及权限是否足够高,以满足所要求的信息。第三种方法既检查用户的认证,又检查他们是否被分配了 "管理员 "角色。在这个时代,最小权限的访问控制应该是大多数情况下的标准,关键是角色的设置和检查,以确保信息只在需要了解的基础上被访问。 

开发人员最优先考虑的是构建功能,虽然安全问题没有被刻意放在后面,但他们不一定有能力避免导致安全漏洞的不良编码模式,而优秀工程师的基准很少包括安全编码的能力。如果功能足够棒,我们间接地鼓励了这些坏习惯,而这种心态必须改变。问题是,一些学习途径鼓励动手修复代码的方式也有可能强化那些安全但质量不合格的代码。通过应用二进制的 "是的这是安全的/不这是不安全的 "assessment ,而不是深入研究这是否真的是解决错误和维护软件完整性的最佳方法,在细节上有一些魔鬼没有被注意到。 

如果不把开发人员带入整个过程以获得安全编码的完整观点,这种方法会使它试图解决的问题长期存在。想象一下,如果我们都只根据我们将车辆开到目的地的能力来获得我们的执照;即使我们闯了红灯,开过了树篱,险些错过了过马路的行人,也能获得一个合格的标记来到达目的地。我们完成了目标,但我们到达目的地的旅程最重要。 

开发人员需要能够更关心创建安全的软件。

现代的开发人员必须保持很多盘子的旋转,所以他们发现安全培训很无聊也就不足为奇了,特别是当安全培训没有考虑到他们的工作日,并且把他们从他们的最后期限和优先事项中带走的时候。当他们没有从定期的、合适的学习机会和补充工具中积累的技能时,改变他们的关键绩效指标以包括强调安全编码也是完全不公平的。然而,安全软件开发的重要性怎么强调都不为过,让开发人员加入到这个行列是至关重要的。 

作为一个曾经的开发者,一般来说,我们都希望 自己能做得很好,而在质量输出方面被视为比别人高一等,是非常有动力的。激励开发人员参与到持续的安全技能建设中来是没有问题的,而且他们应该因为认识到代码级安全的重要性而得到奖励。安全冠军计划、漏洞赏金和黑客马拉松可以成为建立积极安全文化的绝佳机会,而那些卷起袖子参与其中的人应该得到奖赏。

我们希望得到您的许可,向您发送有关我们产品和/或相关安全编码主题的信息。我们将始终以最谨慎的态度对待您的个人资料,绝不会将其出售给其他公司用于营销目的。

提交
要提交表格,请启用 "分析 "cookies。完成后,请随时再次禁用它们。