<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Segmentation fault &#187; CTF</title>
	<atom:link href="https://www.segmentationfault.fr/categories/ctf/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.segmentationfault.fr</link>
	<description>Projets d’un consultant en sécurité informatique</description>
	<lastBuildDate>Fri, 15 Feb 2019 08:02:10 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<item>
		<title>Résumé partiel des DC18 CTF Quals</title>
		<link>https://www.segmentationfault.fr/securite-informatique/resume-dc18-ctf-quals/</link>
		<comments>https://www.segmentationfault.fr/securite-informatique/resume-dc18-ctf-quals/#comments</comments>
		<pubDate>Mon, 24 May 2010 19:29:25 +0000</pubDate>
		<dc:creator>Emilien Girault</dc:creator>
				<category><![CDATA[CTF]]></category>
		<category><![CDATA[Sécurité informatique]]></category>
		<category><![CDATA[challenge]]></category>
		<category><![CDATA[Cryptographie]]></category>
		<category><![CDATA[hacking]]></category>

		<guid isPermaLink="false">http://www.segmentationfault.fr/?p=796</guid>
		<description><![CDATA[Contrairement à ce que certains pensent peut-être en voyant ce blog à l&#8217;abandon depuis plusieurs mois, non, je ne suis pas mort ! J&#8217;ai simplement été assez pris ces derniers temps, et j&#8217;essaye au passage de finaliser ma première release de XeeK pour la NDH le 19 juin&#8230; Ce week-end, j&#8217;ai rapidement participé aux qualifications [...]]]></description>
			<content:encoded><![CDATA[<p>Contrairement à ce que certains pensent peut-être en voyant ce blog à l&rsquo;abandon depuis plusieurs mois, non, je ne suis pas mort ! J&rsquo;ai simplement été assez pris ces derniers temps, et j&rsquo;essaye au passage de finaliser ma première release de <a href="http://www.segmentationfault.fr/projets/conference-sur-xeek-a-la-ndh-2010/">XeeK</a> pour la <a href="http://www.nuitduhack.com">NDH</a> le 19 juin&#8230;</p>
<p>Ce week-end, j&rsquo;ai rapidement participé aux qualifications du CTF de la <a href="http://www.defcon.org/">DefCon</a> 18. Je n&rsquo;avais pas refait de challenge depuis <a href="http://www.segmentationfault.fr/securite-informatique/insomnihack2010-hzv-won/">Insomni&rsquo;hack 2010</a> donc je me suis senti obligé de me décrasser un peu le cerveau. Ma participation à ces qualifications est toutefois restée limitée ; n&rsquo;ayant pas pu m&rsquo;inscrire à temps j&rsquo;ai du rejoindre une team à l&rsquo;arrache (Big-Daddy).<span id="more-796"></span></p>
<h3>Vue d&rsquo;ensemble</h3>
<p>Le challenge consistait en 6 séries de 5 épreuves, chacune intitulée de la sorte :</p>
<ul>
<li>Poursuit trivial (épreuves générales)</li>
<li>Crypto Badness (cryptographie)</li>
<li>Packet Madness (réseau)</li>
<li>Binary L33tness (cracking, applicatif)</li>
<li>Pwtent Pwnables (exploitations de services)</li>
<li>Forensics (analyse de fichiers)</li>
</ul>
<p>N&rsquo;ayant pas énormément de temps à consacrer à ce challenge, je n&rsquo;ai pas vraiment touché à tout mais me suis focalisé sur la crypto et le réseau.</p>
<p>Dans l&rsquo;ensemble j&rsquo;ai trouvé ça plutôt sympa, même si j&rsquo;ai quand même deux remarques négatives à faire :</p>
<ul>
<li>L&rsquo;interface du panneau d&rsquo;équipe codée en Java était vraiment plus que foireuse. Je ne sais pas si c&rsquo;était du au fait qu&rsquo;on soit plusieurs à partager le même compte, mais il fallait bouriner comme un dingue sur le bouton de validation afin d&rsquo;avoir un espoir de valider les réponses (valides), voire même parfois se reconnecter.</li>
<li>Certaines épreuves étaient relativement <a href="http://www.dico-des-mots.com/definitions/capilotracter.html">capilotractées</a>, dans le sens ou elles n&rsquo;étaient pas réalistes du tout et qu&rsquo;il fallait être à peu près aussi dingue que leur concepteur pour la valider. Enfin je pense que ça doit être à peu près pareil sur tous les challenges du genre&#8230;</li>
</ul>
<p>Étant loin d&rsquo;avoir réussi à valider toutes les épreuves, je vous propose de dévoiler la solution de deux d&rsquo;entre elles que j&rsquo;ai trouvées assez sympathiques.</p>
<h3>Packet Madness 200</h3>
<p>Dans cette épreuve, on fournissait une <a href="http://www.segmentationfault.fr/wp-content/uploads/2010/05/Copie-de-pkt200_55216efa7a182fb0.pcap_.txt">capture de paquets</a> (à renommer en .pcap), le but étant comme toutes les autres épreuves de trouver une passphrase de validation.</p>
<p>Sous Wireshark, on constate qu&rsquo;il s&rsquo;agit d&rsquo;un trafic TCP entre un client et un serveur. En utilisant l&rsquo;option &laquo;&nbsp;Follow TCP Stream&nbsp;&raquo;, on constate qu&rsquo;il semble s&rsquo;agir de trafic binaire&#8230;</p>
<div id="attachment_799" class="wp-caption aligncenter" style="width: 496px"><a href="http://www.segmentationfault.fr/wp-content/uploads/2010/05/pkt200_1.png"><img class="size-full wp-image-799" title="pkt200_1" src="http://www.segmentationfault.fr/wp-content/uploads/2010/05/pkt200_1.png" alt="" width="486" height="246" /></a><p class="wp-caption-text">Capture Wireshark</p></div>
<p style="text-align: left;">Cependant, l&rsquo;indice laissé par l&rsquo;épreuve suggère que les deux machines communiquent avec une &laquo;&nbsp;langue&nbsp;&raquo; inhabituelle. S&rsquo;agirait-il d&rsquo;un encodage connu mais peu courant ? En regardant un peu les encodages supportés par Wireshark, on s&rsquo;aperçoit rapidement qu&rsquo;ils &lsquo;agit en fait de l&rsquo;<a href="http://fr.wikipedia.org/wiki/Extended_Binary_Coded_Decimal_Interchange_Code">EBCDIC</a>, encodage créé par IBM qui semble remonter à l&rsquo;époque quasi-préhistorique des cartes perforées&#8230; En utilisant cet encodage, on y voit tout de suite plus clair :</p>
<div id="attachment_800" class="wp-caption aligncenter" style="width: 647px"><a href="http://www.segmentationfault.fr/wp-content/uploads/2010/05/pkt200_2.png"><img class="size-full wp-image-800" title="pkt200_2" src="http://www.segmentationfault.fr/wp-content/uploads/2010/05/pkt200_2.png" alt="Trafic décodé" width="637" height="293" /></a><p class="wp-caption-text">Trafic décodé</p></div>
<p style="text-align: left;">Il s&rsquo;agit donc d&rsquo;une sorte de telnet encodé en EBCDIC. Visiblement, le serveur propose plusieurs options, comme la création d&rsquo;un compte, l&rsquo;authentification, un mode maintenance et un affichage de news. L&rsquo;IP du serveur visible dans le dump, 192.42.96.121, existe bel et bien et héberge bien ce service sur le port 8686. Il semble donc que la réponse à l&rsquo;épreuve doive être obtenue en s&rsquo;y connectant. Malheureusement les outils classiques comme telnet et netcat ne supportent pas l&rsquo;EBCDIC. Mais c&rsquo;est sans compter Python, qui le supporte nativement, et qui va ainsi nous permettre de se coder un petit client maison :</p>
<pre style="text-align: left;">#!/usr/bin/python

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.41.96.121", 8686))

while True:
 data = s.recv(3000)
 print data.decode('EBCDIC-CP-BE').encode('ascii')

 input = raw_input()
 input_to_send = input.decode('ascii').encode('EBCDIC-CP-BE')+"%"
 s.send(input_to_send)</pre>
<p style="text-align: left;">Ce client permet d&rsquo;envoyer des commandes au service tout en affichant ses réponses. Toutefois, j&rsquo;ai constaté qu&rsquo;il était toujours en retard d&rsquo;un message par rapport au serveur. N&rsquo;ayant pas le temps d&rsquo;être perfectionniste, je m&rsquo;en suis contenté et ai pu me créer un compte sur le serveur avec la commande &laquo;&nbsp;a&nbsp;&raquo;, puis me loguer avec ce même compte (&laquo;&nbsp;l&nbsp;&raquo;). Le mode administrateur &laquo;&nbsp;m&nbsp;&raquo; ne fonctionnant pas, il ne restait que l&rsquo;affichage des news (&laquo;&nbsp;n&nbsp;&raquo;), qui donnait cette sortie :</p>
<pre>5/21/2010 - Defcon qualifiers are underway.

5/18/2010 - It's Bob Randolph's birthday today, wish him well
 if you see him

5/16/2010 - It's IBM old timer's night at the bowling alley.
 The key thing to remember at these things is that:
 once upon a time IBM ruled the world

4/29/2001 - First post! w00t!</pre>
<p>La news du 16 mai 2010 m&rsquo;interpelle du fait de la présence du mot &laquo;&nbsp;key&nbsp;&raquo;&#8230; Nous testons donc la réponse &laquo;&nbsp;<em>once upon a time IBM ruled the world</em>&nbsp;&raquo; à l&rsquo;épreuve, et après un léger acharnement collectif sur le team board, nous parvenons à valider ! Finalement, ce n&rsquo;était pas compliqué&#8230;</p>
<h3>Crypto Badness 400</h3>
<p>Dans cette épreuve épinglée de l&rsquo;indice &laquo;&nbsp;crack me&nbsp;&raquo;, on fournit une <a href="http://www.segmentationfault.fr/wp-content/uploads/2010/05/c400_95bcb7c5807a366d.tgz_.txt">archive tgz</a> (encore une fois à renommer). Celle-ci contient un fichier blob.dat visiblement chiffré et une clé publique pubkey.pem. Il s&rsquo;agit donc visiblement de casser la <a href="http://fr.wikipedia.org/wiki/Cryptographie_asym%C3%A9trique">clé publique</a> afin de retrouver la clé privée et déchiffrer le fichier .dat. Voici la clé publique :</p>
<pre>-----BEGIN RSA PUBLIC KEY-----
MGgCYQDK2YRVfJfgOUMaImrXJ/DG1D7z1BhGnxs3UEmyKYQ+6fg7H5dzisJ09fYf
QB8h8ZE+S2S7MbVaONOYwN/tALE5LwiJcRxEs1nnl2xhf8xzTwbj6VwmR2CRtS9G
LnlBPbUCAwEAAQ==
-----END RSA PUBLIC KEY-----</pre>
<p>Il s&rsquo;agit d&rsquo;une clé <a href="http://en.wikipedia.org/wiki/RSA">RSA</a>. Pour analyser ce genre de clé, l&rsquo;outil tout indiqué est <a href="http://www.openssl.org/">OpenSSL</a>. Cependant, une mauvaise surprise nous attend&#8230;</p>
<pre>$ openssl rsa -pubin -in pubkey.pem -text
unable to load Public Key
20934:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:647:Expecting: PUBLIC KEY</pre>
<p>Impossible de lire la clé avec cet outil, donc. Un peu de recherche Google, et je trouve <a href="http://barelyenough.org/blog/2008/04/fun-with-public-keys/">quelqu&rsquo;un</a> qui a eu le même problème :</p>
<blockquote><p>The problem is this an RSA public key PEM or <a href="http://en.wikipedia.org/wiki/Distinguished_Encoding_Rules">DER</a> generated by Ruby’s <a href="http://ruby-doc.org/stdlib/libdoc/openssl/rdoc/index.html"><code>OpenSSL::PKey::RSA</code></a> are unreadable by <a href="http://www.openssl.org/">OpenSSL</a>, <a href="http://www.bouncycastle.org/">Bouncy Castle</a> and probably other  crypto tools.</p>
<p>The actual issue is that Ruby’s <code>OpenSSL::PKey::RSA#to_pem</code> and <code>#to_der</code> generate a <a href="http://tools.ietf.org/html/rfc3447#appendix-A.1.1">PKCS#1 public  key format</a> while the <code>openssl rsa</code> command only works <a href="http://en.wikipedia.org/wiki/PKCS">PKCS#8</a> formatted public keys.</p></blockquote>
<p>Ainsi, la clé semble avoir été générée avec le module OpenSSL de Ruby, et son format PKCS#1 empêche sa lecture avec OpenSSL. Qu&rsquo;à cela ne tienne, nous allons utiliser ce même module pour la lire ! On ouvre le shell Ruby (IRB) et on tape :</p>
<pre>$ irb
irb(main):001:0&gt; require 'openssl'
=&gt; true
irb(main):002:0&gt; a=OpenSSL::PKey::RSA.new(File.read("pubkey.pem"))
=&gt; -----BEGIN RSA PUBLIC KEY-----
MGgCYQDK2YRVfJfgOUMaImrXJ/DG1D7z1BhGnxs3UEmyKYQ+6fg7H5dzisJ09fYf
QB8h8ZE+S2S7MbVaONOYwN/tALE5LwiJcRxEs1nnl2xhf8xzTwbj6VwmR2CRtS9G
LnlBPbUCAwEAAQ==
-----END RSA PUBLIC KEY-----

irb(main):003:0&gt; a.params
=&gt; {"dmq1"=&gt;0, "dmp1"=&gt;0, "iqmp"=&gt;0, "n"=&gt;12301866845301177551304949
58384962720772853569595334792197322452151726400507263657518745202199
78646938995647494277406384592519255732630345373154826850791702612214
29134616704292143116022212404792747377940806653514195974598569021434
13, "d"=&gt;0, "p"=&gt;0, "e"=&gt;65537, "q"=&gt;0}</pre>
<p>On arrive ainsi à extraire le module (n) et l&rsquo;exposant public (e). Ce dernier étant quasiment toujours le même, seul le module importe ici. Pour savoir si nous avons une chance de le casser, regardons sa taille en bits :</p>
<pre>$ python
&gt;&gt;&gt; import math
&gt;&gt;&gt; n=12301866845301177551304949583849627207728535695953347921973224
52151726400507263657518745202199786469389956474942774063845925192557
32630345373154826850791702612214291346167042921431160222124047927473
7794080665351419597459856902143413
&gt;&gt;&gt; math.log(n, 2)
767.66426718447133</pre>
<p>Il semble codé sur 768 bits&#8230; Cela ne vous rappelle rien ? Le nombre <a href="http://en.wikipedia.org/wiki/RSA_numbers#RSA-768">RSA-768</a> a été cassé en décembre dernier. Et comme par hasard, c&rsquo;est bien le même qui est utilisé ici&#8230; Nous allons donc pouvoir utiliser sa factorisation pour générer la clé privée correspondante. Par chance, <a href="http://blog.stalkr.net/">StalkR</a> de la team <a href="http://nibbles.tuxfamily.org">Nibbles</a> a posté un <a href="http://nibbles.tuxfamily.org/?p=1040">article très similaire</a> issu du CTF <a href="http://www.codegate.org/Eng/">Codegate</a> il y a quelques mois. Il y indique la procédure à suivre pour générer le certificat, qui pour simplifier se résume à télécharger un <a href="http://stalkr.net/files/codegate/2010/7/e_os.h">en-tete d&rsquo;OpenSSL</a> ainsi qu&rsquo;un <a href="http://stalkr.net/files/codegate/2010/7/create_private.c">programme C</a> servant à générer la clé. On lance tout ça :</p>
<pre>$ gcc -lssl -o create_private create_private.c
$ ./create_private</pre>
<p>La clé privée est générée dans le fichier private.pem. Il ne reste alors plus qu&rsquo;à décrypter le fichier blob.dat en utilisant la commande :</p>
<pre>$ openssl rsautl -decrypt -inkey private.pem -in blob.dat -out output.txt</pre>
<p>Moment de vérité&#8230;</p>
<pre>$ cat output.txt
how long until 1024 falls by the wayside?</pre>
<p>Il s&rsquo;agit bien de la réponse à l&rsquo;épreuve (validée encore une fois grâce à un acharnement collectif).</p>
<p>Comme l&rsquo;épreuve précédente, ce n&rsquo;était techniquement pas compliqué, l&rsquo;obstacle majeur étant la non-reconnaissance de la clé par OpenSSL&#8230; En tout cas merci à StalkR pour son article qui a été d&rsquo;une grande aide.</p>
<h3>Conclusion</h3>
<p>Ces épreuves ont été l&rsquo;occasion pour moi de me remettre un peu dans le bain des CTFs. Le niveau était globalement assez élevé (plus dur que l&rsquo;année dernière à en croire certains), et nous n&rsquo;avons réussi à valider que quelques épreuves; les résultats sont disponibles <a href="http://www.ddtek.biz/qualsDC18scores.txt">ici</a>. Pour ceux que ça intéresse, vous trouverez le résultat de la dernière épreuve du Poursuit trivial <a href="http://scott.wolchok.org/t500.html">ici</a>.</p>
<p>Chapeau à Nibbles pour avoir terminé 10ème ; un grand bravo à eux. Et merci à tous ceux avec qui j&rsquo;ai challengé, en particulier à <a href="http://silkcut.wordpress.com/">Silkut</a>, MatToufoutu, et Dad. En espérant que nous parviendrons à créer une équipe HZV l&rsquo;année prochaine, du moins si nous avons plus de temps et de ressources&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>https://www.segmentationfault.fr/securite-informatique/resume-dc18-ctf-quals/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
