AWS - S3 Unauthenticated Enum

HackTricksをサポートする

S3 パブリックバケット

バケットは、「パブリック」と見なされるのは、任意のユーザーがバケットの内容をリストできる場合であり、「プライベート」は、バケットの内容が特定のユーザーによってのみリストまたは書き込まれる場合です。

企業は、バケットの権限が誤って設定されている可能性があり、すべてまたはAWSの任意のアカウントで認証されたすべてのユーザーにアクセスを許可することがあります(つまり、誰にでも)。このような誤設定があっても、バケットには独自のアクセス制御リスト(ACL)があるため、いくつかのアクションを実行できない場合があります。

AWS-S3の誤設定について学ぶにはこちらを参照してください: http://flaws.cloud および http://flaws2.cloud/

AWSバケットの発見

ウェブページがAWSを使用してリソースを保存しているかどうかを見つけるためのさまざまな方法:

列挙 & OSINT:

  • wappalyzerブラウザプラグインを使用

  • burpを使用して(ウェブをスパイダーする)または手動でページをナビゲートすることで、すべてのリソースが履歴に保存されます。

  • リソースを確認するドメインの例:

http://s3.amazonaws.com/[bucket_name]/
http://[bucket_name].s3.amazonaws.com/
  • CNAMESを確認する。resources.domain.combucket.s3.amazonaws.comのCNAMEを持つ可能性があります。

  • https://buckets.grayhatwarfare.comを確認してください。すでに発見されたオープンバケットがあります。

  • バケット名バケットドメイン名同じである必要があります。

  • flaws.cloudIP 52.92.181.107にあり、そこに行くとhttps://aws.amazon.com/s3/にリダイレクトされます。また、dig -x 52.92.181.107s3-website-us-west-2.amazonaws.comを返します。

  • バケットであることを確認するには、https://flaws.cloud.s3.amazonaws.com/訪問することもできます。

ブルートフォース

企業に関連する名前をブルートフォースすることでバケットを見つけることができます:

# パーミュテーションを作成するためのワードリストを生成
curl -s https://raw.githubusercontent.com/cujanovic/goaltdns/master/words.txt > /tmp/words-s3.txt.temp
curl -s https://raw.githubusercontent.com/jordanpotti/AWSBucketDump/master/BucketNames.txt >>/tmp/words-s3.txt.temp
cat /tmp/words-s3.txt.temp | sort -u > /tmp/words-s3.txt

# テストするためのドメインとサブドメインに基づいてワードリストを生成
## これらのドメインとサブドメインをsubdomains.txtに書き込む
cat subdomains.txt > /tmp/words-hosts-s3.txt
cat subdomains.txt | tr "." "-" >> /tmp/words-hosts-s3.txt
cat subdomains.txt | tr "." "\n" | sort -u >> /tmp/words-hosts-s3.txt

# 攻撃するためのドメインとサブドメインのリストに基づいてパーミュテーションを作成
goaltdns -l /tmp/words-hosts-s3.txt -w /tmp/words-s3.txt -o /tmp/final-words-s3.txt.temp
## 前のツールはサブドメインのパーミュテーションを作成するために特化しているので、そのリストをフィルタリングします
### "."で終わる行を削除
cat /tmp/final-words-s3.txt.temp | grep -Ev "\.$" > /tmp/final-words-s3.txt.temp2
### TLDなしのリストを作成
cat /tmp/final-words-s3.txt.temp2 | sed -E 's/\.[a-zA-Z0-9]+$//' > /tmp/final-words-s3.txt.temp3
### ドットなしのリストを作成
cat /tmp/final-words-s3.txt.temp3 | tr -d "." > /tmp/final-words-s3.txt.temp4http://phantom.s3.amazonaws.com/
### ハイフンなしのリストを作成
cat /tmp/final-words-s3.txt.temp3 | tr "." "-" > /tmp/final-words-s3.txt.temp5

## 最終的なワードリストを生成
cat /tmp/final-words-s3.txt.temp2 /tmp/final-words-s3.txt.temp3 /tmp/final-words-s3.txt.temp4 /tmp/final-words-s3.txt.temp5 | grep -v -- "-\." | awk '{print tolower($0)}' | sort -u > /tmp/final-words-s3.txt

## s3scannerを呼び出す
s3scanner --threads 100 scan --buckets-file /tmp/final-words-s3.txt  | grep bucket_exists

S3バケットのLoot

S3のオープンバケットがある場合、BucketLootは自動的に興味深い情報を検索できます。

リージョンを見つける

