PluginProbe
WebTotem Security / 2.1.6
WebTotem Security v2.1.6
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.6, at library/WT.php

348 lines 18.0 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 'RESOURCE_NOT_FOUND':
71 $definition = WTSEC_LIBRARY_Localization::lmsg('resource_not_found');
72 break;
73 case 'Invalid token':
74 $definition = WTSEC_LIBRARY_Localization::lmsg('invalid_token');
75 break;
76 case 'USER_ALREADY_REGISTERED':
77 $definition = WTSEC_LIBRARY_Localization::lmsg('user_already_exist');
78 break;
79 case 'DUPLICATE_HOST':
80 $definition = WTSEC_LIBRARY_Localization::lmsg('duplicate_host');
81 break;
82 case 'Agent does not exist or has been already verified':
83 $definition = WTSEC_LIBRARY_Localization::lmsg('agent_does_not_exist_or_has_been_already_verified');
84 break;
85 case 'INVALID_DOMAIN_NAME':
86 $definition = WTSEC_LIBRARY_Localization::lmsg('invalid_domain_name');
87 break;
88 }
89 return $definition;
90 }
91
92 public static function requestURL($url)
93 {
94 $args = [
95 'timeout' => '30',
96 'sslverify' => false,
97 ];
98 $response = wp_remote_get($url, $args);
99 $httpcode = wp_remote_retrieve_response_code($response);
100 if ($httpcode < 200) {
101 WTSEC_LIBRARY_Session::setNotification("error", WTSEC_LIBRARY_Localization::lmsg('could_not_connect_to_the_server'));
102 }
103 dd($response['headers']["content-disposition"]);
104 $response = wp_remote_retrieve_body($response);
105 return $response;
106 }
107
108
109 public static function getFileByUrl($url)
110 {
111 $args = [
112 'timeout' => '30',
113 'sslverify' => false,
114 ];
115 $response = wp_remote_get($url, $args);
116 $httpcode = wp_remote_retrieve_response_code($response);
117 if ($httpcode < 200) {
118 WTSEC_LIBRARY_Session::setNotification("error", WTSEC_LIBRARY_Localization::lmsg('could_not_connect_to_the_server'));
119 }
120 $filename = null;
121 $metas = explode(";",$response['headers']["content-disposition"]);
122 foreach ($metas as $meta){
123 if(stripos($meta,"filename") !== false){
124 $filename = trim(str_replace(["filename=","=","\""],"",$meta));
125 }
126 }
127 $response = wp_remote_retrieve_body($response);
128 return ["body" => $response, "filename" => $filename];
129 }
130
131 public static function getOwnSite($attempt = false)
132 {
133 $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}"}';
134
135 $result = self::requestApi($payload, true);
136 if (isset($result['data']['auth']['viewer']['sites']['list']['edges'])) {
137 //mutator
138 foreach ($result['data']['auth']['viewer']['sites']['list']['edges'] as &$m) {
139 if (isset($m['node']['hostname'])) {
140 $m['node']['hostname'] = WTSEC_LIBRARY_Idn::idn_to_utf8($m['node']['hostname']);
141 // if ($m['node']['id'] == "c2l0ZV8yNTg=") {
142 // return $m['node'];
143 // }
144 if (self::isSiteUrl($m['node']['hostname'])) {
145 return $m['node'];
146 }
147 }
148 }
149 $add_site = self::addSite(WTSEC_SITE_URL);
150 if (isset($add_site['errors'])) {
151 return $result['data']['node'] = [];
152 } else {
153 if (!$attempt) {
154 return self::getOwnSite(true);
155 }
156 }
157 }
158 return [];
159 }
160
161 public static function isSiteUrl($url)
162 {
163 return WTSEC_LIBRARY_Idn::idn_to_utf8(WTSEC_SITE_URL) === $url;
164 }
165
166 public static function addSite($url)
167 {
168 $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"}';
169 return self::requestApi($payload, true);
170 }
171
172 public static function getAllChecks($host_id)
173 {
174 $from = time() - (60 * 60 * 24);
175 $to = time();
176 $from_waf = time() - (60 * 60 * 24 * 7);
177 $payload = '{"query":"query($id: ID!, $dateRange:DateRangeInput!) {\n auth {\n viewer {\n sites {\n one(id: $id) {\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 . '}}}';
178 $response = self::requestApi($payload, true);
179 if (isset($response['data']['auth']['viewer']['sites']['one'])) {
180 return $response['data']['auth']['viewer']['sites']['one'];
181 }
182 return [];
183 }
184
185 public static function changeStatus($config_id, $host_id)
186 {
187 $payload = '{"query":"\n mutation {\n toggleServiceConfig(\n id: ' . $config_id . '\n userhostId: ' . $host_id . '\n ) {\n isActive\n }\n }\n "}';
188 return self::requestApi($payload, true);
189 }
190
191 public static function serviceConnect($id, $service)
192 {
193 $payload = '{"query":"mutation {\n auth {\n agents{\n check(siteId:\"' . $id . '\",service:' . strtolower($service) . ',plugin:WORDPRESS)\n }\n }\n}\n"}';
194 return self::requestApi($payload, true);
195 }
196
197 public static function generateFile($id, $service)
198 {
199 $payload = '{"query":"mutation {\n auth {\n agents{\n generate(siteId:\"' . $id . '\",service:' . strtolower($service) . '){\n agentName\n }\n }\n }\n}\n"}';
200 return self::requestApi($payload, true);
201 }
202
203 public static function generateAmFile($id)
204 {
205 $payload = '{"operationName":null,"variables":{},"query":"mutation {\n auth {\n am {\n install(siteId: \"'.$id.'\")\n }\n }\n}\n"}';
206 return self::requestApi($payload, true);
207 }
208
209 public static function checkStatus($id, $service)
210 {
211 $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"}';
212 return self::requestApi($payload, true);
213 }
214
215 public static function getOptions($host_id)
216 {
217 $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}"}';
218 return self::requestApi($payload, true);
219 }
220
221 public static function getAntivirus($host_id)
222 {
223 $payload = '{"operationName":null,"variables":{"id":"' . $host_id . '","avLogFilter":{"event":"infected","order":{"direction":"DESC","field":"time"},"pagination":{"first":10,"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"}';
224 return self::requestApi($payload, true);
225 }
226
227 public static function getStatusIcon($status)
228 {
229 $statuses = [
230 "clean" => [
231 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.ok'),
232 "color" => self::getColor("success")
233 ],
234 "pending" => [
235 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.pending'),
236 "color" => self::getColor("grey")
237 ],
238 "expired" => [
239 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.expired'),
240 "color" => self::getColor("orange")
241
242 ],
243 "invalid" => [
244 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.invalid'),
245 "color" => self::getColor("error")
246 ],
247 "no_cert" => [
248 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.no_cert'),
249 "color" => self::getColor("orange")
250 ],
251 "error" => [
252 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.error'),
253 "color" => self::getColor("error")
254 ],
255 "expires" => [
256 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.expires'),
257 "color" => self::getColor("orange")
258 ],
259 "expires_today" => [
260 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.expires_today'),
261 "color" => self::getColor("error")
262 ],
263 "down" => [
264 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.down'),
265 "color" => self::getColor("error")
266 ],
267 "up" => [
268 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.up'),
269 "color" => self::getColor("success")
270 ],
271 "infected" => [
272 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.infected'),
273 "color" => self::getColor("error")
274 ],
275 "open_ports" => [
276 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.open'),
277 "color" => self::getColor("orange")
278 ],
279 "deface" => [
280 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.deface'),
281 "color" => self::getColor("error")
282 ],
283 "modified" => [
284 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.modified'),
285 "color" => self::getColor("grey")
286 ],
287 "not_supported" => [
288 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.unsupported'),
289 "color" => self::getColor("orange")
290 ],
291 "not_registered" => [
292 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.not_registered'),
293 "color" => self::getColor("orange")
294 ],
295 "not_installed" => [
296 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.not_installed'),
297 "color" => self::getColor("error")
298 ],
299 "working" => [
300 "text" => WTSEC_LIBRARY_Localization::lmsg('statuses.working'),
301 "color" => self::getColor("success")
302 ],
303 ];
304 if (isset($statuses[$status])) {
305 return ["icon" => $statuses[$status]["color"]["icon"], "color" => $statuses[$status]["color"]["color"], "text" => "<span class='" . $statuses[$status]["color"]["color"] . "'>" . $statuses[$status]["text"] . "</span>"];
306 } else {
307 return ["icon" => "ww-icon--status_unknow", "color" => "ww--status_unknow", "text" => "<span class='ww--status_unknow'>Unknown status</span>"];
308 }
309 }
310
311 public static function getColor($type)
312 {
313 $types = [
314 "green" => "is--status--ok",
315 "red" => "is--status--error",
316 "success" => "is--status--ok",
317 "error" => "is--status--error",
318 "orange" => "is--status--warning",
319 "warning" => "is--status--warning",
320 "grey" => "ww--status_unknow"
321 ];
322 $icon_types = [
323 "green" => "ww-icon--status_ok",
324 "red" => "ww-icon--status_error",
325 "success" => "ww-icon--status_ok",
326 "error" => "ww-icon--status_error",
327 "orange" => "ww-icon--status_warning",
328 "warning" => "ww-icon--status_warning",
329 "grey" => "ww-icon--status_unknow"
330 ];
331 return ["icon" => $icon_types[$type], "color" => $types[$type]];
332 }
333
334 public static function getConfigId($configs)
335 {
336 $id = 0;
337 $is_active = false;
338 foreach ($configs as &$config) {
339 if (!empty($config)) {
340 $id = $config['id'];
341 $is_active = $config['isActive'];
342 break;
343 }
344 }
345 return compact('id', 'is_active');
346 }
347
348 }