在任何开发过程中,只要涉及到安全问题,我们就需要牢记Shannon的话。虽然它与密码学有关,但也可以应用于服务安全。也就是说,我们应该假设攻击者最终会完全熟悉该系统。作为外卖业务的开发者,安全一直是一个重要的话题,如果你从事健康、金融等相关领域,尤其是北美合规。除了来自业务的一些安全考虑,例如密码强度和多重身份验证(MFA),更多与安全相关的问题对于一个认真的开发人员来说可能很难综合考虑。在此,我想借用一个与医疗保健相关的项目来介绍该项目面临的安全需求和实践。背景除了满足用户在业务上的安全需求,以及一些常规的离散安全理解(TLS、注入、DoS等),我们没有全局的系统安全考虑,客户也提出了第1条安全需求没有组织和结构需要在与客户交谈之前进行大量的讨论和研究。对于计算机安全的定义,机密性、隐私和完整性是三个关键目标。从计算机安全模型来看,它包括硬件、软件和通信。对于这样的分类和定义,如果我们能够做好威胁建模,那么结果可能会更全面,但是问题又来了,由于组内大部分成员都没有威胁建模的经验,我们很难做好威胁建模,使我们的结论可能无法达到我们想要的目标。这样的话,我们可以从一个比较直观和笼统的层面,让大家了解我们可能面临的防护和攻击,在最基础的层面上有一个大概的认识。应用应用程序身份验证和授权。所有需要认证的请求都会经过GatewayAmbassador,使用Ambassador提供的Filter和FilterPolicy来控制认证接口。不同的接口会有不同的权限。该层在应用层上实现。所有用户只能访问租户中属于自己的资源,这也是在应用层实现漏洞。其实我们经常听到很多关于这种攻击的说法,比如SQL注入,XSS等等。这些攻击实际上已经帮助我们在目前使用的通用框架中做好了防护工作。比如现在的ORM框架已经有了Parameterizedquery来防止注入(前提是我们不拼接查询),SpringSecurity也提供了CSPheaders来防范XSS。另一个例子是CSRF。在我目前所知道的使用Spring的应用中,都是禁用的。因为实际上,如果我们使用JWTtoken进行认证而不是基于cookie的认证,那么我们不需要做更多的事情来防止CSRF。日志在我们的实现中,我们对日志进行了不同的分类。一类是基础业务应用日志,主要方便发现生产环境中的问题;另一类是审计日志,主要记录用户行为,包括哪个用户从某个IP做了什么样的请求操作,也可以防止用户RepudiationofAction。GCP中的日志服务提供了日志桶。我们将以上两种类型的日志放到不同的桶中,这样就可以为不同的日志设置不同的保留期。电子邮件电子邮件安全可能是我们容易忽视的一个问题。专为电子邮件设计的安全性包括DMARC、SPF和DKIM。因为项目上使用了邮件服务Sendgrid,邮件服务中实现了DMARC、SPF和DKIM。在这里我要让大家明白,即使是邮件功能,其安全状态也不容忽视。如果基础设施网络在可信的VPC中,我们可以在LoadBalancer上终止TLS,这个VPC中的任何流量都将在解密后传输。但实际上,集群中服务与服务之间的安全也是需要保证的。正确配置Firewall,启用DNSSEC,配置Egress到可信外部服务,使用WAF控制服务访问等,都是我们在网络上可以考虑的安全要素,因为网络安全是一个比较大的话题,而我的知识篇幅有限,就不展开了。安全态势监控我们需要知道我们服务的资产,哪些资产对业务很重要,我们还需要知道我们采取了哪些安全措施来保护我们的资产。对于部署在GCP之上的资产,GCP的安全指挥中心可以帮助我们了解和修补GCP的安全和风险。提供不同等级的服务,详情请参考安全指挥中心。定期或主动轮换现有密码的密码密钥轮换培训。GCP的SecretManager配合pubsub和CloudFunction设置一个轮换周期来帮助我们定时修改密码,但是我们的部分密码是API密钥或者第三方系统集成的私钥,使用Secret提供的轮换功能不方便经理。对于此类第三方密码,运维人员仍然需要在第三方服务中手动更新密码,或者使用其提供的API或脚本重新生成密码,然后使用Terraform控制GCPSecretManager来帮助我们管理密码。但是这里有个问题,密码不能明文保存到对应的Terraformrepo中,所以我们只在项目中加密密码文件,然后上传。对于Terraform更新密码或在本地执行terraformapply,没有比这更有效的方法了。道路。SecurityCheck/TestingSecurityCheck/Testing静态扫描我们可以使用很多静态扫描工具来帮助我们提高代码质量,也可以帮助我们揭示代码层面的安全风险。这些工具会集成到我们的CI中,比如gitleaks帮助我们检查是否有硬编码的密码、私钥等信息,OWASPDependencyCheck检查漏洞。动态扫描除了静态扫描,动态扫描还可以帮助我们排查应用服务的安全风险,比如前面提到的XSS、注入等,可以通过周期性的动态扫描来规避风险。虽然我们不能完全依赖此类扫描工具来保护我们的应用服务,但这可以在一定程度上降低风险的可能性。MobileRunApplicationSelfProtectionRASP对于大部分应用的外围保护,比如防火墙,IDS,这些保护只是针对运行环境的保护,但是当它是针对应用本身设计的时候,这样的保护是不会有针对性的,即可以说,它会突破这些保护限制,也会对应用程序造成威胁。然后是移动应用程序,与部署在几乎完全受我们控制的环境中的服务器端应用程序不同,它可能运行在一个早已过时或安全性较低的操作系统版本上。这时候就需要一个能够提供自我保护的应用程序。在绿码项目中,我们使用了客户合作的PromonSHIELD,它提供了根检测、代码混淆、代码注入保护、屏幕阅读器保护等可配置的保护。RASP更多的是为应用本身提供保护,所以我理解它的实现无非是在应用内部,比如针对特定应用场景的保护,或者是在应用之外的一层保护膜,比如使用PromonSHIELD作为一层wrapper,如下:AppAttestation正如开头所说,我们在设计系统的时候,一定要考虑到攻击者最终会完全熟悉我们的系统。那么想象一下,攻击者有了这些知识之后,是不是可以做出一个和我们一模一样的app。如果这个时候我们如何防止这种类似钓鱼的攻击发生。有多种方法可以为iOS和Android进行认证。在我们的项目中,Android使用的是SafetyNetAttestation,而iOS使用的是通知推送机制。虽然Android本身有通知推送机制,但其推送地址与这个合法APP的关系只是包名,但iOS的推送机制是基于推送证书的,所以使用Android提供的SafetyNet更靠谱。下面是一个简单的流程图,有兴趣的同仁可以更进一步。这里的结论只是从一个普通认真的开发者的安全角度,简单罗列一些其他项目可能参考的安全实践。但安全远不止于此,涉及的知识面也很广,上面提到的任何一点都可以深入探讨。【本文为专栏作者“ThoughtWorks”原创稿件,微信公众号:Thinkworker,转载请联系原作者】点此查看该作者更多好文