AWSがサポートしているすべてのリージョンは、https://docs.aws.amazon.com/general/latest/gr/s3.htmlで確認できます。

DNSによる

digおよびnslookupを使用して、発見されたIPのDNSリクエストを行うことでバケットのリージョンを取得できます:

dig flaws.cloud
;; ANSWER SECTION:
flaws.cloud.    5    IN    A    52.218.192.11

nslookup 52.218.192.11
Non-authoritative answer:
11.192.218.52.in-addr.arpa name = s3-website-us-west-2.amazonaws.com.

ドメインが「website」という単語を含んでいることを確認してください。 静的ウェブサイトには次のURLでアクセスできます: flaws.cloud.s3-website-us-west-2.amazonaws.com または、バケットには次のURLでアクセスできます: flaws.cloud.s3-us-west-2.amazonaws.com

試してみる

バケットにアクセスしようとしたときに、指定したドメイン名が別のリージョンである場合(例えば、バケットが bucket.s3.amazonaws.com にあるが、bucket.s3-website-us-west-2.amazonaws.com にアクセスしようとした場合)、正しい場所に誘導されます:

バケットの列挙

バケットのオープン性をテストするために、ユーザーは単にURLをウェブブラウザに入力することができます。プライベートバケットは「アクセス拒否」と応答します。パブリックバケットは、保存された最初の1,000オブジェクトをリストします。

誰でもアクセス可能:

プライベート:

これをCLIで確認することもできます:

#Use --no-sign-request for check Everyones permissions
#Use --profile <PROFILE_NAME> to indicate the AWS profile(keys) that youwant to use: Check for "Any Authenticated AWS User" permissions
#--recursive if you want list recursivelyls
#Opcionally you can select the region if you now it
aws s3 ls s3://flaws.cloud/ [--no-sign-request] [--profile <PROFILE_NAME>] [ --recursive] [--region us-west-2]

バケットにドメイン名がない場合、列挙しようとするときは、バケット名のみを入力し、AWSs3の全体のドメインは入力しないでください。例: s3://<BUCKETNAME>

公開URLテンプレート

https://{user_provided}.s3.amazonaws.com

公開バケットからアカウントIDを取得する

新しい S3:ResourceAccount ポリシー条件キーを利用することで、AWSアカウントを特定することが可能です。この条件は、アカウントが存在するS3バケットに基づいてアクセスを制限します(他のアカウントベースのポリシーは、リクエスト元のプリンシパルが存在するアカウントに基づいて制限します)。 ポリシーにはワイルドカードを含めることができるため、1つの数字ずつアカウント番号を見つけることが可能です。

このツールはそのプロセスを自動化します:

# Installation
pipx install s3-account-search
pip install s3-account-search
# With a bucket
s3-account-search arn:aws:iam::123456789012:role/s3_read s3://my-bucket
# With an object
s3-account-search arn:aws:iam::123456789012:role/s3_read s3://my-bucket/path/to/object.ext

この技術は、API Gateway URLs、Lambda URLs、Data Exchange データセット、さらにはタグの値を取得するためにも機能します(タグキーがわかっている場合)。詳細については、元の研究と、この悪用を自動化するためのツールconditional-loveを参照してください。

バケットがAWSアカウントに属していることを確認する

このブログ記事で説明されているように、バケットをリストする権限がある場合、次のようなリクエストを送信することで、バケットが属するaccountIDを確認することが可能です:

curl -X GET "[bucketname].amazonaws.com/" \
-H "x-amz-expected-bucket-owner: [correct-account-id]"

<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">...</ListBucketResult>

もしエラーが「アクセス拒否」であれば、それはアカウントIDが間違っていることを意味します。

ルートアカウント列挙としての使用されたメール

このブログ記事で説明されているように、ACLを介してS3バケットに対してメールに権限を付与しようとすることで、メールアドレスがAWSアカウントに関連しているかどうかを確認することが可能です。これがエラーを引き起こさない場合、そのメールはあるAWSアカウントのルートユーザーであることを意味します。

s3_client.put_bucket_acl(
Bucket=bucket_name,
AccessControlPolicy={
'Grants': [
{
'Grantee': {
'EmailAddress': 'some@emailtotest.com',
'Type': 'AmazonCustomerByEmail',
},
'Permission': 'READ'
},
],
'Owner': {
'DisplayName': 'Whatever',
'ID': 'c3d78ab5093a9ab8a5184de715d409c2ab5a0e2da66f08c2f6cc5c0bdeadbeef'
}
}
)

参考文献

HackTricksをサポートする

Last updated