PluginProbe
WebTotem Security / 2.1.7
WebTotem Security v2.1.7
3.0.1 3.0.0 trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.3.3 2.0 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.1 2.2.2 2.2.3 2.2.4 All 109 releases
wt-security / library / WT.php

WT.php in WebTotem Security 2.1.7, at library/WT.php

384 lines 23.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php defined('ABSPATH') or die("Protected By WT!");
2
3
4 class WTSEC_LIBRARY_WT
5 {
6 const URL = "https://api.wtotem.com/graphql";
7
8 public static function auth($key)
9 {
10 $payload = '{"query":"mutation{\n guest{\n apiKeys{\n auth(apiKey:\"' . $key . '\"),{\n token{\n value,refreshToken,expiresIn\n }\n }\n }\n }\n}"}';
11 return self::requestApi($payload);
12 }
13
14 protected static function requestApi($payload, $token = false, $repeat = false)
15 {
16 if ($token) {
17 $token = WTSEC_LIBRARY_App::getToken();
18 }
19 $args = [
20 'body' => $payload,
21 'timeout' => '30',
22 'sslverify' => false,
23 'headers' => ['Content-Type:application/json', 'Content-Type' => 'application/json', 'source:WORDPRESS', 'Accept: application/json'],
24 ];
25 if (!is_null($token) && $token) {
26 $authorization = "Bearer " . $token;
27 $args['headers'] = array_merge($args['headers'], ["Authorization" => $authorization]);
28 }
29 $response = wp_remote_post(self::URL, $args);
30 $httpcode = wp_remote_retrieve_response_code($response);
31
32 if ($httpcode < 200) {
33 WTSEC_LIBRARY_Session::setNotification("error", WTSEC_LIBRARY_Localization::lmsg('could_not_connect_to_the_server'));
34 }
35 $response = wp_remote_retrieve_body($response);
36 $result = json_decode($response, true);
37 if (isset($result['errors'][0]['message'])) {
38 $message = self::diffMesageForHuman($result['errors'][0]['message']);
39 if (stripos($result['errors'][0]['message'], "token") !== false && !$repeat) {
40 $result = WTSEC_LIBRARY_WT::auth(wtsec_app()->get("api_key"));
41 if (isset($result['data']['guest']['apiKeys']['auth']['token']['value'])) {
42 $token_ = $result['data']['guest']['apiKeys']['auth']['token']['value'];
43 WTSEC_LIBRARY_App::login($token_);
44 return self::requestApi($payload, $token, true);
45 } else {
46 WTSEC_LIBRARY_App::logout();
47 }
48 } else {
49 if ($message !== false) {
50 WTSEC_LIBRARY_Session::setNotification("warning", $message);
51 }
52 }
53 }
54 return $result;
55 }
56
57 public static function diffMesageForHuman($message)
58 {
59 $definition = $message;
60 $excepts = [
61 "RESOURCE_NOT_FOUND", "DUPLICATE_HOST", "INVALID_CREDENTIALS", "INVALID_API_KEY", "Invalid token",
62 ];
63 if (in_array($message, $excepts)) {
64 return false;
65 }
66 switch ($message) {
67 case 'HOSTS_LIMIT_EXCEEDED':
68 $definition = WTSEC_LIBRARY_Localization::lmsg('hosts_limit_exceed');
69 break;
70 case 'Invalid token':
71 $definition = WTSEC_LIBRARY_Localization::lmsg('invalid_token');
72 break;
73 case 'USER_ALREADY_REGISTERED':
74 $definition = WTSEC_LIBRARY_Localization::lmsg('user_already_exist');
75 break;
76 case 'DUPLICATE_HOST':
77 $definition = WTSEC_LIBRARY_Localization::lmsg('duplicate_host');
78 break;
79 case 'INVALID_DOMAIN_NAME':
80 $definition = WTSEC_LIBRARY_Localization::lmsg('invalid_domain_name');
81 break;
82 }
83 return $definition;
84 }
85
86 //del
87 public static function requestURL($url)
88 {
89 $args = [
90 'timeout' => '30',
91 'sslverify' => false,
92 ];
93 $response = wp_remote_get($url, $args);
94 $httpcode = wp_remote_retrieve_response_code($response);
95 if ($httpcode < 200) {
96 WTSEC_LIBRARY_Session::setNotification("error", WTSEC_LIBRARY_Localization::lmsg('could_not_connect_to_the_server'));
97 }
98 $response = wp_remote_retrieve_body($response);
99 return $response;
100 }
101
102
103 public static function getFileByUrl($url)
104 {
105 $args = [
106 'timeout' => '30',
107 'sslverify' => false,
108 ];
109 $response = wp_remote_get($url, $args);
110 $httpcode = wp_remote_retrieve_response_code($response);
111 if ($httpcode < 200) {
112 WTSEC_LIBRARY_Session::setNotification("error", WTSEC_LIBRARY_Localization::lmsg('could_not_connect_to_the_server'));
113 }
114 $filename = null;
115 $metas = explode(";",$response['headers']["content-disposition"]);
116 foreach ($metas as $meta){
117 if(stripos($meta,"filename") !== false){
118 $filename = trim(str_replace(["filename=","=","\""],"",$meta));
119 }
120 }
121 $response = wp_remote_retrieve_body($response);
122 return ["body" => $response, "filename" => $filename];
123 }
124
125 public static function getOwnSite($attempt = false)
126 {
127 $payload = '{"query":"query getSites { auth { viewer { sites { ...sites __typename } __typename } __typename }}fragment sites on SiteQueries { list(filter: {}) { edges { node { id hostname title ssl { status __typename } availability { status __typename } reputation { status __typename } ports { status __typename } deface { status __typename } domain { status __typename } antivirus { status __typename } firewall { status __typename } maliciousScript { stack { name __typename } __typename } __typename } __typename } __typename } __typename}"}';
128
129 $result = self::requestApi($payload, true);
130 if (isset($result['data']['auth']['viewer']['sites']['list']['edges'])) {
131 //mutator
132 foreach ($result['data']['auth']['viewer']['sites']['list']['edges'] as &$m) {
133 if (isset($m['node']['hostname'])) {
134 $m['node']['hostname'] = WTSEC_LIBRARY_Idn::idn_to_utf8($m['node']['hostname']);
135 // if ($m['node']['id'] == "c2l0ZV8yNTg=") {
136 // return $m['node'];
137 // }
138 if (self::isSiteUrl($m['node']['hostname'])) {
139 return $m['node'];
140 }
141 }
142 }
143 $add_site = self::addSite(WTSEC_SITE_URL);
144 if (isset($add_site['errors'])) {
145 return $result['data']['node'] = [];
146 } else {
147 if (!$attempt) {
148 return self::getOwnSite(true);
149 }
150 }
151 }
152 return [];
153 }
154
155 public static function isSiteUrl($url)
156 {
157 return WTSEC_LIBRARY_Idn::idn_to_utf8(WTSEC_SITE_URL) === $url;
158 }
159
160 public static function addSite($url)
161 {
162 $payload = '{"variables":{"input":{"title":"' . $url . '","hostname":"' . $url . '","configs":{"scheme":"http","port":80,"wa":{},"dec":{},"ps":{}}}},"query":"mutation ($input: CreateSiteInput) {\n auth {\n sites {\n create(input: $input) {\n id\n hostname\n title\n __typename\n }\n __typename\n }\n __typename\n }\n}\n"}';
163 return self::requestApi($payload, true);
164 }
165
166 public static function getAllChecks($host_id)
167 {
168 $from = time() - (60 * 60 * 24);
169 $to = time();
170 $from_waf = time() - (60 * 60 * 24 * 7);
171 $payload = '{"query":"query($id: ID!, $dateRange:DateRangeInput!) {\n auth {\n viewer {\n sites {\n one(id: $id) {\n ports{\n status\n ip\n tcp\n lastTest{\n time\n }\n }\n availability {\n status\n lastTest {\n time\n }\n responseTime\n downTime(dateRange: $dateRange)\n percent(dateRange: $dateRange)\n }\n deface {\n status\n lastTest {\n time\n }\n words\n count\n }\n domain {\n status\n registrar\n owner\n email\n createdDate\n expiredDate\n }\n ports {\n status\n lastTest {\n time\n }\n ip\n tcp\n country\n }\n ssl {\n status\n daysLeft\n expiryDate\n issueDate\n }\n reputation {\n status\n lastTest {\n time\n }\n virusList {\n viruses\n antiVirus\n }\n }\n firewall {\n lastTest { \n time\n } \n status\n chart(dateRange: $dateRange) {\n time\n attacks\n blocked\n }\n report(dateRange: $dateRange) {\n time\n attacks\n ip\n }\n }\n maliciousScript{\n lastTest{\n time\n }\n status\n }\n antivirus{\n status \n stats { \n changed\n deleted\n scaned\n infected\n error\n } \n lastTest { \n time\n } \n isFirstCheck\n }\n }\n }\n }\n }\n}","variables":{"id":"' . $host_id . '","dateRange":{"to":' . $to . ',"from":' . $from_waf . '}}}';
172 // $payload = '{"query":"query($id: ID!, $dateRange:DateRangeInput!) {\n auth {\n viewer {\n sites {\n one(id: $id) {\n ports{\n status\n ip\n tcp\n lastTest{\n time\n }\n }\n availability {\n status\n lastTest {\n time\n }\n responseTime\n downTime(dateRange: $dateRange)\n percent(dateRange: $dateRange)\n }\n deface {\n status\n lastTest {\n time\n }\n words\n count\n }\n domain {\n status\n registrar\n owner\n email\n createdDate\n expiredDate\n }\n ports {\n status\n lastTest {\n time\n }\n ip\n tcp\n country\n }\n ssl {\n status\n daysLeft\n expiryDate\n issueDate\n }\n reputation {\n status\n lastTest {\n time\n }\n virusList {\n viruses\n antiVirus\n }\n }\n firewall {\n lastTest { \n time\n } \n status\n logs{\n edges\n{\n node{\n status\n country\n type\n}\n}\n}\n chart(dateRange: $dateRange) {\n time\n attacks\n blocked\n }\n report(dateRange: $dateRange) {\n time\n attacks\n ip\n }\n }\n maliciousScript{\n lastTest{\n time\n }\n status\n }\n antivirus{\n status \n stats { \n changed\n deleted\n scaned\n infected\n error\n } \n lastTest { \n time\n } \n isFirstCheck\n }\n }\n }\n }\n }\n}","variables":{"id":"' . $host_id . '","dateRange":{"to":' . $to . ',"from":' . $from_waf . '}}}';
173 $response = self::requestApi($payload, true);
174 if (isset($response['data']['auth']['viewer']['sites']['one'])) {
175 return $response['data']['auth']['viewer']['sites']['one'];
176 }
177 return [];
178 }
179
180 public static function changeStatus($config_id, $host_id)
181 {
182 $payload = '{"query":"\n mutation {\n toggleServiceConfig(\n id: ' . $config_id . '\n userhostId: ' . $host_id . '\n ) {\n isActive\n }\n }\n "}';
183 return self::requestApi($payload, true);
184 }
185
186 public static function serviceConnect($id, $service)
187 {
188 $payload = '{"query":"mutation {\n auth {\n agents{\n check(siteId:\"' . $id . '\",service:' . strtolower($service) . ',plugin:WORDPRESS)\n }\n }\n}\n"}';
189 return self::requestApi($payload, true);
190 }
191
192 public static function generateFile($id, $service)
193 {
194 $payload = '{"query":"mutation {\n auth {\n agents{\n generate(siteId:\"' . $id . '\",service:' . strtolower($service) . '){\n agentName\n }\n }\n }\n}\n"}';
195 return self::requestApi($payload, true);
196 }
197
198 public static function generateAmFile($id)
199 {
200 $payload = '{"operationName":null,"variables":{},"query":"mutation {\n auth {\n am {\n install(siteId: \"'.$id.'\")\n }\n }\n}\n"}';
201 return self::requestApi($payload, true);
202 }
203
204 public static function checkStatus($id, $service)
205 {
206 $payload = '{"operationName":null,"variables":{"id":"' . $id . '"},"query":"query ($id: ID!) {\n auth {\n viewer {\n sites {\n one(id: $id) {\n ... on Site {\n configs {\n ... on ' . $service . 'Config {\n isActive\n id\n }\n }\n }\n }\n }\n }\n }\n}\n"}';
207 return self::requestApi($payload, true);
208 }
209
210 public static function getOptions($host_id)
211 {
212 $payload = '{"query":"query{\nuserHost(id:' . $host_id . '){\n id\n title\n hostname\n stack\n createdAt\n services {\n id\n name\n configs {\n id\n \tdata\n isActive\n }\n }\n }\n}"}';
213 return self::requestApi($payload, true);
214 }
215
216 public static function getAntivirus($host_id)
217 {
218 $payload = '{"operationName":null,"variables":{"id":"' . $host_id . '","avLogFilter":{"event":"infected","order":{"direction":"DESC","field":"time"},"pagination":{"first":20,"cursor":null}}},"query":"query ($id: ID!, $avLogFilter: AvLogFilter!) {\n auth {\n viewer {\n sites {\n one(id: $id) {\n id\n ... on Site {\n configs {\n ... on AvConfig {\n isActive\n id\n }\n }\n }\n antivirus {\n status\n log(avLogFilter: $avLogFilter) {\n edges {\n node {\n filePath\n matches\n event\n signatures\n time\n }\n }\n }\n lastTest {\n time\n }\n stats {\n changed\n deleted\n scaned\n infected\n }\n }\n }\n }\n }\n }\n}\n"}';
219 return self::requestApi($payload, true);
220 }
221
222
223 public static function getFirewall($host_id)
224 {
225 $to = time();
226 $from_waf = time() - (60 * 60 * 24 * 7);
227 $payload = '{"operationName":"FirewallAttackLog","variables":{"dateRange":{"to":'.$to.',"from":'.$from_waf.'},"id":"'.$host_id.'","wafLogFilter":{"dateRange":{"to":'.$to.',"from":'.$from_waf.'},"order":{"direction":"DESC","field":"time"},"pagination":{"first":20,"cursor":null}}},"query":"query FirewallAttackLog($id: ID!, $wafLogFilter: WafLogFilter! ,$dateRange: DateRangeInput!) {\n auth {\n viewer {\n sites {\n one(id: $id) {\n firewall {\n lastTest{\n time\n }\n status\n ...FirewallLogFragment\n map(dateRange: $dateRange) { attacks, country } __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n}\n\nfragment FirewallLogFragment on Waf {\n logs(wafLogFilter: $wafLogFilter) {\n edges {\n cursor\n node {\n type\n blocked\n payload\n ip\n location {\n country {\n nameEn\n __typename\n }\n __typename\n }\n time\n request\n status\n country\n category\n __typename\n }\n __typename\n }\n pageInfo {\n endCursor\n hasNextPage\n __typename\n }\n __typename\n }\n __typename\n}\n"}';
228 return self::requestApi($payload, true);
229 }
230
231
232
233 public static function getFirewallChart($host_id)
234 {
235 $to = time();
236 $from_waf = time() - (60 * 60 * 24 * 7);
237 $payload = '{ "query":"query($id: ID!, $dateRange: DateRangeInput!, $wafLogFilter: WafLogFilter!) { auth { viewer { sites { one(id: $id) { firewall { lastTest { time } status logs(wafLogFilter: $wafLogFilter) { edges { node { status country type userAgent } } } chart(dateRange: $dateRange) { time attacks blocked } report(dateRange: $dateRange) { time attacks ip } } } } } } }", "operationName":null,"variables":{"id":"' . $host_id . '","dateRange":{"to":' . $to . ',"from":' . $from_waf . '}, "wafLogFilter": { "dateRange": { "from": ' .$from_waf. ', "to": ' .$to. ' }, "pagination": { "first": 20, "cursor": null }, "order": { "direction": "DESC", "field": "time" } } } }';
238 return self::requestApi($payload, true);
239 }
240
241 public static function getStatusIcon($status)
242 {
243 $statuses = [
244 "clean" => [
245 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.ok'),
246 "color" => self::getColor("success"),
247 "image" => "check-mark.svg"
248 ],
249 "pending" => [
250 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.pending'),
251 "color" => self::getColor("grey"),
252 "image" => "loading.svg"
253 ],
254 "expired" => [
255 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.expired'),
256 "color" => self::getColor("orange"),
257 "image" => "warning.svg"
258
259 ],
260 "invalid" => [
261 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.invalid'),
262 "color" => self::getColor("error"),
263 "image" => "warning.svg"
264 ],
265 "no_cert" => [
266 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.no_cert'),
267 "color" => self::getColor("orange"),
268 "image" => "warning.svg"
269 ],
270 "error" => [
271 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.error'),
272 "color" => self::getColor("error"),
273 "image" => "warning.svg"
274 ],
275 "expires" => [
276 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.expires'),
277 "color" => self::getColor("orange"),
278 "image" => "warning.svg"
279 ],
280 "expires_today" => [
281 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.expires_today'),
282 "color" => self::getColor("error"),
283 "image" => "warning.svg"
284 ],
285 "down" => [
286 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.down'),
287 "color" => self::getColor("error"),
288 "image" => "warning.svg"
289 ],
290 "up" => [
291 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.up'),
292 "color" => self::getColor("success"),
293 "image" => "check-mark.svg"
294 ],
295 "infected" => [
296 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.infected'),
297 "color" => self::getColor("error"),
298 "image" => "warning.svg"
299 ],
300 "open_ports" => [
301 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.open'),
302 "color" => self::getColor("orange"),
303 "image" => "warning.svg"
304 ],
305 "deface" => [
306 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.deface'),
307 "color" => self::getColor("error"),
308 "image" => "warning.svg"
309 ],
310 "modified" => [
311 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.modified'),
312 "color" => self::getColor("grey"),
313 "image" => "warning.svg"
314 ],
315 "not_supported" => [
316 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.unsupported'),
317 "color" => self::getColor("orange"),
318 "image" => "warning.svg"
319 ],
320 "not_registered" => [
321 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.not_registered'),
322 "color" => self::getColor("orange"),
323 "image" => "warning.svg"
324 ],
325 "not_installed" => [
326 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.not_installed'),
327 "color" => self::getColor("error"),
328 "image" => "warning.svg"
329 ],
330 "working" => [
331 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.working'),
332 "color" => self::getColor("success"),
333 "image" => "check-mark.svg"
334 ],
335 ];
336 if (isset($statuses[$status])) {
337 return ["image" => $statuses[$status]["image"], "icon" => $statuses[$status]["color"]["icon"], "color" => $statuses[$status]["color"]["color"], "text" => "<span class='" . $statuses[$status]["color"]["color"] . "'>" . $statuses[$status]["text"] . "</span>"];
338 } else {
339 return ["image" => "warning.svg", "icon" => "ww-icon--status_unknow", "color" => "ww--status_unknow", "text" => "<span class='ww--status_unknow'>Unknown status</span>"];
340 }
341 }
342
343 public static function getColor($type)
344 {
345 $types = [
346 "green" => "is--status--ok",
347 "red" => "is--status--error",
348 "success" => "is--status--ok",
349 "error" => "is--status--error",
350 "orange" => "is--status--warning",
351 "warning" => "is--status--warning",
352 "grey" => "ww--status_unknow"
353 ];
354 $icon_types = [
355 "green" => "ww-icon--status_ok",
356 "red" => "ww-icon--status_error",
357 "success" => "ww-icon--status_ok",
358 "error" => "ww-icon--status_error",
359 "orange" => "ww-icon--status_warning",
360 "warning" => "ww-icon--status_warning",
361 "grey" => "ww-icon--status_unknow"
362 ];
363 return ["icon" => $icon_types[$type], "color" => $types[$type]];
364 }
365
366 public static function getConfigId($configs)
367 {
368 $id = 0;
369 $is_active = false;
370 foreach ($configs as &$config) {
371 if (!empty($config)) {
372 $id = $config['id'];
373 $is_active = $config['isActive'];
374 break;
375 }
376 }
377 return compact('id', 'is_active');
378 }
379
380 public static function getScore(){
381 return self::requestURL("https://api.wtotem.com/site/score?url=".WTSEC_SITE_URL);
382 }
383
384 }