Nextcloud, CVE's & Apparmor

Nextcloud and others recently reported on CVE-2019-11043 which looks like a particularly nasty RCE affecting only nginx+php-fpm with certain configurations.

Unfortunately, the configuration the Nextcloud documentation recommended was one of those vulnerable configurations.

There's a nice POC up at https://github.com/neex/phuip-fpizdam which gives an output along the lines of:

pricey@laptop:~/git$ ~/go/bin/phuip-fpizdam https://nextcloud-test/index.php
2019/10/26 21:11:57 Base status code is 302
2019/10/26 21:12:02 Status code 502 for qsl=1755, adding as a candidate
2019/10/26 21:12:06 The target is probably vulnerable. Possible QSLs: [1745 1750 1755]
2019/10/26 21:12:12 Status code 500 for &main.AttackParams{QueryStringLength:1745, PisosLength:53}
2019/10/26 21:12:12 Attack params found: --qsl 1745 --pisos 53 --skip-detect
2019/10/26 21:12:12 Trying to set "session.auto_start=0"...
2019/10/26 21:12:16 Detect() returned attack params: --qsl 1745 --pisos 53 --skip-detect <-- REMEMBER THIS
2019/10/26 21:12:16 Performing attack using php.ini settings...
2019/10/26 21:12:18 Success! Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs
2019/10/26 21:12:18 Trying to cleanup /tmp/a...
2019/10/26 21:12:18 Done!

Take a look at your server and find /tmp/a together with other damage if you fancy it.

It hopefully goes without saying that if you're running a vulnerable configuration and don't know better, you should wipe, rebuild & restore from backup.

How do you know if you do know better? Do you audit for issues like this? Are you using SELinux or apparmor? Neither are entirely straight forward to set up but this incident should be a wakeup call to those hosting their own clouds. Since SELinux is quite well documented (though infamously difficult to use) in the link above, here's a quick introduction to apparmor, useful if you're running on Ubuntu for example:

sudo aa-genprof /usr/sbin/php7.2-fpm    # Create a blank profile
sudo aa-complain /usr/sbin/php7.2-fpm   # Start logging breaches
# Use your site a bit...
sudo aa-logprof                         # Guided wizard to add new rules
sudo aa-enforce                         # Get strict

This might leave you with something like:

$ sudo cat /etc/apparmor.d/usr.sbin.php-fpm7.2 
# Last Modified: Sat Oct 26 19:00:11 2019
#include <tunables/global>

