A long time ago, I made a stupid decision to use WordPress for this blog about offensive website security. Since then, I learned a lot. I will be releasing a plugin to defend against XML-RPC attacks and guide how to generate a static HTML site in upcoming weeks.
But today I would like to share an interesting vulnerability that I found in a popular WordPress plugin with 2+ million active installations. I was looking for an easy-to-use backup plugin and All-in-One WP Migration by ServMask seemed like a good choice.
This plugin exports your WordPress website including the database, media files, plugins and themes with no technical knowledge required. Move, transfer, copy, migrate, and backup a site with 1-click. Quick, easy, and reliable.All-in-One WP Migration plugin description
After installing the plugin and creating the first backup, the filename didn’t look too random. I was wondering if it could be guessed by an attacker and somehow downloaded without the authenticated access.
While checking the code, I found out that it’s just a domain-date-time-rand(100,999).wpress and the backup itself was publicly accessible via vavkamil.cz/wp-content/ai1wm-backups/vavkamil.cz-20200324-214633-123.wpress
This seemed bad, but it would still require a huge amount of requests and pure luck to brute-force it. In the “wp-content/ai1wm-backups” folder, there were three additional files preventing directory listing:
Back then, I didn’t know what a “web.config” is for, but I was able to download it. There was nothing useful, it’s basically .htaccess for Microsoft IIS server. Normally I would probably stop there, but I just finished reading Permanent Record by Edward Snowden and remembered about the metadata 🙂
By downloading the web.config file and checking the Last-Modified metadata header, we can determine the exact date a time when the plugin was installed. Let’s assume the user will install the All-in-One WP Migration plugin and create a backup within the first 10 minutes after the installation. The attacker can brute-force the backup file name with approximately 600k requests.
wfuzz -c -z range,33-59 -z range,100-999 -X HEAD –sc 200 https://vavkamil.cz/wp-content/ai1wm-backups/vavkamil.cz-20200324-2146FUZZ-FUZ2Z.wpress
The wfuzz parameters can be slightly modified to add a reasonable delay between the installation and first backup creation, or you can just try pure luck.
Now when the attacker can determine the backup file name and download it, he can use .wpress extractor to dump the database content from the archive, or just install the plugin to a fresh website and import the backup.
It’s worth mentioning that even if you uninstalled the plugin, the “ai1wm-backups” folder with all the backups was not deleted, and therefore you may still be vulnerable.
I scanned hackerone/bugcrowd scope for bug bounty hunting purposes and was able to find ~20 blogs with the plugin installed, but I wasn’t able to exploit any (mainly as I didn’t want to bother them with a huge amount of requests). On the other hand, I exploited a hand-full of websites during the responsible disclosure among my clients, and this blog was also vulnerable/exploitable.
I reported the issue to the author and it was quickly fixed in version 7.15 (Exclude web.config and .htaccess direct access from each other). That means that it’s no longer possible to download .htaccess file from IIS and web.config file from Apache. With the next updates, there were introduced some changes and the backup file name is more random.
- Jan 13, 2020: Reported the vulnerability
- Jan 13, 2020: Response from vendor
- Jan 15, 2020: Ticket marked as resolved
- Jan 20, 2020: Version 7.15 released, vulnerability fixed