如何保护无服务器(开放)API?
介绍
OWASP 十大
结束语
进一步阅读
上周,由于突然采取的疫情措施,我无法发表一篇正式的文章(我希望每个人都平安!),所以我决定推迟。
话虽如此,我想讨论如何使用我们正在使用的 AWS 服务中已经存在的工具来保护您的(开放)API,以及AWS WAF(Web 应用程序防火墙)如何提供帮助(需要付费)。
我们将讨论以下主题:
介绍
为了使本次讨论更有针对性,我将使用OWASP 十大Web 应用程序漏洞作为指导列表。
本文要考虑的架构是我用于本系列 OpenAPI 文章的参考应用程序架构。
rpstreef / openapi-tf-示例
如何将 OpenAPI 与 AWS API Gateway 结合使用的示例,还包括与 AWSLambda、AWS Cognito、AWS SNS 和 CloudWatch 日志的集成
它的特点是;
- API 网关,公开所有可用的服务
- Lambda包含最终向 API 公开/处理数据的代码。
- Cognito 用于身份管理,身份注册、登录和会话管理。
- CloudWatch 日志、错误、信息、调试日志和警报服务。
- SNS,可靠且持久的基于发布/订阅消息的集成服务。
- AWS CodePipeline 和 CodeBuild,用于 Lambda 代码部署的 CI/CD。
通常您还会使用数据源,这里我们可以假设我们使用的是 NoSQL(DynamoDB)或 SQL 变体(MySQL、Postgress)。
OWASP 十大
OWASP 列表代表了对 Web 应用程序最严重的安全风险的广泛共识。
对于这 10 个项目,我将逐一介绍其相关的一般风险,并针对每个相关的 AWS 服务提出可行的解决方案。在每章的结论中,我将简要阐述我的建议。
(1)注射
风险
注入风险最普遍存在于环境变量、(无)SQL 查询、JSON/XML 解析器和 API 查询/正文参数中。
解决方案
AWS API 网关和 OpenAPI
为了缓解任何类型的注入攻击,我们可以强制 API 的正确输入。为此,我们可以利用 API 网关中的“模型”概念。这些模型本质上是 JSON Schema,定义了哪些类型的数据可以作为输入,哪些类型的数据可以作为执行后的输出。
例如,此寄存器模型具有正则表达式模式,该模式定义了允许使用此模型输入到 API 中的信息类型:
{
"title" : "Register",
"required" : [ "email", "firstName", "lastName", "password", "username" ],
"type" : "object",
"properties" : {
"email" : {
"pattern" : "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$",
"type" : "string"
},
"password" : {
"type" : "string"
},
"username" : {
"type" : "string"
},
"firstName" : {
"type" : "string"
},
"lastName" : {
"type" : "string"
}
},
"description" : "Registration details"
}
当您validation
在 OpenAPI 规范中启用 API 资源时,它将使用此 JSON Schema 自动验证您的输入。它不仅支持必需属性,还支持正则表达式验证。有关更多信息,请参阅此AWS 文档。
/identity/register:
post:
tags:
- "Identity"
description: "Register new Business user"
operationId: "identityRegister"
requestBody:
description: "Registration details"
content:
application/json:
schema:
$ref: "#/components/schemas/Register"
required: true
x-amazon-apigateway-request-validator: full
请求验证器选择针对该特定端点使用哪种配置。
我们应该在文档根目录的其他位置配置变体,如下所示:
x-amazon-apigateway-request-validators:
full:
validateRequestBody: true
validateRequestParameters: true
body-only:
validateRequestBody: true
validateRequestParameters: false
当然,您需要在应用程序代码中进行更多数据验证,string
并接受任何数据。您可以在 API 网关验证和基于代码的验证之间进行权衡。API 网关验证的优势在于,您无需为任何代码执行支付任何费用。
当您针对具有此配置的 API 执行并提供不正确的输入时,响应如下:
{
"message": "Invalid request body"
}
AWS Lambda
默认情况下,所有环境变量都是静态加密的,如果您想使用自己的加密密钥(CMK),请参见此处。
如果您需要加密传输中的环境变量,可以使用AWS KMS管理的密钥。请参阅本文,了解如何创建密钥以及如何在 AWS Lambda 中管理加密和解密。
AWS WAF
Web 应用程序防火墙支持 OSI 第 7 层过滤,这意味着它可以在应用程序级别进行输入过滤。这与前面介绍的过滤类似,但这是自动化的,如果过滤器阻止了 API 请求,它根本无法到达您的 API。
如果您愿意,这个Github 项目可以将所有 OWASP Top 10 规则集成到 AWS WAF 中。您需要注意的是,其定价模式存在一些缺点。因此,需要在代码级保护和 AWS 服务保护之间做出权衡。
resource "aws_wafregional_sql_injection_match_set" "owasp_01_sql_injection_set" {
count = "${lower(var.target_scope) == "regional" ? "1" : "0"}"
name = "${lower(var.service_name)}-owasp-01-detect-sql-injection-${random_id.this.0.hex}"
sql_injection_match_tuple {
text_transformation = "URL_DECODE"
field_to_match {
type = "URI"
}
}
sql_injection_match_tuple {
text_transformation = "HTML_ENTITY_DECODE"
field_to_match {
type = "URI"
}
}
sql_injection_match_tuple {
text_transformation = "URL_DECODE"
field_to_match {
type = "QUERY_STRING"
}
}
sql_injection_match_tuple {
text_transformation = "HTML_ENTITY_DECODE"
field_to_match {
type = "QUERY_STRING"
}
}
sql_injection_match_tuple {
text_transformation = "URL_DECODE"
field_to_match {
type = "BODY"
}
}
sql_injection_match_tuple {
text_transformation = "HTML_ENTITY_DECODE"
field_to_match {
type = "BODY"
}
}
sql_injection_match_tuple {
text_transformation = "URL_DECODE"
field_to_match {
type = "HEADER"
data = "Authorization"
}
}
sql_injection_match_tuple {
text_transformation = "HTML_ENTITY_DECODE"
field_to_match {
type = "HEADER"
data = "Authorization"
}
}
}
resource "aws_wafregional_rule" "owasp_01_sql_injection_rule" {
depends_on = ["aws_wafregional_sql_injection_match_set.owasp_01_sql_injection_set"]
count = "${lower(var.target_scope) == "regional" ? "1" : "0"}"
name = "${lower(var.service_name)}-owasp-01-mitigate-sql-injection-${random_id.this.0.hex}"
metric_name = "${lower(var.service_name)}OWASP01MitigateSQLInjection${random_id.this.0.hex}"
predicate {
data_id = "${aws_wafregional_sql_injection_match_set.owasp_01_sql_injection_set.0.id}"
negated = "false"
type = "SqlInjectionMatch"
}
}
此特定示例包含一个 Web ACL 中的 8 条规则。激活此规则的总成本为:
资源类型 | 数字 | 成本 |
---|---|---|
Web ACL | 1 | 5.00 美元(按小时计算) |
规则 | 8 | 8.00 美元(按小时计算) |
要求 | 每百万 | 0.60 美元 |
全部的 | 每月 13.60 美元 |
根据对您的 API 的 100 万个请求,除了常规 API 网关请求成本之外,您还需要支付 13.60 美元来防范所有类型的 SQL 注入攻击。
与 AWS WAF 等基于 DevOps 规则的系统相比,便利性、成本、流量和信任开发级别安全性之间存在明确的权衡。
结论
对于大多数应用程序,我认为针对 SQL 注入的 AWS WAF 不值得通过 API 网关输入验证和应用程序级输入过滤来启用。
如果您有在大型应用程序中使用 AWS WAF 的实际经验,请在评论中告诉我。
(2)身份验证失败
风险
在这里,我们希望避免对您的身份验证过程进行字典攻击,和/或损坏或设计不良的身份验证机制。
解决方案
AWS API 网关和 OpenAPI
对于我们的 API,我们希望确保尽可能在我们的 API 上启用身份验证,为了在我们的 OpenAPI 上启用此功能,我们添加security
如下参数:
paths:
/user:
get:
operationId: getUser
description: get User details by ID
parameters:
- $ref: '#/components/parameters/userID'
security:
- example-CognitoUserPoolAuthorizer: []
该名称是对 Cognito 用户池授权器配置的引用:
components:
securitySchemes:
example-CognitoUserPoolAuthorizer:
type: "apiKey"
name: "Authorization"
in: "header"
x-amazon-apigateway-authtype: "cognito_user_pools"
x-amazon-apigateway-authorizer:
providerARNs:
- "${cognito_user_pool_arn}"
type: "cognito_user_pools"
一旦启用 API,他们需要在 Cognito 用户池中拥有一个注册用户,然后才能进行身份验证并收到JWT Token
他们有权执行 API 的证明。
AWS Cognito
在 Cognito 中,我们需要做几件事来确保防范以下潜在风险:
- 字典攻击/暴力攻击
- 密码长度和强度要求。
- 多因素身份验证
- 授权会话 ID 的轮换。
- 会话 ID 无效。
首先,我们要确保密码长度至少为 8 个字符,这是NIST的建议
在资源内aws_cognito_user_pool
,我们设置密码策略如下:
resource "aws_cognito_user_pool" "_" {
# ... other configuration ...
password_policy {
minimum_length = 8
require_uppercase = true
require_lowercase = true
require_numbers = true
require_symbols = true
}
# ... other configuration ...
}
然后启用多重身份验证:
resource "aws_cognito_user_pool" "_" {
# ... other configuration ...
mfa_configuration = "ON"
sms_authentication_message = "Your code is {####}"
sms_configuration {
external_id = "example"
sns_caller_arn = aws_iam_role.sns_caller.arn
}
software_token_mfa_configuration {
enabled = true
}
# ... other configuration ...
}
当mfa_configuration
设置为时,ON
每个人都必须启用 SMS 或软件 MFA。
如果您需要,Cognito 支持更高级的安全功能,但需要额外付费。例如,10 万用户(不带高级安全功能)的配置价格为 250 美元,而带高级安全功能则为 4525 美元!再次强调,这是否值得您投资。
提供的功能包括:
- 检查是否泄露了凭证,这将进行用户名/密码扫描以查看是否已在任何地方泄露。
- 自适应身份验证,确定每次身份验证的风险级别,如果确定为可疑,则可以阻止登录。
- 发布安全指标,这会将所有登录指标报告到您的 CloudWatch 日志。
这显然需要您将Cognito SDK集成到您的应用程序或 Web 应用程序中。
结论
正确实施 API 网关安全性和 Cognito 身份验证,并使用 2FA 的合理密码要求,已经可以缓解 OWASP 指出的大多数问题。
如果您对应用程序的安全要求更严格,那么 Cognito 提供的额外高级安全功能值得研究。
(3)敏感数据泄露
风险
这里明显的风险是没有对传输中或静止的数据进行加密、可以被逆向工程的弱加密以及中间人攻击。
解决方案
AWS 服务端的所有数据均使用 TLS/SSL 进行传输加密。我们现在主要关注如何保护静态数据。
AWS DynamoDB
对于 DynamoDB,我们要确保按如下方式加密信息。
resource "aws_dynamodb_table" "_" {
# ... other configuration ...
server_side_encryption {
enabled = true
}
# ... other configuration ...
}
有关 CMK 或更新表加密的更多信息,请参阅此官方文档。
有关 DynamoDB 安全性的更多最佳实践,请参阅此官方文档。
由于 DynamoDB 使用 IAM 角色访问,因此并非必须使用 VPC 来限制公共访问。如果您想遵循最佳实践,建议使用 VPC 解决方案,这样可以确保所有流量都在 AWS 网络内进行,从而增强安全性。
AWS RDS
创建基于 SQL 的数据存储时,我们可以使用以下内容来启用加密:
resource "aws_db_instance" "_" {
# ... other configuration ...
storage_encrypted = true
publicly_accessible = false
# ... other configuration ...
}
建议您不要允许公开访问数据库。为了增强安全性,应将 VPC 配置为仅允许私有子网访问数据库。
要连接到 RDS,您可以使用其公共 SSL 证书来确保数据传输是加密的。
有关 AWS RDS 的一般安全指南,请参阅本文。
AWS Lambda
在存储信用卡信息等敏感数据之前,建议使用合适的加密算法。这些算法存在工作延迟,使得暴力破解非常困难。例如, Argon2、scrypt、bcrypt或PBKDF2。
结论
根据您使用的数据库,您可以选择确保传输中和静态加密。下一步是使用 VPC 设置尽可能阻止公开访问。
(4)XML 外部实体(XXE)
风险
许多系统仍然以某种形式使用 XML,例如 SOAP API 服务和集成层消息传递系统。这种风险在于自动化 XML 处理中依赖的库大多已经过时。
解决方案
AWS Lambda
确保您的 XML 处理库是最新的,并检查Example Attack Scenarios
此处以了解攻击媒介。
使用这份备忘单来准确了解如何降低这些编程语言的风险:
结论
说实话,我根本不用 XML。我们只有一个项目需要导入来自美国政府机构的 XML,而这种格式甚至不符合 XML 标准。我们不得不自己构建一个解析器来处理它。
(5)访问控制失效
风险
访问控制失效意味着攻击者可以访问不属于用户会话的信息。例如,通过修改 URL 查询参数,如下所示:
http://example.com/app/accountInfo?acct=notmyacct
另一个潜在风险是自由的 CORS 设置,允许从不同的 Web 域执行 API。
解决方案
AWS API 网关和 OpenAPI
跨域资源共享 (CORS)
管理 API 的正确 CORS 设置是第一步。为此,我们需要修改options
每个启用了 CORS 的 API 路径上的操作:
options:
responses:
200:
$ref: '#/components/responses/cors'
400:
$ref: '#/components/responses/cors'
500:
$ref: '#/components/responses/cors'
x-amazon-apigateway-integration:
responses:
default:
statusCode: "200"
responseParameters:
method.response.header.Access-Control-Max-Age: "'7200'"
method.response.header.Access-Control-Allow-Methods: "'OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE'"
method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
method.response.header.Access-Control-Allow-Origin: "'*'"
passthroughBehavior: "when_no_match"
timeoutInMillis: 29000
requestTemplates:
application/json: "{ \"statusCode\": 200 }"
type: "mock"
至关重要的是,method.response.header.Access-Control-Allow-Origin
响应参数现在设置'*'
为接受所有源请求。对于开发而言,当您处理各种测试服务器和本地执行环境时,这可能没问题。对于生产环境,我们需要将其锁定为仅执行此 API 的域名。
API 限制
接下来我们要确保限制 API 的并行执行次数。
resource "aws_api_gateway_method_settings" "_" {
rest_api_id = aws_api_gateway_rest_api._.id
stage_name = aws_api_gateway_stage._.stage_name
method_path = "*/*"
settings {
throttling_burst_limit = var.api_throttling_burst_limit
throttling_rate_limit = var.api_throttling_rate_limit
metrics_enabled = var.api_metrics_enabled
logging_level = var.api_logging_level
data_trace_enabled = var.api_data_trace_enabled
}
}
要控制 API 阶段的限制,请设置throttling_burst_limit
和throttling_rate_limit
参数。它们控制以下内容:
throttling_burst_limit
:API 阶段每秒将维持的请求数,持续几秒钟后将出现 429 HTTP 响应错误。throttling_rate_limit
:API 阶段每秒的请求数,它将持续直到达到突发速率限制,之后它将出现 429 HTTP 响应错误。
为了防止滥用,我们需要确保这些限制具有合理的限制,以尽可能地限制 DoS 攻击。
AWS DynamoDB、Cognito 和 Lambda
细粒度的访问控制
我们可以在 DynamoDB 上实现细粒度的访问控制机制,只允许经过身份验证的用户访问其自己的记录。
本文详细介绍了如何做到这一点,并给出了以下示例:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:BatchGetItem",
"dynamodb:Query"
],
"Resource": [
"arn:aws:dynamodb:us-west-2:123456789012:dynamodb:table/GameScores"
],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": [
"${www.amazon.com:user_id}"
],
"dynamodb:Attributes": [
"UserId",
"GameTitle",
"Wins"
]
},
"StringEqualsIfExists": {
"dynamodb:Select": "SPECIFIC_ATTRIBUTES"
}
}
}
]
}
上述策略将提供对GameScores
表中属于的项目的只读访问权限www.amazon.com:user_id
,并且只能检索每行的这些列;UserId
、、GameTitle
和Wins
。
需要注意的是,此处www.amazon.com:user_id
指的是来自 Amazon 联合登录的身份,而不是常规的 Cognito 用户池。要使用用户池注册的身份,请使用cognito-identity.amazonaws.com:sub
。
为了能够在您的 AWS Lambda 代码中使用此策略,您必须使用以下函数检索临时凭证,有关更多详细信息,请参阅官方文档:
var params = {
RoleArn: 'STRING_VALUE', /* required */
RoleSessionName: 'STRING_VALUE', /* required */
WebIdentityToken: 'STRING_VALUE', /* required */
DurationSeconds: 'NUMBER_VALUE',
Policy: 'STRING_VALUE',
PolicyArns: [
{
arn: 'STRING_VALUE'
},
/* more items */
],
ProviderId: 'STRING_VALUE'
};
sts.assumeRoleWithWebIdentity(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
当此操作成功执行后,您将拥有临时凭证,允许您按照之前的策略从 DynamoDB 读取数据。
角色和角色访问
要解决 API 的角色和角色访问问题,您可以在 Cognito 中使用以下设置:
module "cognito" {
source = "../modules/cognito"
namespace = var.namespace
resource_tag_name = var.resource_tag_name
region = var.region
cognito_identity_pool_name = var.cognito_identity_pool_name
cognito_identity_pool_provider = var.cognito_identity_pool_provider
schema_map = [
{
name = "email"
attribute_data_type = "String"
mutable = false
required = true
},
{
name = "phone_number"
attribute_data_type = "String"
mutable = false
required = true
},
{
name = "businessID"
attribute_data_type = "String"
mutable = true
required = false
},
{
name = "role"
attribute_data_type = "String"
mutable = true
required = false
},
{
name = "roleAccess"
attribute_data_type = "String"
mutable = true
required = false
}
]
}
包含schema_map
注册时需要记录的所有附加参数(注册后手动或自动记录),并且可以在authenticated
AWS Lambda 会话期间检索它们。
AWS Lambda 会话中的对象event
包含当前已验证用户的所有信息。要检索这些信息,请访问该claims
对象:event.requestContext.authorizer.claims
该对象将包含在 AWS Cognito 中设置的自定义参数,如下所示:
{
'custom:role': 'USER',
'custom:roleAccess': '{
"business": "rwu",
"role": "r",
"user": "rwud",
}',
'custom:businessID': '1'
}
当用户通过 Cognito 进行身份验证时,AWS Lambda 便会知道该用户拥有哪个角色,以及该角色需要哪些访问权限。例如business
,每个属性都允许您访问该特定业务 API 上的GET
(r)、POST
(w)、PUT
(u)、DELETE
(d) 操作。您可以根据需要进行细粒度的设置。
对于诸如 之类的关键标识符,businessID
建议将它们作为 DynamoDB 分区键的一部分,以便在查询数据时它们是必需的,并且永远不会通过 API 查询参数或主体 JSON 对象提供。
结论
破坏的访问控制会给数据安全带来很多问题,并且还会通过 API 上松散的 CORS 和速率限制设置带来 (D)DoS 攻击机会。
(6)安全配置错误
风险
这是一组非常广泛的威胁,涵盖整个应用程序堆栈。从未打补丁的软件到默认帐户,不一而足。一个典型的例子是具有公共权限的 S3 存储桶,正如本文
所述 ,这种情况曾经非常普遍。
解决方案
AWS 代码构建
由于此堆栈完全在无服务器模式下运行,因此是亚马逊的托管服务,最容易受到潜在安全漏洞影响的区域是我们在 AWS Lambda 和 Lambda Layer 上使用的代码。
对于 Node,我们需要确保已升级到 AWS 支持的最新版本,即版本 12。在构建系统中,我们有很多机会测试依赖项和代码中的漏洞,例如:
- NPM 审计:要审计您的依赖项,请参阅本文了解详细信息,我们可以在 CodeBuild 中实现该
npm audit
步骤,并在发现漏洞后停止管道。 - OWASP 依赖项检查器: OWASP 有一个依赖项检查器,也可以集成到命令行中,请参阅此处。此特定的分析器支持多种语言,包括 NodeJS 和 NPM 包管理器,详情请参阅此处。
- NodeJsScan: NodeJsScan 是一款专为 NodeJS 设计的 Docker 通用安全扫描器,更多详情请访问Github。它可以扫描整个代码库,查找 XSS、远程代码注入、SQL 注入等漏洞。
- RetireJs:是一个著名的 Node 依赖项和 JavaScript 代码漏洞扫描器。详情请参阅其Github 页面。
AWS Lambda
对于 AWS Lambda,我们有一个很棒的中间件Middy,它可以帮助覆盖有关 HTTP REST API 的正确安全配置。以下是一些推荐的插件:
- HTTP-CORS有助于设置正确的 HTTP CORS 标头。
- HTTP-Error-handler返回正确的 HTTP 响应,它与http-error一起工作。
- HTTP-Security-headers将最佳实践安全标头应用于 HTTP 响应。
结论
由于 AWS 负责处理我们使用的每项服务的细节,因此我们仍然有责任避免可能的安全漏洞。当然,我们可能会错误地配置 S3 存储桶以进行公开访问,还有很多其他示例我可以介绍。但是,我主要关注的是源代码这个关键领域。
如果您有兴趣进行更广泛和更深入的了解,请在此处查看有关 CIS 的指南以获取更多解决方案。
(7)跨站脚本(XSS)
风险
当 Web 应用程序将用户提供的数据包含在未经适当过滤的网页中并发送到浏览器时,就会出现 XSS 漏洞。如果数据未经过正确验证或转义,攻击者就可以将脚本、内联框架或其他对象嵌入到渲染的页面中。
XSS 是一种众所周知的安全风险,OWASP可以识别出几种变体:
- 反射型 XSS:这通常与来自未经清理的用户数据的恶意 URL 交互/脚本有关。
- 存储型 XSS:存储未经清理的用户输入,供其他人查看,最坏的情况下,由具有管理员权限的人查看。
- DOM XSS:在操作 DOM 的 JavaScript 框架(例如 ReactJS 和 VueJS)中最为常见。例如,攻击者利用恶意登录屏幕替换 DOM 节点。
解决方案
AWS API 网关和 Lambda
这种风险与输入卫生有关,我们已经在前面的章节中讨论过这个问题,请参阅有关注入的章节,了解我对如何处理这个问题的建议。
AWS WAF
此外,如果您希望使用特定的 Web 应用程序防火墙规则来处理 XSS 风险,可以使用以下 Terraform 代码(取自此Github repo):
resource "aws_wafregional_xss_match_set" "owasp_03_xss_set" {
count = "${lower(var.target_scope) == "regional" ? "1" : "0"}"
name = "${lower(var.service_name)}-owasp-03-detect-xss-${random_id.this.0.hex}"
xss_match_tuple {
text_transformation = "URL_DECODE"
field_to_match {
type = "URI"
}
}
xss_match_tuple {
text_transformation = "HTML_ENTITY_DECODE"
field_to_match {
type = "URI"
}
}
xss_match_tuple {
text_transformation = "URL_DECODE"
field_to_match {
type = "QUERY_STRING"
}
}
xss_match_tuple {
text_transformation = "HTML_ENTITY_DECODE"
field_to_match {
type = "QUERY_STRING"
}
}
xss_match_tuple {
text_transformation = "URL_DECODE"
field_to_match {
type = "BODY"
}
}
xss_match_tuple {
text_transformation = "HTML_ENTITY_DECODE"
field_to_match {
type = "BODY"
}
}
xss_match_tuple {
text_transformation = "URL_DECODE"
field_to_match {
type = "HEADER"
data = "cookie"
}
}
xss_match_tuple {
text_transformation = "HTML_ENTITY_DECODE"
field_to_match {
type = "HEADER"
data = "cookie"
}
}
}
resource "aws_wafregional_rule" "owasp_03_xss_rule" {
depends_on = ["aws_wafregional_xss_match_set.owasp_03_xss_set"]
count = "${lower(var.target_scope) == "regional" ? "1" : "0"}"
name = "${lower(var.service_name)}-owasp-03-mitigate-xss-${random_id.this.0.hex}"
metric_name = "${lower(var.service_name)}OWASP03MitigateXSS${random_id.this.0.hex}"
predicate {
data_id = "${aws_wafregional_xss_match_set.owasp_03_xss_set.0.id}"
negated = "false"
type = "XssMatch"
}
}
再次强调,AWS 为您处理此问题的成本如下。这些 XSS 保护在一个 Web ACL 中包含 8 条规则。激活此规则的总成本为:
资源类型 | 数字 | 成本 |
---|---|---|
Web ACL | 1 | 5.00 美元(按小时计算) |
规则 | 8 | 8.00 美元(按小时计算) |
要求 | 每百万 | 0.60 美元 |
全部的 | 每月 13.60 美元 |
基于您的 API 请求数为 100 万次,除了常规 API 网关请求费用外,您还需要支付 13.60 美元来防御所有类型的 XSS 攻击。当然,您也可以在同一 Web ACL 中同时启用此功能和 SQL 注入规则,每月节省 5.00 美元,总费用为每月 22.20 美元。
结论
当你应用良好的输入安全措施时,应该足以保护你免受任何 XSS 风险的侵害。请根据 OWASP 的这份
备忘单 检查你当前的实现,以确保你已获得全面保护。
(8)不安全的反序列化
风险
反序列化过程中的缺陷可能导致远程代码执行。例如,Web 应用程序通过 AWS API 网关发送的 JSON 对象会被反序列化(将 JSON 转换为 JavaScript 对象),并针对此数据执行操作。
潜在风险的例子有:会话 cookie 篡改和会话状态操纵。
解决方案
AWS Lambda
这需要手动代码审查并使用“安全配置错误”一章中介绍的代码漏洞扫描程序。OWASP 推荐的解决方案是使用数字签名(例如哈希或身份验证签名)进行完整性检查,以验证状态和 Cookie。如果数据不包含此类签名,则会被忽略。
此外,记录任何反序列化错误对于检测任何可能的篡改行为非常有用。
结论
请查看此OWASP 备忘单,了解每种编程语言需要注意的详细信息。
(9)使用已知漏洞的组件
风险
任何用作依赖项的代码或组件都可能存在已知漏洞。由于大多数项目对开源依赖项的依赖程度如此之高,因此很难意识到安全风险。
解决方案
这里我们需要依赖构建阶段的依赖扫描和人工审核来尽可能地规避安全风险。请参考“安全配置错误”章节中的解决方案来缓解此安全风险。
结论
OWASP 十大风险中的多个风险具有相似之处,这意味着许多软件服务和产品都依赖于开源软件。这种依赖带来了安全漏洞,如果没有某种形式的自动化检测,这些漏洞很难被发现。开发人员和 DevOps 人员需要在代码投入生产之前的构建阶段更加重视威胁检测。
(10)日志记录和监控不足
风险
这种风险在于缺乏上下文日志记录(位置、内容和方式),从而降低了对威胁的感知和及时监控能力。后者关乎IT团队对安全事件的响应速度。
解决方案
AWS CloudWatch
CloudWatch 既可以提供日志记录,也可以提供带有警报的监控功能。正如我在本OpenAPI系列文章的上一篇文章中所演示的那样。您可以阅读该文章,了解日志记录和监控方面的建议,这些建议将提高可见性,并使调试和错误(威胁)检测更加容易。
AWS X-Ray
顾名思义,X-Ray 是一项服务,它通过可视化执行路径和轻松访问日志,为无服务器执行提供了更高的透明度。我在之前的一篇文章中介绍过它的使用和实现,请阅读下面的文章。
结论
有了这两个工具,大多数异常都可以相对快速地检测到,要么通过 SNS 监控来自 CloudWatch 的警报,要么通过使用 AWS X-Ray 进行错误/错误分析。
结束语
这里有很多内容需要讲解,我相信自己也同样遗漏了很多。研究这些内容实际上让我发现了一些自己尚未真正实践过的东西,这正是我撰写这些文章如此宝贵的原因。希望这篇文章对您有所帮助,也非常感谢您的时间和关注。
如果我有任何错误,或者您有任何建议或补充,请在评论区告诉我。我非常乐意阅读您关于这个难题的想法和专业知识。
在我的下一篇文章中,我想详细讨论 DynamoDB,以及为什么应该使用它。
感谢阅读!