Diff
13 years ago
.htaccess
14 years ago
Diff.php
13 years ago
IPTraf.php
13 years ago
diffResult.php
13 years ago
email_genericAlert.php
13 years ago
email_newIssues.php
14 years ago
email_unlockRequest.php
14 years ago
menu_activity.php
14 years ago
menu_blockedIPs.php
13 years ago
menu_options.php
13 years ago
menu_scan.php
13 years ago
sysinfo.php
13 years ago
viewFullActivityLog.php
13 years ago
wf503.php
13 years ago
wfAPI.php
13 years ago
wfAction.php
14 years ago
wfArray.php
13 years ago
wfBrowscap.php
14 years ago
wfBrowscapCache.php
14 years ago
wfConfig.php
13 years ago
wfCrawl.php
13 years ago
wfDB.php
13 years ago
wfDict.php
14 years ago
wfIssues.php
13 years ago
wfLockedOut.php
14 years ago
wfLog.php
13 years ago
wfModTracker.php
14 years ago
wfRate.php
14 years ago
wfScanEngine.php
13 years ago
wfSchema.php
13 years ago
wfUnlockMsg.php
14 years ago
wfUtils.php
13 years ago
wfViewResult.php
13 years ago
wordfenceClass.php
13 years ago
wordfenceConstants.php
13 years ago
wordfenceHash.php
13 years ago
wordfenceScanner.php
13 years ago
wordfenceURLHoover.php
13 years ago
wordfenceURLHoover.php
198 lines
| 1 | <?php |
| 2 | require_once('wfAPI.php'); |
| 3 | require_once('wfArray.php'); |
| 4 | class wordfenceURLHoover { |
| 5 | private $debug = false; |
| 6 | public $errorMsg = false; |
| 7 | private $hostsToAdd = false; |
| 8 | private $table = ''; |
| 9 | private $apiKey = false; |
| 10 | private $wordpressVersion = false; |
| 11 | private $dRegex = 'aero|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|ss|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw|xn--lgbbat1ad8j|xn--fiqs8s|xn--fiqz9s|xn--wgbh1c|xn--j6w193g|xn--h2brj9c|xn--mgbbh1a71e|xn--fpcrj9c3d|xn--gecrj9c|xn--s9brj9c|xn--xkc2dl3a5ee0h|xn--45brj9c|xn--mgba3a4f16a|xn--mgbayh7gpa|xn--mgbc0a9azcg|xn--ygbi2ammx|xn--wgbl6a|xn--p1ai|xn--mgberp4a5d4ar|xn--90a3ac|xn--yfro4i67o|xn--clchc0ea0b2g2a9gcd|xn--3e0b707e|xn--fzc2c9e2c|xn--xkc2al3hye2a|xn--mgbtf8fl|xn--kprw13d|xn--kpry57d|xn--o3cw4h|xn--pgbs0dh|xn--mgbaam7a8h|xn--54b7fta0cc|xn--90ae|xn--node|xn--4dbrk0ce|xn--80ao21a|xn--mgb9awbf|xn--mgbai9azgqp6j|xn--j1amh|xn--mgb2ddes|xn--kgbechtv|xn--hgbk6aj7f53bba|xn--0zwm56d|xn--g6w251d|xn--80akhbyknj4f|xn--11b5bs3a9aj6g|xn--jxalpdlp|xn--9t4b11yi5a|xn--deba0ad|xn--zckzah|xn--hlcj6aya9esc7a'; |
| 12 | private $api = false; |
| 13 | private $db = false; |
| 14 | public function __sleep(){ |
| 15 | $this->writeHosts(); |
| 16 | return array('debug', 'errorMsg', 'table', 'apiKey', 'wordpressVersion', 'dRegex'); |
| 17 | } |
| 18 | public function __wakeup(){ |
| 19 | $this->hostsToAdd = new wfArray(array('owner', 'host', 'path', 'hostKey')); |
| 20 | $this->api = new wfAPI($this->apiKey, $this->wordpressVersion); |
| 21 | $this->db = new wfDB(); |
| 22 | } |
| 23 | public function __construct($apiKey, $wordpressVersion){ |
| 24 | $this->hostsToAdd = new wfArray(array('owner', 'host', 'path', 'hostKey')); |
| 25 | $this->apiKey = $apiKey; |
| 26 | $this->wordpressVersion = $wordpressVersion; |
| 27 | $this->api = new wfAPI($apiKey, $wordpressVersion); |
| 28 | $this->db = new wfDB(); |
| 29 | global $wpdb; |
| 30 | $this->table = $wpdb->base_prefix . 'wfHoover'; |
| 31 | $this->db->query("truncate table $this->table"); |
| 32 | } |
| 33 | public function hoover($id, $data){ |
| 34 | if(strpos($data, '.') === false){ |
| 35 | return; |
| 36 | } |
| 37 | if(! preg_match('/[a-zA-Z0-9\-]+\.(?:' . $this->dRegex . ')/i', $data)){ |
| 38 | return; |
| 39 | } |
| 40 | try { |
| 41 | @preg_replace("/(?<=^|[^a-zA-Z0-9\-])((?:[a-zA-Z0-9\-]+\.)+)(" . $this->dRegex . ")((?:$|[^a-zA-Z0-9\-\.\'\"])[^\r\n\s\t\"\'\$\{\}<>]*)/ie", "\$this->" . "addHost(\$id, '$1$2', '$3')", $data); |
| 42 | } catch(Exception $e){ error_log("Regex error 1: $e"); } |
| 43 | preg_replace("/(?<=[^\d]|^)(\d{8,10}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})([^\d\'\"][^\r\n\s\t\"\'\$\{\}<>]*)/e", "\$this->" . "addIP(\$id, \"$1\",\"$2\")", $data); |
| 44 | $this->writeHosts(); |
| 45 | } |
| 46 | private function dbg($msg){ if($this->debug){ error_log("DEBUG: $msg\n"); } } |
| 47 | public function addHost($id, $host, $path){ |
| 48 | $path = preg_replace_callback('/([^A-Za-z0-9\-\.\_\~:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,;\=]+)/', 'wordfenceURLHoover::urlenc', $path); |
| 49 | $host = strtolower($host); |
| 50 | $this->intAddHost($id, $host, $path); |
| 51 | } |
| 52 | public function addIP($id, $ipdata, $path){ |
| 53 | $path = preg_replace_callback('/([^A-Za-z0-9\-\.\_\~:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,;\=]+)/', 'wordfenceURLHoover::urlenc', $path); |
| 54 | if(strstr($ipdata, '.') === false && $ipdata >= 16777216 && $ipdata <= 4026531840){ |
| 55 | $ipdata = long2ip($ipdata); |
| 56 | } |
| 57 | $parts = explode('.', $ipdata); |
| 58 | $isValid = true; |
| 59 | if($parts[0] >= 240 || $parts[0] == '10' || $parts[0] == '172' || $parts[0] == '192' || $parts[0] == '127'){ |
| 60 | $isValid = false; |
| 61 | } |
| 62 | if($isValid){ |
| 63 | foreach($parts as $part){ |
| 64 | if($part < 1 || $part > 255){ |
| 65 | $isValid = false; |
| 66 | } |
| 67 | } |
| 68 | } |
| 69 | if($isValid && $ipdata){ |
| 70 | $this->intAddHost($id, $ipdata, $path); |
| 71 | } |
| 72 | } |
| 73 | public static function urlenc($m){ |
| 74 | return urlencode($m[1]); |
| 75 | } |
| 76 | private function intAddHost($id, $host, $path){ |
| 77 | if(strpos($path, '/') !== 0){ |
| 78 | $path = '/'; |
| 79 | } |
| 80 | $this->hostsToAdd->push(array('owner' => $id, 'host' => $host, 'path' => $path, 'hostKey' => $this->makeHostKey($host))); |
| 81 | if($this->hostsToAdd->size() > 1000){ $this->writeHosts(); } |
| 82 | return true; |
| 83 | } |
| 84 | private function writeHosts(){ |
| 85 | if($this->hostsToAdd->size() < 1){ return; } |
| 86 | $sql = "insert into " . $this->table . " (owner, host, path, hostKey) values "; |
| 87 | while($elem = $this->hostsToAdd->shift()){ |
| 88 | $sql .= sprintf("('%s', '%s', '%s', '%s'),", |
| 89 | mysql_real_escape_string($elem['owner']), |
| 90 | mysql_real_escape_string($elem['host']), |
| 91 | mysql_real_escape_string($elem['path']), |
| 92 | mysql_real_escape_string($elem['hostKey']) |
| 93 | ); |
| 94 | } |
| 95 | $sql = rtrim($sql, ','); |
| 96 | $this->db->query($sql); |
| 97 | } |
| 98 | private function makeHostKey($host){ |
| 99 | $hostParts = explode('.', $host); |
| 100 | $hostKey = ''; |
| 101 | if(sizeof($hostParts) == 2){ |
| 102 | $hostKey = substr(hash('sha256', $hostParts[0] . '.' . $hostParts[1] . '/', true), 0, 4); |
| 103 | } else if(sizeof($hostParts) > 2){ |
| 104 | $hostKey = substr(hash('sha256', $hostParts[sizeof($hostParts) - 3] . '.' . $hostParts[sizeof($hostParts) - 2] . '.' . $hostParts[sizeof($hostParts) - 1] . '/', true), 0, 4); |
| 105 | } |
| 106 | return $hostKey; |
| 107 | } |
| 108 | public function getBaddies(){ |
| 109 | $allHostKeys = array(); |
| 110 | $stime = microtime(true); |
| 111 | $allHostKeys = array(); |
| 112 | $q1 = $this->db->query("select distinct hostKey as hostKey from $this->table"); |
| 113 | while($hRec = mysql_fetch_assoc($q1)){ |
| 114 | array_push($allHostKeys, $hRec['hostKey']); |
| 115 | } |
| 116 | //Now call API and check if any hostkeys are bad. |
| 117 | //This is a shortcut, because if no hostkeys are bad it saves us having to check URLs |
| 118 | if(sizeof($allHostKeys) > 0){ //If we don't have any hostkeys, then we won't have any URL's to check either. |
| 119 | //Hostkeys are 4 byte sha256 prefixes |
| 120 | //Returned value is 2 byte shorts which are array indexes for bad keys that were passed in the original list |
| 121 | $this->dbg("Checking " . sizeof($allHostKeys) . " hostkeys"); |
| 122 | $resp = $this->api->binCall('check_host_keys', implode('', $allHostKeys)); |
| 123 | $this->dbg("Done hostkey check"); |
| 124 | |
| 125 | $badHostKeys = array(); |
| 126 | if($resp['code'] == 200){ |
| 127 | if(strlen($resp['data']) > 0){ |
| 128 | $dataLen = strlen($resp['data']); |
| 129 | if($dataLen % 2 != 0){ |
| 130 | $this->errorMsg = "Invalid data length received from Wordfence server: " . $dataLen; |
| 131 | return false; |
| 132 | } |
| 133 | for($i = 0; $i < $dataLen; $i += 2){ |
| 134 | $idxArr = unpack('n', substr($resp['data'], $i, 2)); |
| 135 | $idx = $idxArr[1]; |
| 136 | if(isset($allHostKeys[$idx]) ){ |
| 137 | array_push($badHostKeys, $allHostKeys[$idx]); |
| 138 | } else { |
| 139 | $this->errorMsg = "Bad allHostKeys index: $idx"; |
| 140 | return false; |
| 141 | } |
| 142 | } |
| 143 | } |
| 144 | } else { |
| 145 | $this->errorMsg = "Wordfence server responded with an error. HTTP code " . $resp['code'] . " and data: " . $resp['data']; |
| 146 | return false; |
| 147 | } |
| 148 | if(sizeof($badHostKeys) > 0){ |
| 149 | $urlsToCheck = array(); |
| 150 | //need to figure out which id's have bad hostkeys |
| 151 | //need to feed in all URL's from those id's where the hostkey matches a URL |
| 152 | foreach($badHostKeys as $badHostKey){ |
| 153 | $q1 = $this->db->query("select owner, host, path from $this->table where hostKey='%s'", $badHostKey); |
| 154 | while($rec = mysql_fetch_assoc($q1)){ |
| 155 | $url = 'http://' . $rec['host'] . $rec['path']; |
| 156 | if(! isset($urlsToCheck[$rec['owner']])){ |
| 157 | $urlsToCheck[$rec['owner']] = array(); |
| 158 | } |
| 159 | if(! in_array($url, $urlsToCheck[$rec['owner']])){ |
| 160 | $urlsToCheck[$rec['owner']][] = $url; |
| 161 | } |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | if(sizeof($urlsToCheck) > 0){ |
| 166 | $this->dbg("Checking " . sizeof($urlsToCheck) . " URLs"); |
| 167 | $badURLs = $this->api->call('check_bad_urls', array(), array( 'toCheck' => json_encode($urlsToCheck)) ); |
| 168 | $this->dbg("Done URL check"); |
| 169 | if(is_array($badURLs) && sizeof($badURLs) > 0){ |
| 170 | $finalResults = array(); |
| 171 | foreach($badURLs as $file => $badSiteList){ |
| 172 | if(! isset($finalResults[$file])){ |
| 173 | $finalResults[$file] = array(); |
| 174 | } |
| 175 | foreach($badSiteList as $badSite){ |
| 176 | array_push($finalResults[$file], array( |
| 177 | 'URL' => $badSite[0], |
| 178 | 'badList' => $badSite[1] |
| 179 | )); |
| 180 | } |
| 181 | } |
| 182 | return $finalResults; |
| 183 | } else { |
| 184 | return array(); |
| 185 | } |
| 186 | } else { |
| 187 | return array(); |
| 188 | } |
| 189 | } else { |
| 190 | return array(); |
| 191 | } |
| 192 | } else { |
| 193 | return array(); |
| 194 | } |
| 195 | } |
| 196 | } |
| 197 | ?> |
| 198 |