forked from quentin/quentin.dufour.io
Merge branch 'master' of ssh://git.deuxfleurs.fr:110/quentin.dufour.tk
This commit is contained in:
commit
e661704003
12 changed files with 591 additions and 129 deletions
|
@ -1,2 +1,5 @@
|
|||
# My Blog
|
||||
|
||||
|
||||
bundle exec jekyll serve
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ highlighter: rouge
|
|||
|
||||
paginate: 20
|
||||
domain_name: 'http://quentin.dufour.io'
|
||||
#google_analytics: 'UA-37637739-1'
|
||||
disqus_shortname: 'blogdequentin'
|
||||
|
||||
# Details for the RSS feed generator
|
||||
url: 'http://quentin.dufour.io'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
|
@ -8,9 +8,9 @@
|
|||
|
||||
<title>{{ site.name }}{% if page.title %} - {{ page.title }}{% endif %}</title>
|
||||
<link rel="shortcut icon" href="/assets/images/favicon.ico">
|
||||
<link rel="stylesheet" href="/assets/css/style.css">
|
||||
<link rel="alternate" type="application/rss+xml" title="My Blog" href="/feed.xml">
|
||||
<link rel="stylesheet" href="/assets/css/highlight.css">
|
||||
<link rel="stylesheet" href="/assets/css/style.css">
|
||||
<link rel="stylesheet" href="/assets/css/native.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -23,10 +23,5 @@
|
|||
<section id="wrapper" class="{% if page.profile %}home{% endif %}">
|
||||
{{ content }}
|
||||
</section>
|
||||
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
<script src="/assets/js/main.js"></script>
|
||||
<script src="/assets/js/highlight.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
---
|
||||
layout: default
|
||||
disqus: true
|
||||
archive: true
|
||||
---
|
||||
|
||||
|
@ -27,14 +26,6 @@ archive: true
|
|||
</section>
|
||||
</footer>
|
||||
|
||||
<!-- Disqus comments -->
|
||||
{% if page.disqus %}
|
||||
<div class="archive readmore">
|
||||
<h3>Comments</h3>
|
||||
{% include disqus.html %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Archive post list -->
|
||||
{% if page.archive %}
|
||||
<ul id="post-list" class="archive readmore">
|
||||
|
|
|
@ -270,7 +270,7 @@ FILETYPE="PNG"
|
|||
|
||||
On suppose donc que le fichier à trouver est un fichier PNG. Cependant, il y a beaucoup trop de fichiers pour les vérifier un à un manuellement. J'ai fait le choix d'automatiser la recherche avec python :
|
||||
|
||||
```
|
||||
```python
|
||||
from os import listdir
|
||||
from os.path import isfile, join
|
||||
import magic
|
||||
|
|
73
_posts/2018-01-15-recharger-carte-korrigo-avec-fedora.md
Normal file
73
_posts/2018-01-15-recharger-carte-korrigo-avec-fedora.md
Normal file
|
@ -0,0 +1,73 @@
|
|||
---
|
||||
layout: post
|
||||
slug: recharger-carte-korrigo-sur-fedora
|
||||
status: published
|
||||
sitemap: true
|
||||
title: Recharger sa carte Korrigo sur Fedora
|
||||
description: C'est possible !
|
||||
disqus: false
|
||||
categories:
|
||||
tags:
|
||||
- fedora
|
||||
---
|
||||
|
||||
La STAR, la Société de Transport de l'Agglomération Rennaise, propose à la vente des lecteurs de carte pour pouvoir recharger votre carte depuis chez vous. Pour cela, elle a fait le choix d'utiliser une application Java Web Start, qui fonctionne sous Windows, Mac OS et... Linux ! Pour autant, la procédure n'est pas totalement directe.
|
||||
|
||||
## Installer les dépendances
|
||||
|
||||
```
|
||||
sudo dnf install pcsc-lite-ccid pcsc-tools icedtea-web
|
||||
```
|
||||
|
||||
Si vous rencontrez des problèmes à l'étape "Utilisez l'applet Java Web Start", vous pouvez essayer d'installer le Java d'Oracle. Rendez-vous sur la page [de téléchargement d'Oracle](https://java.com/en/download/linux_manual.jsp) et choisissez Linux x64 RPM (ou Linux RPM si vous avez une installation 32 bits).
|
||||
|
||||
Une fois téléchargé, executé la commande suivante dans le répertoire de téléchargement :
|
||||
|
||||
```
|
||||
sudo dnf install jre-8u151-linux-x64.rpm
|
||||
```
|
||||
|
||||
Puis remplacez par la suite toutes les occurences de javaws par :
|
||||
|
||||
```
|
||||
/usr/java/jre1.8.0_151/bin/javaws
|
||||
```
|
||||
|
||||
## Test du lecteur
|
||||
|
||||
Vous devez probablement être dans le groupe dialout pour utiliser votre lecteur USB :
|
||||
|
||||
```
|
||||
sudo usermod -a -G dialout votre_nom_d_utilisateur
|
||||
```
|
||||
|
||||
Vous allez également devoir démarrer le daemon pcscd :
|
||||
|
||||
```
|
||||
sudo systemctl start pcscd
|
||||
```
|
||||
|
||||
Vérifiez que votre carte est bien détectée en lançant :
|
||||
|
||||
```
|
||||
pcsc_scan -n
|
||||
```
|
||||
|
||||
## Utiliser l'applet Java Web Start
|
||||
|
||||
Avant toute chose, il faut savoir que Java cherche la lib sous le nom de libpcsclite.so et non pas libpcsclite.so.1. Nous allons donc exécuter la commande suivante :
|
||||
|
||||
```
|
||||
sudo ln -s /usr/lib64/libpcsclite.so.1 /usr/local/lib64/libpcsclite.so
|
||||
```
|
||||
|
||||
Ensuite, connectez-vous sur votre compte STAR, et cliquez sur "Lire ma carte".
|
||||
Puis sur le bouton commencer, le site va vous proposer de télécharger un fichier en .jnlp. Une fois téléchargé, exécutez le comme suit :
|
||||
|
||||
```
|
||||
javaws Application-KorriGo-STAR.jnlp
|
||||
```
|
||||
|
||||
Normalement le site va détecter votre lecteur puis votre carte.
|
||||
|
||||
Bon courage !
|
425
_posts/2018-04-22-bzhctf18.md
Normal file
425
_posts/2018-04-22-bzhctf18.md
Normal file
|
@ -0,0 +1,425 @@
|
|||
---
|
||||
layout: post
|
||||
slug: write-up-breizhctf-2018
|
||||
status: published
|
||||
sitemap: true
|
||||
title: Write-Up BreizhCTF 2018
|
||||
description: Garanti 100% sans Go
|
||||
categories:
|
||||
- securite
|
||||
tags:
|
||||
---
|
||||
|
||||
Le BreizhCTF est une compétition autour de la sécurité, qui a lieu à Rennes tous les ans, où des équipes de 5 personnes se retrouvent face à un code obscurci, des binaires à reverse, des injections diverses et variées... tout ça pour trouver des *flags* et marquer un maximum de points.
|
||||
|
||||
L'édition 2018 s'est tenue durant la nuit du 20 au 21 avril dans le hall de l'université de Rennes 1. Vous pouvez trouver la vidéo de l'évènement sur [Vimeo](https://vimeo.com/265870042). L'évènement s'est bien terminé pour notre équipe puisque nous avons fini 7<sup>e</sup> (équipe ~).
|
||||
|
||||
[![scoreboard bzhctf](/assets/images/posts/bzhctf18-scoreboard.jpg)](/assets/images/posts/bzhctf18-scoreboard.jpg)
|
||||
|
||||
C'est donc l'occasion pour ma part de faire un compte-rendu des challenges sur lesquels j'ai travaillés.
|
||||
|
||||
Mais avant de commencer, les autres write-ups de notre équipe sont disponibles ici :
|
||||
|
||||
* [Trace Me, BabyAPK, Cryptonik et Desprecitor](https://blog.tclaverie.eu/posts/breizh-ctf---write-ups/) par Tristan
|
||||
* [Diskcrypt, Use the luck force, Chinoiseries, Diffie-Failman - strike back](https://blog.lesterpig.com/post/breizhctf-2k18-write-up/) par Loïck
|
||||
|
||||
## Baby JS
|
||||
|
||||
Pour ce challenge, on récupérait un texte inconnu et un fichier javascript [baby.js](/assets/code/bzhctf18-baby.js) qui avait l'air bien obscurci.
|
||||
En écrivant ce write-up, je me rends compte qu'il n'a pas été obscurci à la main mais à l'aide de l'outil [JSFuck](http://www.jsfuck.com/) (merci [Tristan](https://tclaverie.eu/)).
|
||||
|
||||
Voilà à quoi ressemble du code après passage dans JSFuck :
|
||||
|
||||
```javascript
|
||||
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])...
|
||||
```
|
||||
|
||||
Le détail de l'implémentation se trouve sur [le README du projet github de JSFuck](https://github.com/aemkei/jsfuck).
|
||||
Pensant que ce JS a été obscurci spécialement pour l'évènement, je me suis mis en quête d'un moyen de le désobscurcir à la main.
|
||||
|
||||
Sans pour autant complètement comprendre pourquoi, il apparait que :
|
||||
|
||||
1. En enlevant la première déclaration de tableau (`[]`)
|
||||
2. En enlevant l'appel à la fonction tout à la fin de la ligne (`()`)
|
||||
3. En stockant ce qui reste dans une variable (`let a = `)
|
||||
|
||||
Ce qui ressemble à ça :
|
||||
|
||||
```javascript
|
||||
let a = [(![]+[])[+[]]+...
|
||||
console.log(a[0])
|
||||
```
|
||||
|
||||
On obtient alors la fonction suivante :
|
||||
|
||||
```javascript
|
||||
function breizHash(string, method) {
|
||||
if (!('ENCRYPT' == method || 'DECRYPT' == method)) {
|
||||
method = 'ENCRYPT';
|
||||
}
|
||||
|
||||
if ('ENCRYPT' == method) {
|
||||
var output = '';
|
||||
for (var x = 0, y = string.length, charCode, hexCode; x < y; ++x) {
|
||||
charCode = string.charCodeAt(x);
|
||||
if (128 > charCode) {
|
||||
charCode += 128;
|
||||
} else if (127 < charCode) {
|
||||
charCode -= 128;
|
||||
}
|
||||
charCode = 255 - charCode;
|
||||
hexCode = charCode.toString(16);
|
||||
if (2 > hexCode.length) {
|
||||
hexCode = '0' + hexCode;
|
||||
}
|
||||
output += hexCode;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Fonction qui manque définitivement d'une partie `DECRYPT`. On peut réécrire cette partie en refaisant les étapes dans le sens inverse :
|
||||
|
||||
```javascript
|
||||
if ('DECRYPT' == method) {
|
||||
var output = '';
|
||||
for (var i = 0; i < string.length; i+=2) {
|
||||
var hexCode = Buffer.from(string[i] + string[i+1], 'hex')[0];
|
||||
var charCode = 255 - hexCode
|
||||
if (128 > charCode) {
|
||||
charCode += 128;
|
||||
} else if (127 < charCode) {
|
||||
charCode -= 128;
|
||||
}
|
||||
output += String.fromCharCode(charCode)
|
||||
}
|
||||
return output
|
||||
}
|
||||
```
|
||||
|
||||
Il suffit alors d'appeler la fonction breizHash avec le message encodé pour obtenir le flag.
|
||||
|
||||
```javascript
|
||||
console.log(breizHash("3d25373c2b39044f1d390a4a1c4b484e4f11204e4a20114f48204a4c3c0a0d16480620084c131c4f124c200b4f20352c20084f0d131b02","DECRYPT"));
|
||||
```
|
||||
|
||||
Ce qui nous donne le flag suivant :
|
||||
|
||||
```
|
||||
BZHCTF{0bFu5c4710n_15_n07_53Curi7y_w3lc0m3_t0_JS_w0rld}
|
||||
```
|
||||
|
||||
## Breizh Coin Miner
|
||||
|
||||
Pour ce challenge, l'objectif est de trouver des valeurs de départ dont le hash sha512 commence par `1337`.
|
||||
C'est le principe du proof-of-work utilisé par Bitcoin. La seule façon connue à ce jour est d'essayer plein de valeurs de départ aléatoires, les hasher et regarder si le hash obtenu commence par `1337`.
|
||||
|
||||
Pour la complexité demandée, un simple programme en javascript suffit. Pour les valeurs aléatoires, je récupère 100 octets depuis `/dev/urandom` que j'encode en base64.
|
||||
C'est cette chaîne de caractères en base64 que je vais hasher.
|
||||
En effet, pour valider les résultats, il est nécessaire de communiquer avec le serveur en utilisant un protocole texte : si jamais la valeur générée contient un byte interprété comme un retour à la ligne, mon résultat sera tronqué.
|
||||
En utilisant des chaînes en base64, je suis sûr de ne pas avoir de retour à la ligne.
|
||||
|
||||
Le programme final :
|
||||
|
||||
```javascript
|
||||
const crypto = require('crypto');
|
||||
const RandBytes = new require('randbytes');
|
||||
const randomSource = RandBytes.urandom.getInstance();
|
||||
|
||||
function iterate() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
randomSource.getRandomBytes(100, function (buff) {
|
||||
let gen = buff.toString('base64');
|
||||
const hash = crypto.createHash('sha512');
|
||||
hash.update(gen);
|
||||
const res = hash.digest('hex')
|
||||
if (res.substring(0,4) == "1337") {
|
||||
console.log(gen);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function loop() {
|
||||
while(true) {
|
||||
await iterate();
|
||||
}
|
||||
}
|
||||
loop();
|
||||
```
|
||||
|
||||
Pour s'exécuter, il faut installer le paquet `randbytes`.
|
||||
|
||||
```
|
||||
npm install randbytes
|
||||
```
|
||||
|
||||
Ensuite, il suffit d'exécuter le script, de récupérer 42 valeurs et les envoyer au serveur.
|
||||
|
||||
```
|
||||
node index.js
|
||||
```
|
||||
|
||||
En échange, le serveur retourne le flag (que je n'ai pas noté).
|
||||
|
||||
## Breizh Kartenn
|
||||
|
||||
Le challenge consistait à renvoyer le nom de la ville correspondant au code postal fourni. Il était plutôt buggé car il avait un comportement indéfini quand plusieurs villes avaient le même code postal.
|
||||
En effet, il acceptait uniquement une seule des villes pour un code postal donné mais sans règle claire.
|
||||
|
||||
À cela s'ajoute qu'en fonction de la couleur du texte envoyé, il fallait répondre un texte différent.
|
||||
Si le texte de la question était vert, il fallait renvoyer `YA! Me gwel <nom de la ville> :)`, si il était rouge il fallait renvoyer `NANN! Me ne gwel ket <nom de la ville> :/`.
|
||||
|
||||
Pour ce qui est de la couleur du texte, il s'agit de codes spéciaux interprétés par les émulateurs de terminaux.
|
||||
Pour faire un essai :
|
||||
|
||||
```
|
||||
echo -e "\e[92m vert \e[91m rouge \e[0m"
|
||||
```
|
||||
|
||||
Ce sont donc ces caractères que l'on va chercher pour connaître la couleur du texte. Si vous voulez en savoir plus sur la couleur dans les terminaux, je vous recommande la lecture de [Bash tips: Colors and formatting (ANSI/VT100 Control sequences)](https://misc.flogisoft.com/bash/tip_colors_and_formatting).
|
||||
|
||||
Étant donné que l'on doit répondre à un service TCP avec un protocole texte, j'ai du utiliser la bibliothèque socket de python également.
|
||||
Cependant, faisant face à un protocole texte principalement fait pour être utilisé par un humain, il est difficile de savoir combien d'octets il faut lire avant d'avoir tout le message.
|
||||
Pour ma part, je me suis basé sur la présence du prompt ou de certains mots clés dans le buffer.
|
||||
|
||||
La correspondance ville-code postal a été récupérée depuis un site internet pointé par le challenge. J'ai converti le tout en CSV :
|
||||
|
||||
```csv
|
||||
Yffiniac,22120
|
||||
Vitré,35500
|
||||
Vezin-le-Coquet,35132
|
||||
Vern-sur-Seiche,35770
|
||||
Vannes,56000
|
||||
Trégunc,29910
|
||||
Trégueux,22950
|
||||
Thorigné-Fouillard,35235
|
||||
Theix-Noyalo,56450
|
||||
Séné,56860
|
||||
...
|
||||
```
|
||||
|
||||
Enfin le code python consistait à mettre en place toutes les solutions évoquées précédemment :
|
||||
|
||||
```python
|
||||
import csv, socket, re
|
||||
|
||||
def read_until(st, token):
|
||||
data = b''
|
||||
while token not in data and b'BZHCTF' not in data and b'bzhctf' not in data and b'KENAVO' not in data:
|
||||
data += st.recv(8096)
|
||||
|
||||
return data
|
||||
|
||||
mes_villes = {}
|
||||
with open('villes-code-postaux.csv', newline='') as csvfile:
|
||||
csv_reader = csv.reader(csvfile, delimiter=',', quotechar='|')
|
||||
for row in csv_reader:
|
||||
mes_villes[row[1]] = row[0]
|
||||
|
||||
st = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
st.connect(("148.60.87.243", 9400))
|
||||
|
||||
msg = read_until(st, b'<ENTER>')
|
||||
print(msg.decode('utf-8'))
|
||||
|
||||
st.send(b'\n')
|
||||
|
||||
while True:
|
||||
msg = read_until(st, b'>>')
|
||||
print(msg.decode('utf-8'))
|
||||
if b'bzhctf' in msg or b'BZHCTF' in msg or b'KENAVO' in msg:
|
||||
break
|
||||
|
||||
vert = b'\x1b[92m' in msg
|
||||
rouge = b'\x1b[91m' in msg
|
||||
|
||||
msg = msg.decode('utf-8')
|
||||
postcode = re.search(r"(\d+)\?", msg).group(1)
|
||||
|
||||
reponse = ""
|
||||
if vert:
|
||||
reponse = "YA! Me gwel "+mes_villes[postcode]+" :)\n"
|
||||
else:
|
||||
reponse = "NANN! Me ne gwel ket "+mes_villes[postcode]+" :/\n"
|
||||
|
||||
st.send(bytes(reponse, 'utf-8'))
|
||||
print(reponse)
|
||||
```
|
||||
|
||||
Au bout d'un certain nombre de bonnes réponses, on obtient le flag (que je n'ai pas noté).
|
||||
|
||||
## Breizh Path
|
||||
|
||||
Tout comme le challenge précédent, BreizhPath nécessite d'interagir avec un protocole texte relativement pratique pour un humain mais pas nécessairement facile à automatiser.
|
||||
Certaines parties du texte sont colorées, ajoutant à la difficulté.
|
||||
|
||||
Le but de ce challenge est de trouver le chemin le plus court entre deux points d'une carte représentée par un quadrillage possédant des murs.
|
||||
Il nous faut donc un algorithme de "path finding", on peut citer entre autre Breadth First Search, Dijkstra ou encore A\*. Pour plus d'informations sur ces algorithmes, je recommande [Introduction to A\*](https://www.redblobgames.com/pathfinding/a-star/introduction.html).
|
||||
|
||||
Pour gagner du temps, on peut récupérer l'implémentation python sur [la page dédiée](https://www.redblobgames.com/pathfinding/a-star/implementation.html#python).
|
||||
|
||||
Ensuite il nous reste à récupérer le labyrinthe depuis le socket, le stocker dans un format de donnée compatible avec notre implémentation, puis récupérer le résultat et le convertir au format attendu.
|
||||
|
||||
Voilà à quoi pouvait ressembler une carte :
|
||||
|
||||
```
|
||||
- - - - - - - - - -
|
||||
- - - - - - - - - -
|
||||
K B - - - - - - - -
|
||||
- B B B - B B B - -
|
||||
- B B - B B B B - -
|
||||
- B B B B S B B B -
|
||||
B B B B B B B - - -
|
||||
B B B B B B - - - -
|
||||
B B - - B - - - - -
|
||||
B B - - - - - - - -
|
||||
```
|
||||
|
||||
Il faut donc trouver le chemin le plus court de S à K. Dans ce cas, il fallait aller 4 fois à gauche puis 3 fois en haut puis 1 fois à gauche.
|
||||
On nous dit que :
|
||||
|
||||
* haut = `i`
|
||||
* bas = `k`
|
||||
* gauche = `j`
|
||||
* droite = `l`
|
||||
|
||||
La réponse attendue est donc `jjjjiiij`.
|
||||
|
||||
Pour l'implementation, j'ai utilisé Dijkstra, mais A* aurait été suffisant et aurait nécessité moins de ressources.
|
||||
On suppose que le fichier [implementation.py](https://www.redblobgames.com/pathfinding/a-star/implementation.py) contenant A\* et Dijkstra fourni par Red Blob Games se trouve dans le même dossier que notre solution.
|
||||
|
||||
```python
|
||||
from implementation import GridWithWeights, dijkstra_search, reconstruct_path
|
||||
import sys, socket
|
||||
|
||||
st = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
st.connect(("148.60.87.243", 9500))
|
||||
data = ""
|
||||
while "<ENTER>" not in data:
|
||||
data = st.recv(200000).decode("utf-8")
|
||||
print(data)
|
||||
|
||||
st.send(b'\n')
|
||||
|
||||
def convert_path_to_relative_moves(p):
|
||||
if len(p) < 2:
|
||||
return ''
|
||||
|
||||
dx = p[0][0] - p[1][0]
|
||||
dy = p[0][1] - p[1][1]
|
||||
if dx < 0: # right
|
||||
return 'l'+convert_path_to_relative_moves(p[1:])
|
||||
elif dx > 0: # left
|
||||
return 'j'+convert_path_to_relative_moves(p[1:])
|
||||
elif dy < 0: # bottom
|
||||
return 'k'+convert_path_to_relative_moves(p[1:])
|
||||
elif dy > 0: # up
|
||||
return 'i'+convert_path_to_relative_moves(p[1:])
|
||||
|
||||
while True:
|
||||
# get input
|
||||
data = b''
|
||||
while b'New path to find' not in data and b'Out of the Grid' not in data:
|
||||
data += st.recv(8096)
|
||||
data = data.decode("utf-8").strip()
|
||||
print(data)
|
||||
if "No next step" in data:
|
||||
st.close()
|
||||
sys.exit(1)
|
||||
|
||||
# parse input
|
||||
x, y, walls, weights, k, s = 0, 0, [], {}, None, None
|
||||
for line in data.split("\n"):
|
||||
if "STEP" in line or "New path":
|
||||
continue
|
||||
line = line.split()
|
||||
if len(line) < 1:
|
||||
continue
|
||||
x = 0
|
||||
while x < len(line):
|
||||
if '-' in line[x]:
|
||||
walls.append((x,y))
|
||||
else:
|
||||
if 'K' in line[x]:
|
||||
k = (x, y)
|
||||
elif 'S' in line[x]:
|
||||
s = (x, y)
|
||||
|
||||
weights[(x,y)] = 1
|
||||
x += 1
|
||||
y += 1
|
||||
|
||||
# create data structure
|
||||
diagram5 = GridWithWeights(x, y)
|
||||
diagram5.walls = walls
|
||||
diagram5.weights = weights
|
||||
|
||||
# compute path
|
||||
came_from, cost_so_far = dijkstra_search(diagram5, s, k)
|
||||
path = reconstruct_path(came_from, s, k)
|
||||
answer = convert_path_to_relative_moves(path)
|
||||
print(answer)
|
||||
|
||||
st.send(bytes(answer+"\n", "utf-8"))
|
||||
|
||||
s.close()
|
||||
```
|
||||
|
||||
Ce qui permet d'obtenir le flag :
|
||||
|
||||
```
|
||||
BZHCTF{1_w45_br0k3_bu7_n0_m0r3}
|
||||
```
|
||||
|
||||
## Cuvée d'exception
|
||||
|
||||
Une fois connecté à ce challenge en telnet, on était dans une jail python.
|
||||
On nous demandait de déclencher 35 exceptions Python différentes. Bien entendu, impossible de lever ses propres exceptions.
|
||||
J'ai commencé par essayer ce qui me passait par la tête :
|
||||
|
||||
```python
|
||||
throw
|
||||
throw "e"
|
||||
5/0
|
||||
5[5]
|
||||
[][3]
|
||||
{}['t']a
|
||||
e
|
||||
```
|
||||
|
||||
Mais impossible d'en trouver d'autres.
|
||||
|
||||
On a donc décidé de voir s'il n'était pas possible de sortir de la jail.
|
||||
Notre point de départ était l'article [BreizhCTF 2016 – Write-Up – PyJail 1, 2, 3](https://securite.intrinsec.com/2016/05/17/breizhctf-2016-write-up-pyjail-1-2-3/) d'Intrinsec.
|
||||
|
||||
Malheureusement pas de clé `_module` dans dans la classe `warnings.catch_warnings`.
|
||||
|
||||
|
||||
En cherchant, [Maximilien](http://mricher.fr/) a trouvé un article nommé [Python Sandbox Escape](http://blog.orleven.com/2016/10/27/python-sandbox-excape/) (en chinois !) qui nous a permis de trouver l'inspiration.
|
||||
Nous avons finalement trouvé une variable qui contenait le module `os` qui nous a permis d'exécuter des commandes et, finalement, de lire le flag.
|
||||
|
||||
La jail possède une liste noire de mots clés, dont `os`. Il existe plusieurs solutions pour contourner cette limitation quand il s'agit d'une chaine de caractère, comme une concaténation : `'o'+'s'` ou encore en utilisant les codes ASCII `'\x6F\x73'`.
|
||||
|
||||
Finalement, la ligne suivante nous a permis de lire le flag :
|
||||
|
||||
```python
|
||||
print ()\
|
||||
.__class__ \
|
||||
.__base__ \
|
||||
.__subclasses__()[59] \
|
||||
.__init__ \
|
||||
.func_globals['linecache'] \
|
||||
.__dict__['o'+'s'] \
|
||||
.__dict__['system']('cat *')
|
||||
```
|
||||
|
||||
Ce qui permet d'obtenir le flag :
|
||||
|
||||
```
|
||||
BZHCTF{y0u_kn0w_by_n0w_4_l177l3_b17_m0r3_4b0u7_d1ff3r3n7_py7h0n_exceptions_4nd_m4yb3_m0r3}
|
||||
```
|
||||
|
||||
Et voilà, c'est tout !
|
1
assets/code/bzhctf18-baby.js
Normal file
1
assets/code/bzhctf18-baby.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
IR_Black style (c) Vasily Mikhailitchenko <vaskas@programica.ru>
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
/*padding: 0.5em;*/
|
||||
background: #272b2d;
|
||||
color: #d0d0d0;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
.hljs-shebang,
|
||||
.hljs-comment {
|
||||
color: #777279;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-tag,
|
||||
.tex .hljs-command,
|
||||
.hljs-request,
|
||||
.hljs-status,
|
||||
.clojure .hljs-attribute {
|
||||
color: #ebde68;
|
||||
}
|
||||
|
||||
.hljs-sub .hljs-keyword,
|
||||
.method,
|
||||
.hljs-list .hljs-title,
|
||||
.nginx .hljs-title {
|
||||
color: #ffffb6;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-tag .hljs-value,
|
||||
.hljs-cdata,
|
||||
.hljs-filter .hljs-argument,
|
||||
.hljs-attr_selector,
|
||||
.apache .hljs-cbracket,
|
||||
.hljs-date,
|
||||
.coffeescript .hljs-attribute {
|
||||
color: #c1ef65;
|
||||
}
|
||||
|
||||
.hljs-subst {
|
||||
color: #daefa3;
|
||||
}
|
||||
|
||||
.hljs-regexp {
|
||||
color: #e9c062;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-sub .hljs-identifier,
|
||||
.hljs-pi,
|
||||
.hljs-decorator,
|
||||
.tex .hljs-special,
|
||||
.hljs-type,
|
||||
.hljs-constant,
|
||||
.smalltalk .hljs-class,
|
||||
.hljs-doctag,
|
||||
.nginx .hljs-built_in {
|
||||
color: #c1ef65;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.ruby .hljs-symbol .hljs-string,
|
||||
.hljs-number,
|
||||
.hljs-variable,
|
||||
.vbscript,
|
||||
.hljs-literal,
|
||||
.hljs-name {
|
||||
color: #77bcd7;
|
||||
}
|
||||
|
||||
.css .hljs-tag {
|
||||
color: #96cbfe;
|
||||
}
|
||||
|
||||
.css .hljs-rule .hljs-property,
|
||||
.css .hljs-id {
|
||||
color: #ffffb6;
|
||||
}
|
||||
|
||||
.css .hljs-class {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.hljs-hexcolor {
|
||||
color: #c6c5fe;
|
||||
}
|
||||
|
||||
.hljs-number {
|
||||
color:#77bcd7;
|
||||
}
|
||||
|
||||
.coffeescript .javascript,
|
||||
.javascript .xml,
|
||||
.tex .hljs-formula,
|
||||
.xml .javascript,
|
||||
.xml .vbscript,
|
||||
.xml .css,
|
||||
.xml .hljs-cdata {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
78
assets/css/native.css
Normal file
78
assets/css/native.css
Normal file
|
@ -0,0 +1,78 @@
|
|||
.highlight .hll { background-color: #404040 }
|
||||
.highlight { background: #202020; color: #d0d0d0 }
|
||||
.highlight .c { color: #999999; font-style: italic } /* Comment */
|
||||
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
||||
.highlight .esc { color: #d0d0d0 } /* Escape */
|
||||
.highlight .g { color: #d0d0d0 } /* Generic */
|
||||
.highlight .k { color: #6ab825; font-weight: bold } /* Keyword */
|
||||
.highlight .l { color: #d0d0d0 } /* Literal */
|
||||
.highlight .n { color: #d0d0d0 } /* Name */
|
||||
.highlight .o { color: #d0d0d0 } /* Operator */
|
||||
.highlight .x { color: #d0d0d0 } /* Other */
|
||||
.highlight .p { color: #d0d0d0 } /* Punctuation */
|
||||
.highlight .ch { color: #999999; font-style: italic } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #999999; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #cd2828; font-weight: bold } /* Comment.Preproc */
|
||||
.highlight .cpf { color: #999999; font-style: italic } /* Comment.PreprocFile */
|
||||
.highlight .c1 { color: #999999; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */
|
||||
.highlight .gd { color: #d22323 } /* Generic.Deleted */
|
||||
.highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #d22323 } /* Generic.Error */
|
||||
.highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */
|
||||
.highlight .gi { color: #589819 } /* Generic.Inserted */
|
||||
.highlight .go { color: #cccccc } /* Generic.Output */
|
||||
.highlight .gp { color: #aaaaaa } /* Generic.Prompt */
|
||||
.highlight .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */
|
||||
.highlight .gt { color: #d22323 } /* Generic.Traceback */
|
||||
.highlight .kc { color: #6ab825; font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { color: #6ab825; font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #6ab825; font-weight: bold } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #6ab825 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #6ab825; font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #6ab825; font-weight: bold } /* Keyword.Type */
|
||||
.highlight .ld { color: #d0d0d0 } /* Literal.Date */
|
||||
.highlight .m { color: #3677a9 } /* Literal.Number */
|
||||
.highlight .s { color: #ed9d13 } /* Literal.String */
|
||||
.highlight .na { color: #bbbbbb } /* Name.Attribute */
|
||||
.highlight .nb { color: #24909d } /* Name.Builtin */
|
||||
.highlight .nc { color: #447fcf; text-decoration: underline } /* Name.Class */
|
||||
.highlight .no { color: #40ffff } /* Name.Constant */
|
||||
.highlight .nd { color: #ffa500 } /* Name.Decorator */
|
||||
.highlight .ni { color: #d0d0d0 } /* Name.Entity */
|
||||
.highlight .ne { color: #bbbbbb } /* Name.Exception */
|
||||
.highlight .nf { color: #447fcf } /* Name.Function */
|
||||
.highlight .nl { color: #d0d0d0 } /* Name.Label */
|
||||
.highlight .nn { color: #447fcf; text-decoration: underline } /* Name.Namespace */
|
||||
.highlight .nx { color: #d0d0d0 } /* Name.Other */
|
||||
.highlight .py { color: #d0d0d0 } /* Name.Property */
|
||||
.highlight .nt { color: #6ab825; font-weight: bold } /* Name.Tag */
|
||||
.highlight .nv { color: #40ffff } /* Name.Variable */
|
||||
.highlight .ow { color: #6ab825; font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #666666 } /* Text.Whitespace */
|
||||
.highlight .mb { color: #3677a9 } /* Literal.Number.Bin */
|
||||
.highlight .mf { color: #3677a9 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #3677a9 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #3677a9 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #3677a9 } /* Literal.Number.Oct */
|
||||
.highlight .sa { color: #ed9d13 } /* Literal.String.Affix */
|
||||
.highlight .sb { color: #ed9d13 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #ed9d13 } /* Literal.String.Char */
|
||||
.highlight .dl { color: #ed9d13 } /* Literal.String.Delimiter */
|
||||
.highlight .sd { color: #ed9d13 } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #ed9d13 } /* Literal.String.Double */
|
||||
.highlight .se { color: #ed9d13 } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #ed9d13 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #ed9d13 } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #ffa500 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #ed9d13 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #ed9d13 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #ed9d13 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #24909d } /* Name.Builtin.Pseudo */
|
||||
.highlight .fm { color: #447fcf } /* Name.Function.Magic */
|
||||
.highlight .vc { color: #40ffff } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #40ffff } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #40ffff } /* Name.Variable.Instance */
|
||||
.highlight .vm { color: #40ffff } /* Name.Variable.Magic */
|
||||
.highlight .il { color: #3677a9 } /* Literal.Number.Integer.Long */
|
|
@ -43,7 +43,7 @@ html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abb
|
|||
.icon-facebook-rect:before { content: '\e803'; }
|
||||
|
||||
/* Spacing */
|
||||
.post h1, h3, h4, h5, p, .post-body ul, #post-list li, pre {
|
||||
.post h1, h3, h4, h5, p, #post-body ul, #post-body ol, #post-list li, pre {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,11 @@ h2 {
|
|||
color: #bbb;
|
||||
}
|
||||
|
||||
sup {
|
||||
vertical-align: super;
|
||||
font-size: 72%;
|
||||
}
|
||||
|
||||
.profile #wrapper {
|
||||
padding: 100px 40px 0px;
|
||||
max-width: 600px;
|
||||
|
@ -291,7 +296,7 @@ hr {
|
|||
background: #eee;
|
||||
}
|
||||
|
||||
span.code { font-family:Menlo, Monaco, Courier; background-color:#EEE; font-size:14px; }
|
||||
span.code, code { font-family:Menlo, Monaco, Courier; color: #ffffff; padding: 6px 0px 3px 0px; background-color:#272b2d; font-size:14px; }
|
||||
|
||||
pre {
|
||||
font-family:Menlo, Monaco, Courier;
|
||||
|
|
BIN
assets/images/posts/bzhctf18-scoreboard.jpg
Normal file
BIN
assets/images/posts/bzhctf18-scoreboard.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
Loading…
Reference in a new issue