By Scott Court
Today I am writing about how I accidentally discovered CVE-2017-17087. This is a security vulnerability in Vim that allows for a couple interesting exploits.
It all began again November 2, 2017. I set out that morning to analyze the vulnerability CVE-2017-1000382 on Cucumber Linux. This was a new vulnerability that had just come through in Vim. It was slightly different but very closely related to the vulnerability I ultimately discovered. I wasn’t looking to discover a CVE and at that time I had no idea I was going to discover my first CVE that day. CVE-2017-100382 was discovered by Hanno Bock of The Fuzzing Project. If you are not familiar with him, he does a lot of really great work and a lot of really cutting-edge Linux vulnerability research. This vulnerability allowed a remote attacker to obtain the database credentials for a WordPress database from a WordPress site.
This vulnerability works by exploiting the way Vim handles swap files. Anyone who’s ever used Vim knows it creates a swap file whenever you edit a file. This file contains recovery information in case your vim session crashes: you can recover what you were editing next time you go to edit that file. What is not as well known is that the swap file also contains the entire contents of the file you’re editing. The swap file sticks around until Vim exits properly, at which point the swap file is deleted.
So how does this relate to WordPress? All of the database credentials in WordPress are stored in the lovely wp-config.php file. This is in the public HTML directory, which is what gets served up to the internet when people connect to the site. Since it’s a *.php script and anything you put inside of a PHP tag in a PHP script it gets parsed by the preprocessor, it doesn’t ultimately get sent to the client, so it’s secure right?
Turns out it’s not. Say the system administrator goes to edit that file in Vim. Vim is going to create our swap file right in that directory, but that swap file is not a *.php file, and since PHP parses only files that end in *.php, this file is not going to get parsed. Now if you go to your website /.wp-config.php.swp, you can get the contents that file and get the site’s database credentials.
This requires someone to be actively editing the wp-config.php file which happens from time to time. The big concern is that if the system administrator’s Vim session crashes while he’s editing the file, the swap file is going to stick around for a really long time: until a system administrator goes to edit that file again and specifically deletes the file or until he realizes there’s an extra swap file lying around and deletes it manually.
At this point you’re probably thinking that this is all very theoretical, but no one would actually be dumb enough to do this in the real world. Well that is not true. When Hanno Bock discovered this vulnerability, he went and he scanned a bunch of the top WordPress sites and he found 25 of them were vulnerable to this. He quickly contacted the webmasters and they were very quick to remove the swap files. He then reported the vulnerability.
This vulnerability was given the following description in the Mitre CVE dictionary: Vim version 8.0.1187 (and other versions most likely) ignores umask when creating a swap file (“[ORIGINAL_FILENAME].swp”) resulting in files that may be world readable or otherwise accessible in ways not intended by the user running the vi binary. It occurred to me that that description has nothing to do with the issue we just encountered with WordPress, because the original file was readable by the webserver so even if a swap file had the same exact permissions, it would be readable by the web server.
Regardless of whether or not that was the case, that didn’t have anything to do with that vulnerability. I later found out that was not the case; it had nothing to do with the umask. It seemed like the umask should be ignored: it would make more sense to copy the permissions of the original file which supposedly was the behavior of Vim.
I was investigating this vulnerability further, so I decided to run an ls -la on my public HTML directory to see what was going on for myself, and this is what I found.
This should terrify all of you because the original wp-config.php file was owned by the apache group; however, the .wp-config.php.swp file if owned by the users group. The webmaster is a member of the apache group so he can edit the file just fine (since it’s a chmod to 660); however, the primary group for webmaster is not apache: it is users. So turns out that when Vim creates your swap file, it does copy the permissions from the original file more or less; however, it does not chgrp the file to the group ownership of the original file. It does try to do this, but on Linux you cannot chgrp a file unless your root, so unless you are editing the file as root (and even if you are root there are still a couple other conditions that have to be met) the chgrp is going to fail and then you’re going to end up with a swap file that’s readable by the users default group. So now in addition to exposing all of our WordPress credentials remotely, we’re also exposing them locally.
At first I wasn’t sure if this was really a distinct vulnerability from Hanno Bock’s vulnerability since it was very similar in the way it worked; it was not clear if this was really something different or if it was just an extension of his vulnerability. After discussing the matter with a friend for while, ultimately we both agreed that they were distinct vulnerabilities since it was possible to fix one vulnerability without fixing the other. I promptly reported it, and shortly thereafter it was assigned CVE-2017-17087.
Fortunately, I came up with a fix for both of these vulnerabilities very quickly: each user got a dedicated directory to store his swap files under ~/.vim/swap. This directory was chmod to 700 so only that user could access the contents of the directory and then Vim was reconfigured to store the swap files in that directory on a per user basis.