/usr/sbin/php-fpm7.2 {
  #include <abstractions/base>
  #include <abstractions/nameservice>
  #include <abstractions/php>

  capability kill,
  capability net_admin,
  capability dac_override,
  capability chown,
  capability setgid,
  capability setuid,

  /run/php/php7.2-fpm.pid wr,
  /run/php/php7.2-fpm.sock wr,
  /etc/php/7.2/fpm/php-fpm.conf r,
  /etc/php/7.2/fpm/pool.d/www.conf r,
  /var/log/php7.2-fpm.log w,

  /etc/ImageMagick-6/** r,
  /run/systemd/notify w,
  /{usr/,}lib{,32,64}/** mr,
  /etc/ssl/openssl.cnf r,

  /usr/sbin/php-fpm7.2 rm,
  /proc/loadavg r,

  /var/www/nextcloud/** rk,
  /media/nextcloud/data/** rw,

  /tmp/php* rw,
}

...after which...

pricey@laptop:~/git$ ~/go/bin/phuip-fpizdam https://nextcloud-test/index.php 
2019/10/26 22:10:49 Base status code is 302
2019/10/26 22:10:54 Status code 502 for qsl=1755, adding as a candidate
2019/10/26 22:10:57 The target is probably vulnerable. Possible QSLs: [1745 1750 1755]
2019/10/26 22:11:03 Status code 500 for &main.AttackParams{QueryStringLength:1745, PisosLength:53}
2019/10/26 22:11:03 Attack params found: --qsl 1745 --pisos 53 --skip-detect
2019/10/26 22:11:03 Trying to set "session.auto_start=0"...
2019/10/26 22:11:08 Detect() returned attack params: --qsl 1745 --pisos 53 --skip-detect <-- REMEMBER THIS
2019/10/26 22:11:08 Performing attack using php.ini settings...

...and in the server log...

Oct 26 21:11:08 nextcloud-test kernel: [ 3870.864135] audit: type=1400 audit(1572124268.340:9768): apparmor="DENIED" operation="mknod" profile="/usr/sbin/php-fpm7.2" name="/var/log/fpm-php.www.log" pid=5154 comm="php-fpm7.2" requested_mask="c" denied_mask="c" fsuid=33 ouid=33
Oct 26 21:11:08 nextcloud-test kernel: [ 3870.864455] audit: type=1400 audit(1572124268.340:9769): apparmor="DENIED" operation="mknod" profile="/usr/sbin/php-fpm7.2" name="/var/log/fpm-php.www.log" pid=5154 comm="php-fpm7.2" requested_mask="c" denied_mask="c" fsuid=33 ouid=33
Oct 26 21:11:08 nextcloud-test kernel: [ 3870.991091] audit: type=1400 audit(1572124268.468:9770): apparmor="DENIED" operation="mknod" profile="/usr/sbin/php-fpm7.2" name="/var/log/fpm-php.www.log" pid=5154 comm="php-fpm7.2" requested_mask="c" denied_mask="c" fsuid=33 ouid=33
Oct 26 21:11:08 nextcloud-test kernel: [ 3871.128717] audit: type=1400 audit(1572124268.604:9771): apparmor="DENIED" operation="mknod" profile="/usr/sbin/php-fpm7.2" name="/var/log/fpm-php.www.log" pid=5154 comm="php-fpm7.2" requested_mask="c" denied_mask="c" fsuid=33 ouid=33
Oct 26 21:11:08 nextcloud-test kernel: [ 3871.178654] audit: type=1400 audit(1572124268.656:9772): apparmor="DENIED" operation="mknod" profile="/usr/sbin/php-fpm7.2" name="/tmp/a" pid=5139 comm="php-fpm7.2" requested_mask="c" denied_mask="c" fsuid=33 ouid=33
Oct 26 21:11:08 nextcloud-test kernel: [ 3871.255682] audit: type=1400 audit(1572124268.732:9773): apparmor="DENIED" operation="mknod" profile="/usr/sbin/php-fpm7.2" name="/var/log/fpm-php.www.log" pid=5154 comm="php-fpm7.2" requested_mask="c" denied_mask="c" fsuid=33 ouid=33
Oct 26 21:11:08 nextcloud-test kernel: [ 3871.400260] audit: type=1400 audit(1572124268.876:9774): apparmor="DENIED" operation="mknod" profile="/usr/sbin/php-fpm7.2" name="/var/log/fpm-php.www.log" pid=5154 comm="php-fpm7.2" requested_mask="c" denied_mask="c" fsuid=33 ouid=33
Oct 26 21:11:08 nextcloud-test kernel: [ 3871.453021] audit: type=1400 audit(1572124268.928:9775): apparmor="DENIED" operation="mknod" profile="/usr/sbin/php-fpm7.2" name="/tmp/a" pid=5139 comm="php-fpm7.2" requested_mask="c" denied_mask="c" fsuid=33 ouid=33
Oct 26 21:11:08 nextcloud-test kernel: [ 3871.453366] audit: type=1400 audit(1572124268.928:9776): apparmor="DENIED" operation="mknod" profile="/usr/sbin/php-fpm7.2" name="/tmp/a" pid=5139 comm="php-fpm7.2" requested_mask="c" denied_mask="c" fsuid=33 ouid=33
Oct 26 21:11:08 nextcloud-test kernel: [ 3871.501848] audit: type=1400 audit(1572124268.976:9777): apparmor="DENIED" operation="mknod" profile="/usr/sbin/php-fpm7.2" name="/var/log/fpm-php.www.log" pid=5154 comm="php-fpm7.2" requested_mask="c" denied_mask="c" fsuid=33 ouid=33
...

Taking something like apparmor into use moves us closer towards a default-deny state, but is still far from that ultimate goal. Is it reasonable to be able to expect anyone to be able to manage a Nextcloud instance securely?

The apparmor profile shown above is far from perfect. It won't prevent you from being exploited. Anyone having adopted the detection methods ain the poc might be put off and not investigate further though, so perhaps that's worth it? If you did have something like SELinux/AppArmor in place, you might also be more confident that after putting the new nginx configuration changes, php upgrades in place & restarting nginx/php, that any attackers will have lost their foothold? Still wouldn't stop data exfiltration though...

Do we need to put a secure auth solution in place before PHP? That wouldn't stop insiders with accounts...

Security being layers, maybe you could do with putting another layer up?