SANS held their annual CTF event over the Christmas period, The CTF was in the shape of a game where you had an avatar and you navigate your way through the world. In this CTF you were recovering the five rings of christmas
- Tolkien Ring
- Elfen Ring
- Web Ring
- Cloud Ring
- Burning Ring of Fire
Each ring was around a specific topic where Cloud focused on AWS and web was focused on logs and Wireshark. I Managed to complete the cloud ring and completed almost all the other rings but ran out of time.
Recover the Cloud Ring
AWS CLI intro (Easy)
Brief: Try out some basic AWS command line skills in this terminal. Talk to Jill Underpole in the Cloud Ring for hints.
You may not know this, but AWS CLI help messages are very easy to access. First, try typing:
$ aws help
Typing aws help
solved the first question
Brief: Great! When you’re done, you can quit with q.
Next, please configure the default aws cli credentials with the access key AKQAAYRKO7A5Q5XUY2IY, the secret key qzTscgNdcdwIo/soPKPoJn9sBrl5eMQQL19iO5uf and the region us-east-1 .
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config
By using the aws configure
command and filling in the details we were provided allowed us to continue on
elf@f9a55f733065:~$ aws configure
AWS Access Key ID [None]: AKQAAYRKO7A5Q5XUY2IY
AWS Secret Access Key [None]: qzTscgNdcdwIo/soPKPoJn9sBrl5eMQQL19iO5uf
Default region name [None]: us-east-1
Default output format [None]:
elf@f9a55f733065:~$
Brief: Excellent! To finish, please get your caller identity using the AWS command line. For more details please reference:
$ aws sts help
or reference:
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sts/index.html
using aws sts get-caller-identity
we then query AWS for the STS Caller information
elf@f9a55f733065:~$ aws sts get-caller-identity
{
"UserId": "AKQAAYRKO7A5Q5XUY2IY",
"Account": "602143214321",
"Arn": "arn:aws:iam::602143214321:user/elf_helpdesk"
}
Trufflehog Search (medium)
Brief: Use Trufflehog to find secrets in a Git repo. Work with Jill Underpole in the Cloud Ring for hints. What’s the name of the file that has AWS credentials?
Use Trufflehog to find credentials in the Gitlab instance at https://haugfactory.com/asnowball/aws_scripts.git.
Configure these credentials for us-east-1 and then run:
$ aws sts get-caller-identity
Using Trufflehog which can be downloaded from https://github.com/trufflesecurity/trufflehog we uncover a file where the access key and secret access key is listed
elf@93da53c0e2ae:~$ trufflehog github --repo https://haugfactory.com/asnowball/aws_scripts.git
🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷
ERRO[0002] Could not get Github repository: https://haugfactory.com/asnowball/aws_scripts.git error="Get \"https://api.github.com/repos/asnowball/aws_scripts\": dial tcp 140.82.114.6:443: i/o timeout"
WARN[0002] Unauthenticated scans cannot determine if a repository is private.
Found unverified result 🐷🔑❓
Detector Type: AWS
Decoder Type: PLAIN
Raw result: AKIAAIDAYRANYAHGQOHD
Timestamp: 2022-09-07 07:53:12 -0700 -0700
Line: 6
Visibility: 1
Link: https://haugfactory.com/asnowball/aws_scripts/blob/106d33e1ffd53eea753c1365eafc6588398279b5/put_policy.py
Repository: https://haugfactory.com/asnowball/aws_scripts.git
Commit: 106d33e1ffd53eea753c1365eafc6588398279b5
Email: asnowball alabaster@northpolechristmastown.local
File: put_policy.py
Visiting https://haugfactory.com/asnowball/aws_scripts/blob/106d33e1ffd53eea753c1365eafc6588398279b5/put_policy.py we pull out the AWS access key and Secret Access key.
<code>iam = boto3.client('iam', region_name='us-east-1', aws_access_key_id="AKIAAIDAYRANYAHGQOHD", aws_secret_access_key="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" elf@93da53c0e2ae:~$ aws configure AWS Access Key ID [None]: AKIAAIDAYRANYAHGQOHD AWS Secret Access Key [None]: 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 Default region name [None]: us-east-1 Default output format [None]: elf@93da53c0e2ae:~$ aws sts get-caller-identity { "UserId": "AIDAJNIAAQYHIAAHDDRA", "Account": "602123424321", "Arn": "arn:aws:iam::602123424321:user/haug" } elf@93da53c0e2ae:~$ </code>
Brief: Managed (think: shared) policies can be attached to multiple users. Use the AWS CLI to find any policies attached to your user. The aws iam command to list attached user policies can be found here: https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/index.html Hint: it is NOT list-user-policies.
As we ran aws sts get-caller-identity
we can see the user is haug. now using aws iam list-attached-user-policies --user-name haug
we are presented with
elf@93da53c0e2ae:~$ aws iam list-attached-user-policies --user-name haug
{
"AttachedPolicies": [
{
"PolicyName": "TIER1_READONLY_POLICY",
"PolicyArn": "arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY"
}
],
"IsTruncated": false
}
Brief: Now, view or get the policy that is attached to your user.
The aws iam command to get a policy can be found here:
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/index.html
Now we can see the TIER1_READONLY_POLICY
that is assigned, we can then use aws iam get-policy --policy-arn arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY
and we are then giving our policy information
elf@93da53c0e2ae:~$ aws iam get-policy --policy-arn arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY
{
"Policy": {
"PolicyName": "TIER1_READONLY_POLICY",
"PolicyId": "ANPAYYOROBUERT7TGKUHA",
"Arn": "arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY",
"Path": "/",
"DefaultVersionId": "v1",
"AttachmentCount": 11,
"PermissionsBoundaryUsageCount": 0,
"IsAttachable": true,
"Description": "Policy for tier 1 accounts to have limited read only access to certain resources in IAM, S3, and LAMBDA.",
"CreateDate": "2022-06-21 22:02:30+00:00",
"UpdateDate": "2022-06-21 22:10:29+00:00",
"Tags": []
}
}
elf@93da53c0e2ae:~$
Brief:Attached policies can have multiple versions. View the default version of this policy.
The aws iam command to get a policy version can be found here:
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/index.html
We can see the default version of the policy is v1
. We can view the default policy version using aws iam get-policy-version --policy-arn arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY --version-id v1
elf@93da53c0e2ae:~$ aws iam get-policy-version --policy-arn arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY --version-id v1
{
"PolicyVersion": {
"Document": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow", "Action": [ "lambda:ListFunctions",
"lambda:GetFunctionUrlConfig" ],
"Resource": "<em>" }, { "Effect": "Allow", "Action": [ "iam:GetUserPolicy", "iam:ListUserPolicies", "iam:ListAttachedUserPolicies" ], "Resource": "arn:aws:iam::602123424321:user/${aws:username}" }, { "Effect": "Allow", "Action": [ "iam:GetPolicy", "iam:GetPolicyVersion" ], "Resource": "arn:aws:iam::602123424321:policy/TIER1_READONLY_POLICY" }, { "Effect": "Deny", "Principal": "</em>",
"Action": [
"s3:GetObject",
"lambda:Invoke<em>" ], "Resource": "</em>"
}
]
},
"VersionId": "v1",
"IsDefaultVersion": false,
"CreateDate": "2022-06-21 22:02:30+00:00"
}
Brief:Inline policies are policies that are unique to a particular identity or resource. Use the AWS CLI to list the inline policies associated with your user.
The aws iam command to list user policies can be found here:
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/index.html
Hint: it is NOT list-attached-user-policies.
As we have the user haug, we can see what policies are attached to his account by using the following command aws iam list-user-policies --user-name haug
elf@93da53c0e2ae:~$ aws iam list-user-policies --user-name haug
{
"PolicyNames": [
"S3Perms"
],
"IsTruncated": false
}
Brief: Now, use the AWS CLI to get the only inline policy for your user.
The aws iam command to get a user policy can be found here:
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/index.html
Now we have the policy name S3Perms we can search the policy name with the username. aws iam get-user-policy --user-name haug --policy-name S3Perms
elf@93da53c0e2ae:~$ aws iam get-user-policy --user-name haug --policy-name S3Perms
{
"UserPolicy": {
"UserName": "haug",
"PolicyName": "S3Perms",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListObjects"
],
"Resource": [
"arn:aws:s3:::smogmachines3",
"arn:aws:s3:::smogmachines3/*"
]
}
]
}
},
"IsTruncated": false<br>}
Brief: The inline user policy named S3Perms disclosed the name of an S3 bucket that you have permissions to list objects.
List those objects!
The aws s3api command to list objects in an s3 bucket can be found here:
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/index.html
Now we are given our bucket name smogmachines3, We can then use the s3api
to query the bucket with this command aws s3api list-objects --bucket smogmachines3
elf@93da53c0e2ae:~$aws s3api list-objects --bucket smogmachines3
{
"Key": "pollution.jpg",
"LastModified": "2022-09-23 20:40:45+00:00",
"ETag": "\"d40d1db228c9a9b544b4c552df712478\"",
"Size": 81775,
"StorageClass": "STANDARD",
"Owner": {
"DisplayName": "grinchum",
"ID": "15f613452977255d09767b50ac4859adbb2883cd699efbabf12838fce47c5e60"
}
},
{
"Key": "power-station-smoke.jpg",
"LastModified": "2022-09-23 20:40:48+00:00",
"ETag": "\"2d7a8c8b8f5786103769e98afacf57de\"",
"Size": 45264,
"StorageClass": "STANDARD",
"Owner": {
"DisplayName": "grinchum",
"ID": "15f613452977255d09767b50ac4859adbb2883cd699efbabf12838fce47c5e60"
}
},
{
"Key": "smog-power-station.jpg",
"LastModified": "2022-09-23 20:40:46+00:00",
"ETag": "\"0e69b8d53d97db0db9f7de8663e9ec09\"",
"Size": 32498,
"StorageClass": "STANDARD",
"Owner": {
"DisplayName": "grinchum",
"ID": "15f613452977255d09767b50ac4859adbb2883cd699efbabf12838fce47c5e60"
}
},
{
"Key": "smogmachine_lambda_handler_qyJZcqvKOthRMgVrAJqq.py",
"LastModified": "2022-09-26 16:31:33+00:00",
"ETag": "\"fd5d6ab630691dfe56a3fc2fcfb68763\"",
"Size": 5823,
"StorageClass": "STANDARD",
"Owner": {
"DisplayName": "grinchum",
"ID": "15f613452977255d09767b50ac4859adbb2883cd699efbabf12838fce47c5e60"
}
}
],
"Name": "smogmachines3",
"Prefix": "",
"MaxKeys": 1000,
"EncodingType": "url"
}
Brief: The attached user policy provided you several Lambda privileges. Use the AWS CLI to list Lambda functions.
The aws lambda command to list functions can be found here:
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/index.html
Looking at the aws documentation to list lambda functions we can use aws lambda list-functions
elf@8b9a4cd407cb:~$ aws lambda list-functions
{
"Functions": [
{
"FunctionName": "smogmachine_lambda",
"FunctionArn": "arn:aws:lambda:us east-1:602123424321:function:smogmachine_lambda",
"Runtime": "python3.9",
"Role": "arn:aws:iam::602123424321:role/smogmachine_lambda",
"Handler": "handler.lambda_handler",
"CodeSize": 2126,
"Description": "",
"Timeout": 600,
"MemorySize": 256,
"LastModified": "2022-09-07T19:28:23.634+0000",
"CodeSha256": "GFnsIZfgFNA1JZP3TgTI0tIavOpDLiYlg7oziWbtRsa=",
"Version": "$LATEST",
"VpcConfig": {
"SubnetIds": [
"subnet-8c80a9cb8b3fa5505"
],
"SecurityGroupIds": [
"sg-b51a01f5b4711c95c"
],
"VpcId": "vpc-85ea8596648f35e00"
},
"Environment": {
"Variables": {
"LAMBDASECRET": "975ceab170d61c75",
"LOCALMNTPOINT": "/mnt/smogmachine_files"
}
},
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "7e198c3c-d4ea-48dd-9370-e5238e9ce06e",
"FileSystemConfigs": [
{"Arn": "arn:aws:elasticfilesystem:us-east-1:602123424321:access-point/fsap-db3277b03c6e975d2",
"LocalMountPath": "/mnt/smogmachine_files"
}
],
"PackageType": "Zip",
"Architectures": [
"x86_64"
],
"EphemeralStorage": {
"Size": 512
}
}
]
}
Brief:The attached user policy provided you several Lambda privileges. Use the AWS CLI to list Lambda functions.
The aws lambda command to list functions can be found here:
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/index.html
We can see the lambda function “FunctionName”: “smogmachine_lambda”, using the following command allows us to query lambda aws lambda get-function-url-config --function-name smogmachine_lambda
elf@8b9a4cd407cb:~$ aws lambda get-function-url-config --function-name smogmachine_lambda
{
"FunctionUrl": "https://rxgnav37qmvqxtaksslw5vwwjm0suhwc.lambda-url.us-east-1.on.aws/",
"FunctionArn": "arn:aws:lambda:us-east-1:602123424321:function:smogmachine_lambda",
"AuthType": "AWS_IAM",
"Cors": {
"AllowCredentials": false,
"AllowHeaders": [],
"AllowMethods": [
"GET",
"POST"
],
"AllowOrigins": [
"*"
],
"ExposeHeaders": [],
"MaxAge": 0
},
"CreationTime": "2022-09-07T19:28:23.808713Z",
"LastModifiedTime": "2022-09-07T19:28:23.808713Z"
}
elf@8b9a4cd407cb:~$
Recover the Web Ring
Naughty IP (Easy)
Breif: Use the artifacts from Alabaster Snowball to analyze this attack on the Boria mines. Most of the traffic to this site is nice, but one IP address is being naughty! Which is it? Visit Sparkle Redberry in the Tolkien Ring for hints.
We get a zip file that contains 2 files victim.pcap and weberror.log. Reviewing the weberror.log we see a number of POST
requests within the same second of each other from the IP 18.222.86.32
18.222.86.32 - - [05/Oct/2022 16:46:41] "POST /login.html HTTP/1.1" 200 - 18.222.86.32 - - [05/Oct/2022 16:46:41] "POST /login.html HTTP/1.1" 200 - 18.222.86.32 - - [05/Oct/2022 16:46:41] "POST /login.html HTTP/1.1" 200 - 18.222.86.32 - - [05/Oct/2022 16:46:41] "POST /login.html HTTP/1.1" 200 - 18.222.86.32 - - [05/Oct/2022 16:46:41] "POST /login.html HTTP/1.1" 200 - 18.222.86.32 - - [05/Oct/2022 16:46:41] "POST /login.html HTTP/1.1" 200 - 18.222.86.32 - - [05/Oct/2022 16:46:41] "POST /login.html HTTP/1.1" 200 -
Credential Mining (easy)
Brief:The first attack is a brute force login. What’s the first username tried?
Reviewing the victim.pcap file as we have already identified the attacking IP being 18.222.86.32 and that the malicious user was sending POST requests we can use ip.src==18.222.86.32 && http.request.method==POST
to filter our packets and reviewing the HTML Form URL Encoded: application/x-www-form-urlencoded we see the username is “alice”
404 FTW (easy)
Brief: The next attack is forced browsing where the naughty one is guessing URLs. What’s the first successful URL path in this attack?
going back to the weberror.log we can filter all packages associated with 18.222.86.32 and we can review the data and we see /proc is the first URL to give a 200 response
18.222.86.32 - - [05/Oct/2022 16:47:47] "GET /password HTTP/1.1" 404 -
18.222.86.32 - - [05/Oct/2022 16:47:47] "GET /affiliate HTTP/1.1" 404 -
18.222.86.32 - - [05/Oct/2022 16:47:47] "GET /pictures HTTP/1.1" 404 -
18.222.86.32 - - [05/Oct/2022 16:47:47] "GET /56 HTTP/1.1" 404 -
18.222.86.32 - - [05/Oct/2022 16:47:47] "GET /policies HTTP/1.1" 404 -
18.222.86.32 - - [05/Oct/2022 16:48:17] "GET /proc HTTP/1.1" 200 -
18.222.86.32 - - [05/Oct/2022 16:48:27] "POST /proc HTTP/1.1" 200 -
18.222.86.32 - - [05/Oct/2022 16:48:32] "POST /proc HTTP/1.1" 200 -
IMDS, XXE, and Other Abbreviations (medium)
Brief: The last step in this attack was to use XXE to get secret keys from the IMDS service. What URL did the attacker force the server to fetch?
Reviewing the weberror.log as a whole we can see XML data being leaked in the logs
18.191.6.79 - - [05/Oct/2022 16:48:47] "GET /admin.html HTTP/1.1" 302 -<br>ic| xml: (b'
]'
b'>
&id;
')
parsed_xml: b'info security-credentials/'
tree:
Looking at each xml data block we can see a access key and secret access key leaked
18.191.6.79 - - [05/Oct/2022 16:48:57] "GET / HTTP/1.1" 200 -
ic| xml: (b'<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY id SYSTE'
b'M "http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security'
b'-credentials/ec2-instance"> ]>
<product><productId>&id;</productId></pro'
b'duct>
')
parsed_xml: (b'<product><productId>{
"Code" : "Success",
"LastUpdated" : "2022-10-0'
b'5T16:43:21Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "ASIAV4AVRXQVJ267'
b'LD2Q",
"SecretAccessKey" : "OpGR4v70ygZ3RFf4WTzjNL45pQayRwZgBUgd0LJT",'
b'
"Token" : "IQoJb3JpZ2luX2VjECEaCXVzLWVhc3QtMiJHMEUCIHDsZXiUuHIUrLNH5p'
b'AeMiv4aUMVIScjwbo1E9LctQ3rAiEA819eJ24mILbxM3eELK2xrgskHxsRmrza/jIj3y96/sgqsg'
b'QI2v//////////ARADGgw0MDM3NzIxMjgyOTgiDMAdG5EGamJ4Z2FwyiqGBPy+CL9AfXIGfLBBDC'
b'NkCyl5WOMN7owHr84k+hz4XZYBUp7/+KFZgEiKARroMuD6ofdNRvAj7dQ1/wFxeR6wezUPUkHqtc'
b'303oTBY7eTk5EQXClpKsmV1l25QAfD0DOL6FPxpjLPug0AbDFlIhjUeImvk3NBWiUHtXptrJH2ks'
b'SaQqU2DBPkkQ4IjMBMbLj0ZdJVWaiUy9sf5ecc2d/qVQU1c6SrYLg0HpyuH9brqm0zuv8/tR17Y/'
b'Jo2aNeNGX1wvyb5jP1FcQteypV6IqKIUUCADJ7chYeMypMlwV77phvrZco921O6MV+JlhSIomuzF'
b'RLdvzD+RP8DyLZeYZ65vKzr6h0yc+XIHOCT+P01pWQgfZBtvfCJKLKqwTMEbIr/i/xgGmHoCTzx6'
b'm38kd4EZvGXZMp3EEasdnqTtKLOR6JFAAlW8SoxOKRL1MshK3SUmYvWnMoLKCotPwyJeAMHEHuZi'
b'pNMiZ2gbN//PMbUBnPjNVFBP4SfHaTv7EHzHNpTl5toy8qlPyxE0yLbh5a//DF5wJQE6UKfXWlQh'
b'k9/NVM7QAAzEzWPiFTp8ajRIDjPoprVlX3yUaTUHOH8PwMtURCJLl0sOQaJtRGWEMrH52ls5e83p'
b'm0ta8257vu8HyTR7zgc/7a0ZsoxetlsB7VYIKyXnETO7SMniTO8R/yE1Wn9qAoWp/jMPvn9pkGOo'
b'8CLegclGA49hB/LRr/V1bXEyIIRg5Zn93xXvccMX5QyKGVSRghNOVGn/cCglDWc9zSRFRlZ4tHbl'
b'Vi1v8021J04REPR69FDuVvpUzEDJfDF1u4XwYGsp7uuuIngiiegP56H5nSYjmpBfyIURwgNvsz6p'
b'tpUvplGCxOvBJcKeyborHJDKG40QRXsLpOgB8NTKhgaFNxO7PjA/YrT7g1rYS7xNrKzVIK4tTwxW'
b'B5zN5JAQ3pVRp2JB8Q1ng3qsj3UPfZ3O3JjY4U+rrBKPEHIw9B+Pz6kffOu73aPKgo333w/hd9U4'
b'slj74JQXPhO9jCYpAF1bLdS/If20Ed6HvGcAONep0A/FrtZ62EWX4HmeYZ4A==",
"Expi'
b'ration" : "2022-10-05T23:00:40Z"
}</productId></product>')
tree: <Element product at 0x7f9baeffc180>
We see the URL visited was http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance
Recover the Elfen Ring
Clone with a Difference (easy)
Brief: We just need you to clone one repo: git clone git@haugfactory.com:asnowball/aws_scripts.git
This should be easy, right?
Thing is: it doesn’t seem to be working for me. This is a public repository though. I’m so confused!
Please clone the repo and cat the README.md file.
Then runtoanswer and tell us the last word of the README.md file!
Doing a google search on asnowball/aws_scripts.git we see that the public repository is found at https://haugfactory.com/orcadmin/aws_scripts
, Reviewing the readme file we see the last word is maintainers
Prison Escape (medium to hard)
Brief: Escape from a container. Get hints for this challenge from Bow Ninecandle in the Elfen Ring. What hex string appears in the host file /home/jailer/.ssh/jail.key.priv
?
When we start the terminal we are presented
############################################
Wed Jan 11 12:13:24 UTC 2023
On attempt [6] of trying to connect.
If no connection is made after [60] attempts
contact the holidayhack sys admins via discord.
#############################################
Greetings Noble Player,
You find yourself in a jail with a recently captured Dwarven Elf.
He desperately asks your help in escaping for he is on a quest to aid a friend in a search for treasure inside a crypto-mine.
If you can help him break free of his containment, he claims you would receive "MUCH GLORY!"
Please, do your best to un-contain yourself and find the keys to both of your freedom.
Looking at the /home we have 1 user being samways
in the / directory we see a file called .dockerenv
Now we know we are in a docker container we can start looking at ways to break out of docker, Reviewing https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation for methods to breakout. We have determined we do not have access to the docker tool. Now checking to see if we have sudo access we can see we can sudo all commands
now attempting Mounting Disk breakout. We check if we can use fdisk -l
which was successful
We now mount /dev/vda as /mnt
Now we can attempt to visit /mnt/home/ we can see a user called jailer
now in the challenge it tells us to read /home/jailer/.ssh/jail.key.priv
When we cat /mnt/home/jailer/.ssh/jail.key.priv
This is as far as I got in the SANS Christmas CTF. The CTF as always is alot of fun and was great to practice my CTF breakout. I was a little upset not to see any programming challenges like they had last year but overall it was a great experience,