PluginProbe
CookieAdmin – Cookie Consent Banner / 1.2.6
CookieAdmin – Cookie Consent Banner v1.2.6
1.2.6 1.2.5 1.2.4 1.2.3 1.2.2 1.2.1 1.2.0 1.1.9 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 All 26 releases
cookieadmin / includes / scanner.php

scanner.php in CookieAdmin – Cookie Consent Banner 1.2.6, at includes/scanner.php

248 lines 6.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace CookieAdmin;
4
5 if(!defined('COOKIEADMIN_VERSION') || !defined('ABSPATH')){
6 die('Hacking Attempt');
7 }
8
9 class Scanner{
10
11 static $home_url;
12 static $urls_to_scan = [];
13 static $visited_urls = [];
14 static $raw_redirect_headers = [];
15 static $found_cookies = [];
16 static $scan_limit = 10;
17
18
19 static function start_scan(){
20
21 self::$home_url = get_home_url();
22 self::$urls_to_scan[] = self::$home_url;
23
24 while (! empty(self::$urls_to_scan) && count(self::$visited_urls) < self::$scan_limit){
25 $url = array_shift(self::$urls_to_scan); // Get the next URL from the queue
26
27 if (in_array($url, self::$visited_urls, true)){
28 continue;
29 }
30
31 self::scan_single_url($url);
32 }
33
34 return self::$found_cookies;
35 }
36
37
38 static function scan_single_url($url){
39
40 self::$visited_urls[] = $url;
41
42 $response = wp_remote_get($url, [
43 'sslverify' => false,
44 'timeout' => 15,
45 'redirection' => 5
46 ]);
47
48 if (is_wp_error($response)) return;
49
50 if (! empty($response['cookies'])){
51
52 $all_headers = wp_remote_retrieve_headers($response);
53 $raw_cookie_headers = isset($all_headers['set-cookie']) ? $all_headers['set-cookie'] : [];
54
55 self::process_and_store_cookies($response['cookies'], $raw_cookie_headers);
56 }
57
58 $body = wp_remote_retrieve_body($response);
59 if (empty($body)) return;
60
61 $dom = new \DOMDocument();
62 @$dom->loadHTML($body, LIBXML_NOERROR | LIBXML_NOWARNING);
63
64 self::find_and_queue_links($dom);
65 self::scan_forms_on_page($url, $dom);
66 }
67
68
69 static function scan_forms_on_page($page_url, $dom){
70
71 $forms = $dom->getElementsByTagName('form');
72
73 foreach ($forms as $form){
74
75 $method = strtolower($form->getAttribute('method'));
76 if ($method !== 'post'){
77 continue;
78 }
79
80 self::$raw_redirect_headers = [];
81
82 $action_url = $form->getAttribute('action');
83 if (empty($action_url) || $action_url[0] === '#'){
84 $action_url = $page_url;
85 } elseif ($action_url[0] === '/'){
86 $action_url = self::$home_url . $action_url;
87 }
88
89 $post_data = [];
90 $inputs = $form->getElementsByTagName('input');
91 foreach ($inputs as $input){
92 $name = $input->getAttribute('name');
93 $type = strtolower($input->getAttribute('type'));
94 if (empty($name)){
95 continue;
96 }
97 $value = $input->getAttribute('value');
98
99 switch ($type){
100 case 'text':
101 case 'email':
102 case 'url':
103 case 'password':
104 case 'search':
105 // If the value is empty, provide dummy data. Otherwise, use the existing value.
106 if (empty($value)){
107 if($type === 'email') $post_data[$name] = '[email protected]';
108 elseif($type === 'url') $post_data[$name] = 'https://cookieadmin.net';
109 else $post_data[$name] = 'Scanner Tester - '.uniqid();
110 } else {
111 $post_data[$name] = $value;
112 }
113 break;
114
115 case 'hidden':
116 $post_data[$name] = $value;
117 break;
118
119 case 'checkbox':
120 case 'radio':
121 if (empty($value)) $post_data[$name] = true;
122 break;
123
124 case 'submit':
125 $post_data[$name] = $value;
126 break;
127 }
128 }
129
130 $textareas = $form->getElementsByTagName('textarea');
131 foreach ($textareas as $textarea){
132 $name = $textarea->getAttribute('name');
133 if(!empty($name) && !isset($post_data[$name])){
134 $post_data[$name] = 'This is a test comment from the scanner. - '.uniqid();
135 }
136 }
137
138 if (!empty($post_data)){
139
140 add_action('requests-before_redirect_check', [self::class, 'capture_redirect_headers'], 10, 1);
141
142 $post_response = wp_remote_post($action_url, [
143 'sslverify' => false,
144 'body' => $post_data,
145 ]);
146
147 remove_action('requests-before_redirect_check', [self::class, 'capture_redirect_headers'], 10);
148
149 $final_headers = wp_remote_retrieve_headers($post_response);
150 $final_cookie_headers = isset($final_headers['set-cookie']) ? $final_headers['set-cookie'] : [];
151 if (!is_array($final_cookie_headers)) $final_cookie_headers = [$final_cookie_headers];
152
153 $all_raw_cookie_headers = array_merge(self::$raw_redirect_headers, $final_cookie_headers);
154
155 if (!is_wp_error($post_response) && !empty($post_response['cookies'])){
156 self::process_and_store_cookies($post_response['cookies'], $all_raw_cookie_headers);
157 }
158
159 }
160 }
161 }
162
163
164 static function process_and_store_cookies($cookie_objects, $all_raw_headers){
165
166 if(!is_array($all_raw_headers)){
167 $all_raw_headers = [$all_raw_headers];
168 }
169
170 foreach ($cookie_objects as $cookie){
171
172 if (! isset(self::$found_cookies[$cookie->name])){
173
174 $is_secure = false;
175 $is_httponly = false;
176 $max_age = null;
177 $samesite = null;
178
179 foreach ($all_raw_headers as $header_string){
180
181 if (!empty($header_string) && strpos(trim($header_string), $cookie->name . '=') === 0){
182
183 $is_secure = preg_match('/\bsecure\b/i', $header_string) === 1;
184 $is_httponly = preg_match('/\bhttponly\b/i', $header_string) === 1;
185
186 if (preg_match('/;\s*Max-Age\s*=\s*([0-9]+)/i', $header_string, $matches)){
187 $max_age = (int) $matches[1];
188 }
189
190 if (preg_match('/;\s*SameSite\s*=\s*(Strict|Lax|None)/i', $header_string, $matches)){
191 $samesite = ucfirst(strtolower($matches[1]));
192 }
193 break;
194 }
195 }
196
197 self::$found_cookies[$cookie->name] = [
198 'cookie_name' => $cookie->name,
199 'expires' => $cookie->expires,
200 'path' => $cookie->path,
201 'domain' => $cookie->domain,
202 'secure' => $is_secure,
203 'httponly' => $is_httponly,
204 'Max-Age' => $max_age,
205 'samesite' => $samesite,
206 ];
207 }
208 }
209 }
210
211
212 static function find_and_queue_links($dom){
213
214 $links = $dom->getElementsByTagName('a');
215
216 foreach ($links as $link){
217 $href = $link->getAttribute('href');
218
219 if (strpos($href, self::$home_url) === 0 || preg_match('/^\/(?!\/)/', $href)){
220
221 if ($href[0] === '/'){
222 $href = self::$home_url . $href;
223 }
224
225 if (! in_array($href, self::$visited_urls) && ! in_array($href, self::$urls_to_scan)){
226 self::$urls_to_scan[] = $href;
227 }
228 }
229 }
230 }
231
232 static function capture_redirect_headers($response){
233
234 if (is_object($response) && isset($response->headers['set-cookie'])){
235
236 $cookies = $response->headers['set-cookie'];
237
238 if (! is_array($cookies)){
239 $cookies = [$cookies];
240 }
241
242 self::$raw_redirect_headers = array_merge(self::$raw_redirect_headers, $cookies);
243 }
244
245 return $response;
246 }
247 }
248