PluginProbe
The WP Remote WordPress Plugin / 6.65
The WP Remote WordPress Plugin v6.65
6.72 6.69 6.65 6.62 6.48 6.47 4.87 4.97 5.05 5.09 5.16 5.22 5.24 5.25 5.38 5.41 5.42 5.45 5.47 5.53 5.56 5.65 5.68 5.72 5.73 All 53 releases
wpremote / callback / request.php

request.php in The WP Remote WordPress Plugin 6.65, at callback/request.php

322 lines 9.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) exit;
4 if (!class_exists('WPRCallbackRequest')) :
5 class WPRCallbackRequest {
6 public $params;
7 public $method;
8 public $wing;
9 public $is_afterload;
10 public $is_aftershutdown;
11 public $keep_page_output;
12 public $is_admin_ajax;
13 public $is_debug;
14 public $account;
15 public $settings;
16 public $sig;
17 public $sighshalgo;
18 public $time;
19 public $version;
20 public $is_sha1;
21 public $bvb64stream;
22 public $bvb64cksize;
23 public $checksum;
24 public $error = array();
25 public $pubkey_name;
26 public $bvprmsmac;
27 public $bvboundry;
28
29 private static $SIG_HASH_ALGO_MAP = array(
30 '1' => OPENSSL_ALGO_SHA1,
31 '7' => OPENSSL_ALGO_SHA256
32 );
33
34 public function __construct($account, $in_params, $settings) {
35 $this->params = array();
36 $this->account = $account;
37 $this->settings = $settings;
38 $this->wing = $in_params['wing'];
39 $this->method = $in_params['bvMethod'];
40 $this->is_afterload = array_key_exists('afterload', $in_params);
41 $this->is_aftershutdown = array_key_exists('aftershutdown', $in_params);
42 $this->keep_page_output = $this->is_aftershutdown &&
43 array_key_exists('keeppageoutput', $in_params);
44 $this->is_admin_ajax = array_key_exists('adajx', $in_params);
45 $this->is_debug = array_key_exists('bvdbg', $in_params);
46 $this->sig = $in_params['sig'];
47 $this->sighshalgo = !empty($in_params['sighshalgo']) ? $in_params['sighshalgo'] : '1';
48 $this->time = intval($in_params['bvTime']);
49 $this->version = $in_params['bvVersion'];
50 $this->is_sha1 = array_key_exists('sha1', $in_params);
51 $this->bvb64stream = isset($in_params['bvb64stream']);
52 $this->bvb64cksize = array_key_exists('bvb64cksize', $in_params) ? intval($in_params['bvb64cksize']) : false;
53 $this->checksum = array_key_exists('checksum', $in_params) ? $in_params['checksum'] : false;
54 $this->pubkey_name = !empty($in_params['pubkeyname']) ?
55 WPRAccount::sanitizeKey($in_params['pubkeyname']) : 'm_public';
56 $this->bvprmsmac = !empty($in_params['bvprmsmac']) ? WPRAccount::sanitizeKey($in_params['bvprmsmac']) : "";
57 $this->bvboundry = !empty($in_params['bvboundry']) ? $in_params['bvboundry'] : "";
58 }
59
60 public function isAPICall() {
61 return array_key_exists('apicall', $this->params);
62 }
63
64 public function http_request($url, $body) {
65 $body = http_build_query($body);
66 $response = wp_remote_post($url, array(
67 'body' => $body,
68 'timeout' => 15,
69 'headers' => array(
70 'Content-Type' => 'application/x-www-form-urlencoded',
71 ),
72 ));
73
74 if (is_wp_error($response)) {
75 return false;
76 }
77
78 return wp_remote_retrieve_body($response);
79 }
80
81 public function get_params_via_api($params_key, $apiurl) {
82 $res = $this->http_request($apiurl, array('bvkey' => $params_key));
83
84 if ($res === FALSE) {
85 return false;
86 }
87
88 return $res;
89 }
90
91 public function info() {
92 $info = array(
93 "requestedsig" => $this->sig,
94 "requestedtime" => $this->time,
95 "requestedversion" => $this->version,
96 "error" => $this->error
97 );
98 if ($this->is_debug) {
99 $info["inreq"] = $this->params;
100 }
101 if ($this->is_admin_ajax) {
102 $info["adajx"] = true;
103 }
104 if ($this->is_afterload) {
105 $info["afterload"] = true;
106 }
107 if ($this->is_aftershutdown) {
108 $info["aftershutdown"] = true;
109 }
110 if ($this->keep_page_output) {
111 $info["keeppageoutput"] = true;
112 }
113 return $info;
114 }
115
116 public function processParams($in_params) {
117 $params = array();
118
119 if (array_key_exists('obend', $in_params) && function_exists('ob_end_clean'))
120 @ob_end_clean();
121
122 if (array_key_exists('op_reset', $in_params) && function_exists('output_reset_rewrite_vars'))
123 @output_reset_rewrite_vars();
124
125 if (array_key_exists('concat', $in_params)) {
126 foreach ($in_params['concat'] as $key) {
127 $concated = '';
128 $count = intval($in_params[$key]);
129 for ($i = 1; $i <= $count; $i++) {
130 $concated .= $in_params[$key."_bv_".$i];
131 }
132 $in_params[$key] = $concated;
133 }
134 }
135
136 if (isset($in_params['bvpdataviaapi']) && isset($in_params['bvapiurl'])) {
137 $pdata = $this->get_params_via_api($in_params['bvpdataviaapi'], $in_params['bvapiurl']);
138 if ($pdata !== false) {
139 $in_params["bvprms"] = $pdata;
140 }
141 }
142
143 if (array_key_exists('bvprms', $in_params) && isset($in_params['bvprms'])) {
144 if (!empty($in_params['bvprmshshalgo']) && $in_params['bvprmshshalgo'] === 'sha256') {
145 $calculated_mac = hash_hmac('SHA256', $in_params['bvprms'], $this->account->secret);
146 } else {
147 $calculated_mac = hash_hmac('SHA1', $in_params['bvprms'], $this->account->secret);
148 }
149
150 if ($this->compare_mac($this->bvprmsmac, $calculated_mac) === true) {
151
152 if (array_key_exists('b64', $in_params)) {
153 foreach ($in_params['b64'] as $key) {
154 if (is_array($in_params[$key])) {
155 $in_params[$key] = array_map('base64_decode', $in_params[$key]);
156 } else {
157 $in_params[$key] = base64_decode($in_params[$key]);
158 }
159 }
160 }
161
162 if (array_key_exists('unser', $in_params)) {
163 foreach ($in_params['unser'] as $key) {
164 $in_params[$key] = json_decode($in_params[$key], TRUE);
165 }
166 }
167
168 if (array_key_exists('sersafe', $in_params)) {
169 $key = $in_params['sersafe'];
170 $in_params[$key] = WPRCallbackRequest::serialization_safe_decode($in_params[$key]);
171 }
172
173 if (array_key_exists('bvprms', $in_params) && isset($in_params['bvprms'])) {
174 $params = $in_params['bvprms'];
175 }
176
177 if (array_key_exists('clacts', $in_params)) {
178 foreach ($in_params['clacts'] as $action) {
179 remove_all_actions($action);
180 }
181 }
182
183 if (array_key_exists('clallacts', $in_params)) {
184 global $wp_filter;
185 foreach ( $wp_filter as $filter => $val ){
186 remove_all_actions($filter);
187 }
188 }
189
190 if (array_key_exists('memset', $in_params)) {
191 $val = intval($in_params['memset']);
192 // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- Required for memory limit adjustment
193 @ini_set('memory_limit', $val.'M');
194 }
195
196 return $params;
197 }
198 }
199 return false;
200 }
201
202 private function compare_mac($l_hash, $r_hash) {
203 if (!is_string($l_hash) || !is_string($r_hash)) {
204 return false;
205 }
206
207 if (strlen($l_hash) !== strlen($r_hash)) {
208 return false;
209 }
210
211 if (function_exists('hash_equals')) {
212 return hash_equals($l_hash, $r_hash);
213 } else {
214 return $l_hash === $r_hash;
215 }
216 }
217
218 public static function serialization_safe_decode($data) {
219 if (is_array($data)) {
220 $data = array_map(array('WPRCallbackRequest', 'serialization_safe_decode'), $data);
221 } elseif (is_string($data)) {
222 $data = base64_decode($data);
223 }
224
225 return $data;
226 }
227
228 public function authenticate() {
229 if (!$this->account) {
230 $this->error["message"] = "ACCOUNT_NOT_FOUND";
231 return false;
232 }
233
234 $bv_last_recv_time = $this->settings->getOption('bvLastRecvTime');
235 if ($this->time < intval($bv_last_recv_time) - 300) {
236 return false;
237 }
238
239 $data = $this->method.$this->account->secret.$this->time.$this->version.$this->bvprmsmac;
240 if (!$this->verify($data, base64_decode($this->sig), $this->sighshalgo)) {
241 return false;
242 }
243 $this->settings->updateOption('bvLastRecvTime', $this->time);
244
245 return 1;
246 }
247
248 public function verify($data, $sig, $sighshalgo) {
249 if (!function_exists('openssl_verify') || !function_exists('openssl_pkey_get_public')) {
250 $this->error["message"] = "OPENSSL_FUNCS_NOT_FOUND";
251 return false;
252 }
253
254 $openssl_algo = array_key_exists($sighshalgo, self::$SIG_HASH_ALGO_MAP) ? self::$SIG_HASH_ALGO_MAP[$sighshalgo] : null;
255 if ($openssl_algo === null) {
256 $this->error["message"] = "UNSUPPORTED_HASH_ALGORITHM: " . $sighshalgo;
257 return false;
258 }
259
260 $key_file = dirname( __DIR__ ) . '/public_keys/' . $this->pubkey_name . '.pub';
261 if (!file_exists($key_file)) {
262 $this->error["message"] = "PUBLIC_KEY_NOT_FOUND";
263 return false;
264 }
265
266 $public_key_str = WPRWPFileSystem::getInstance()->getContents($key_file);
267
268 $public_key = openssl_pkey_get_public($public_key_str);
269 if (!$public_key) {
270 $this->error["message"] = "UNABLE_TO_LOAD_PUBLIC_KEY";
271 return false;
272 }
273
274 $verify = openssl_verify($data, $sig, $public_key, $openssl_algo);
275 if ($verify === 1) {
276 return true;
277 } elseif ($verify === 0) {
278 $this->error["message"] = "INCORRECT_SIGNATURE";
279 $this->error["pubkey_sig"] = substr(hash('md5', $public_key_str), 0, 8);
280 } else {
281 $this->error["message"] = "OPENSSL_VERIFY_FAILED";
282 }
283 return false;
284 }
285
286 public function corruptedParamsResp() {
287 $bvinfo = new WPRInfo($this->settings);
288
289 return array(
290 "account_info" => $this->account->info(),
291 "request_info" => $this->info(),
292 "bvinfo" => $bvinfo->info(),
293 "statusmsg" => "BVPRMS_CORRUPTED"
294 );
295 }
296
297 public function authFailedResp() {
298 $api_public_key = WPRAccount::getApiPublicKey($this->settings);
299 $default_account_pubkey = WPRAccount::getDefaultPublicKey();
300 $bvinfo = new WPRInfo($this->settings);
301 $resp = array(
302 "request_info" => $this->info(),
303 "bvinfo" => $bvinfo->info(),
304 "statusmsg" => "FAILED_AUTH",
305 "api_pubkey" => substr($api_public_key, 0, 8)
306 );
307
308 if (is_string($default_account_pubkey) && strlen($default_account_pubkey) >= 32) {
309 $resp["default_account_pubkey"] = substr($default_account_pubkey, 0, 8);
310 }
311
312 if ($this->account) {
313 $resp["account_info"] = $this->account->info();
314 } else {
315 $resp["account_info"] = array("error" => "ACCOUNT_NOT_FOUND");
316 }
317
318 return $resp;
319 }
320 }
321 endif;
322