PluginProbe
WebTotem Security / 2.1
WebTotem Security v2.1
3.0.2 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 All 110 releases
wt-security / library / WT.php

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

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