Subversion Repositories vnag

Rev

Rev 40 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 40 Rev 42
Line 1... Line 1...
1
<?php /* <ViaThinkSoftSignature>
1
<?php /* <ViaThinkSoftSignature>
2
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
23
g==
23
g==
24
</ViaThinkSoftSignature> */ ?>
24
</ViaThinkSoftSignature> */ ?>
25
<?php
25
<?php
26
 
26
 
27
/*
27
/*
28
 * VNag - Nagios Framework for PHP
28
 * VNag - Nagios Framework for PHP
29
 * Developed by Daniel Marschall, ViaThinkSoft <www.viathinksoft.com>
29
 * Developed by Daniel Marschall, ViaThinkSoft <www.viathinksoft.com>
30
 * Licensed under the terms of the Apache 2.0 license
30
 * Licensed under the terms of the Apache 2.0 license
31
 *
31
 *
32
 * Revision 2021-12-06
32
 * Revision 2021-12-23
33
 */
33
 */
34
 
34
 
35
declare(ticks=1);
35
declare(ticks=1);
36
 
36
 
37
class OpenBugBountyCheck extends VNag {
37
class OpenBugBountyCheck extends VNag {
Line 107... Line 107...
107
                //assert(!empty($this->argDomain->getValue()));
107
                //assert(!empty($this->argDomain->getValue()));
108
                //assert(empty($this->argPrivateAPI->getValue()));
108
                //assert(empty($this->argPrivateAPI->getValue()));
109
 
109
 
110
                $fixed = 0;
110
                $fixed = 0;
111
                $unfixed = 0;
111
                $unfixed = 0;
-
 
112
                $unfixed_ignored = 0;
112
 
113
 
113
                $this->setStatus(VNag::STATUS_OK);
114
                $this->setStatus(VNag::STATUS_OK);
114
 
115
 
115
                $domain = strtolower($domain);
116
                $domain = strtolower($domain);
116
                $cache_file = $this->get_cache_dir() . '/' . md5($domain);
117
                $cache_file = $this->get_cache_dir() . '/' . md5($domain);
Line 127... Line 128...
127
 
128
 
128
                $xml = simplexml_load_string($cont);
129
                $xml = simplexml_load_string($cont);
129
                foreach ($xml as $x) {
130
                foreach ($xml as $x) {
130
                        $submission = $x->url;
131
                        $submission = $x->url;
131
 
132
 
-
 
133
                        if ($x->fixed == '1') {
-
 
134
                                $fixed++;
-
 
135
                                $this->addVerboseMessage("Fixed issue found at $domain: $submission", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
-
 
136
                                $this->setStatus(VNag::STATUS_OK);
132
                        if ($fake_fix = $this->is_ignored($this->extract_id_from_url($submission))) $x->fixed = '1';
137
                        } else if ($this->is_ignored($this->extract_id_from_url($submission))) {
133
 
-
 
134
                        if ($x->fixed == '0') {
138
                                $unfixed_ignored++;
-
 
139
                                $this->addVerboseMessage("Ignored issue found at $domain: $submission", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
-
 
140
                                $this->setStatus(VNag::STATUS_OK);
-
 
141
                        } else {
135
                                $unfixed++;
142
                                $unfixed++;
136
                                $this->addVerboseMessage("Unfixed issue found at $domain: $submission", VNag::VERBOSITY_SUMMARY);
143
                                $this->addVerboseMessage("Unfixed issue found at $domain: $submission", VNag::VERBOSITY_SUMMARY);
137
                                $this->setStatus(VNag::STATUS_WARNING);
144
                                $this->setStatus(VNag::STATUS_WARNING);
138
                                // TODO: Unlike the "private" API, the "normal" API does not show if a bug is disclosed (= critical instead of warning)
145
                                // TODO: Unlike the "private" API, the "normal" API does not show if a bug is disclosed (= critical instead of warning)
139
                                //       But we could check if the report is older than XXX months, and then we know that it must be disclosed.
146
                                //       But we could check if the report is older than XXX months, and then we know that it must be disclosed.
140
                        }
147
                        }
141
 
148
 
142
                        if ($x->fixed == '1') {
-
 
143
                                $fixed++;
-
 
144
                                $tmp = $fake_fix ? ' (fix asserted by operator)' : '';
-
 
145
                                $this->addVerboseMessage("Fixed issue found at $domain: $submission$tmp", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
-
 
146
                                $this->setStatus(VNag::STATUS_OK);
-
 
147
                        }
-
 
148
                }
149
                }
149
 
150
 
150
                return array($fixed, $unfixed);
151
                return array($fixed, $unfixed, $unfixed_ignored);
151
        }
152
        }
152
 
153
 
153
        function get_privateapi_data($url, $max_cache_time = 3600) { // TODO: make cache time configurable via config
154
        function get_privateapi_data($url, $max_cache_time = 3600) { // TODO: make cache time configurable via config
154
                $url = strtolower($url);
155
                $url = strtolower($url);
155
                $cache_file = $this->get_cache_dir() . '/' . md5($url);
156
                $cache_file = $this->get_cache_dir() . '/' . md5($url);
Line 173... Line 174...
173
                //assert(!empty($this->argPrivateAPI->getValue()));
174
                //assert(!empty($this->argPrivateAPI->getValue()));
174
 
175
 
175
                $sum_fixed = 0;
176
                $sum_fixed = 0;
176
                $sum_unfixed_pending = 0;
177
                $sum_unfixed_pending = 0;
177
                $sum_unfixed_disclosed = 0;
178
                $sum_unfixed_disclosed = 0;
-
 
179
                $sum_unfixed_ignored = 0;
178
 
180
 
179
                $this->setStatus(VNag::STATUS_OK);
181
                $this->setStatus(VNag::STATUS_OK);
180
 
182
 
181
                $ary = $this->get_privateapi_data($privateapi, $max_cache_time);
183
                $ary = $this->get_privateapi_data($privateapi, $max_cache_time);
182
                foreach ($ary as $id => $data) {
184
                foreach ($ary as $id => $data) {
Line 194... Line 196...
194
                        if (empty($data['Vulnerability Reported'])) throw new Exception("This is probably not a correct Private API URL, or the service is down (Missing fields in structure)");
196
                        if (empty($data['Vulnerability Reported'])) throw new Exception("This is probably not a correct Private API URL, or the service is down (Missing fields in structure)");
195
 
197
 
196
                        $status = isset($data['Patch Status']) ? $data['Patch Status'] : $data['Path Status']; // sic! There is a typo in their API (reported, but not fixed)
198
                        $status = isset($data['Patch Status']) ? $data['Patch Status'] : $data['Path Status']; // sic! There is a typo in their API (reported, but not fixed)
197
 
199
 
198
                        $submission = $data['Report Url'];
200
                        $submission = $data['Report Url'];
199
                        if ($fake_fix = $this->is_ignored($this->extract_id_from_url($submission))) $status = 'Patched';
-
 
200
 
-
 
201
                        $domain = $data['Host'];
201
                        $domain = $data['Host'];
202
 
202
 
203
                        if ($status == 'Patched') {
203
                        if ($status == 'Patched') {
204
                                $sum_fixed++;
204
                                $sum_fixed++;
205
                                $fixed_date = $fake_fix ? 'asserted by operator' : $data['Vulnerability Fixed'];
205
                                $fixed_date = $data['Vulnerability Fixed'];
206
                                $this->addVerboseMessage("Fixed issue found at $domain: $submission (fixed: $fixed_date)", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
206
                                $this->addVerboseMessage("Fixed issue found at $domain: $submission (fixed: $fixed_date)", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
207
                                $this->setStatus(VNag::STATUS_OK);
207
                                $this->setStatus(VNag::STATUS_OK);
-
 
208
                        } else if ($this->is_ignored($this->extract_id_from_url($submission))) {
-
 
209
                                $sum_unfixed_ignored++;
-
 
210
                                $this->addVerboseMessage("Ignored issue found at $domain: $submission", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
-
 
211
                                $this->setStatus(VNag::STATUS_OK);
208
                        } else {
212
                        } else {
209
                                $disclosure = $data['Scheduled Public Disclosure'];
213
                                $disclosure = $data['Scheduled Public Disclosure'];
210
                                $time = strtotime(str_replace(',', '', $disclosure));
214
                                $time = strtotime(str_replace(',', '', $disclosure));
211
                                if (time() > $time) {
215
                                if (time() > $time) {
212
                                        $sum_unfixed_disclosed++;
216
                                        $sum_unfixed_disclosed++;
Line 218... Line 222...
218
                                        $this->setStatus(VNag::STATUS_WARNING);
222
                                        $this->setStatus(VNag::STATUS_WARNING);
219
                                }
223
                                }
220
                        }
224
                        }
221
                }
225
                }
222
 
226
 
223
                return array($sum_fixed, $sum_unfixed_pending, $sum_unfixed_disclosed);
227
                return array($sum_fixed, $sum_unfixed_pending, $sum_unfixed_disclosed, $sum_unfixed_ignored);
224
        }
228
        }
225
 
229
 
226
        protected function cbRun($optional_args=array()) {
230
        protected function cbRun($optional_args=array()) {
227
                $domain = $this->argDomain->getValue();
231
                $domain = $this->argDomain->getValue();
228
                $privateapi = $this->argPrivateAPI->getValue();
232
                $privateapi = $this->argPrivateAPI->getValue();
Line 239... Line 243...
239
                        // Possibility 1: Private API (showing all bugs for all of your domains, with detailled information)
243
                        // Possibility 1: Private API (showing all bugs for all of your domains, with detailled information)
240
                        //                https://www.openbugbounty.org/api/2/.../
244
                        //                https://www.openbugbounty.org/api/2/.../
241
                        $sum_fixed = 0;
245
                        $sum_fixed = 0;
242
                        $sum_unfixed_pending = 0;
246
                        $sum_unfixed_pending = 0;
243
                        $sum_unfixed_disclosed = 0;
247
                        $sum_unfixed_disclosed = 0;
244
                        list($sum_fixed, $sum_unfixed_pending, $sum_unfixed_disclosed) = $this->num_open_bugs_v2($privateapi);
-
 
245
                        if ($this->getVerbosityLevel() == VNag::VERBOSITY_SUMMARY) {
248
                        $sum_unfixed_ignored = 0;
246
                                $this->setHeadline(($sum_unfixed_pending + $sum_unfixed_disclosed)." unfixed ($sum_unfixed_pending pending, $sum_unfixed_disclosed disclosed) issues found at your domains", true);
249
                        list($sum_fixed, $sum_unfixed_pending, $sum_unfixed_disclosed, $sum_unfixed_ignored) = $this->num_open_bugs_v2($privateapi);
247
                        } else {
-
 
248
                                $this->setHeadline("$sum_fixed fixed and ".($sum_unfixed_pending + $sum_unfixed_disclosed)." unfixed ($sum_unfixed_pending pending, $sum_unfixed_disclosed disclosed) issues found at your domains", true);
250
                        $this->setHeadline("$sum_fixed fixed and ".($sum_unfixed_pending + $sum_unfixed_disclosed + $sum_unfixed_ignored)." unfixed ($sum_unfixed_pending pending, $sum_unfixed_disclosed disclosed, $sum_unfixed_ignored ignored) issues found at your domain(s)", true);
249
                        }
-
 
250
                } else if (file_exists($domain)) {
251
                } else if (file_exists($domain)) {
251
                        // Possibility 2: File containing a list of domains
252
                        // Possibility 2: File containing a list of domains
252
                        $domains = file($domain);
253
                        $domains = file($domain);
253
                        $sum_fixed = 0;
254
                        $sum_fixed = 0;
254
                        $sum_unfixed = 0;
255
                        $sum_unfixed = 0;
-
 
256
                        $sum_unfixed_ignored = 0;
255
                        $count = 0;
257
                        $count = 0;
256
                        foreach ($domains as $domain) {
258
                        foreach ($domains as $domain) {
257
                                $domain = trim($domain);
259
                                $domain = trim($domain);
258
                                if ($domain == '') continue;
260
                                if ($domain == '') continue;
259
                                if ($domain[0] == '#') continue;
261
                                if ($domain[0] == '#') continue;
260
                                list($fixed, $unfixed) = $this->num_open_bugs_v1($domain);
262
                                list($fixed, $unfixed, $unfixed_ignored) = $this->num_open_bugs_v1($domain);
261
                                $sum_fixed += $fixed;
263
                                $sum_fixed += $fixed;
262
                                $sum_unfixed += $unfixed;
264
                                $sum_unfixed += $unfixed;
-
 
265
                                $sum_unfixed_ignored += $unfixed_ignored;
263
                                $count++;
266
                                $count++;
264
                                $this->addVerboseMessage("$fixed fixed and $unfixed unfixed issues found at $domain", $unfixed > 0 ? VNag::VERBOSITY_SUMMARY : VNag::VERBOSITY_ADDITIONAL_INFORMATION);
267
                                $this->addVerboseMessage("$fixed fixed, $unfixed_ignored ignored, and $unfixed unfixed issues found at $domain", $unfixed > 0 ? VNag::VERBOSITY_SUMMARY : VNag::VERBOSITY_ADDITIONAL_INFORMATION);
265
                        }
-
 
266
                        if ($this->getVerbosityLevel() == VNag::VERBOSITY_SUMMARY) {
-
 
267
                                $this->setHeadline("$sum_unfixed unfixed issues found at $count domains", true);
-
 
268
                        } else {
-
 
269
                                $this->setHeadline("$sum_fixed fixed and $sum_unfixed unfixed issues found at $count domains", true);
-
 
270
                        }
268
                        }
-
 
269
                        $this->setHeadline("$sum_fixed fixed and ".($sum_unfixed + $sum_unfixed_ignored)." unfixed (including $sum_unfixed_ignored ignored) issues found at $count domains", true);
271
                } else if (strpos($domain, ',') !== false) {
270
                } else if (strpos($domain, ',') !== false) {
272
                        // Possibility 3: Domains separated with comma
271
                        // Possibility 3: Domains separated with comma
273
                        $domains = explode(',', $domain);
272
                        $domains = explode(',', $domain);
274
                        $sum_fixed = 0;
273
                        $sum_fixed = 0;
275
                        $sum_unfixed = 0;
274
                        $sum_unfixed = 0;
-
 
275
                        $sum_unfixed_ignored = 0;
276
                        $count = 0;
276
                        $count = 0;
277
                        foreach ($domains as $domain) {
277
                        foreach ($domains as $domain) {
278
                                list($fixed, $unfixed) = $this->num_open_bugs_v1($domain);
278
                                list($fixed, $unfixed, $unfixed_ignored) = $this->num_open_bugs_v1($domain);
279
                                $sum_fixed += $fixed;
279
                                $sum_fixed += $fixed;
280
                                $sum_unfixed += $unfixed;
280
                                $sum_unfixed += $unfixed;
-
 
281
                                $sum_unfixed_ignored += $unfixed_ignored;
281
                                $count++;
282
                                $count++;
282
                                $this->addVerboseMessage("$fixed fixed and $unfixed unfixed issues found at $domain", $unfixed > 0 ? VNag::VERBOSITY_SUMMARY : VNag::VERBOSITY_ADDITIONAL_INFORMATION);
283
                                $this->addVerboseMessage("$fixed fixed, $unfixed_ignored ignored,  and $unfixed unfixed issues found at $domain", $unfixed > 0 ? VNag::VERBOSITY_SUMMARY : VNag::VERBOSITY_ADDITIONAL_INFORMATION);
283
                        }
-
 
284
                        if ($this->getVerbosityLevel() == VNag::VERBOSITY_SUMMARY) {
-
 
285
                                $this->setHeadline("$sum_unfixed unfixed issues found at $count domains", true);
-
 
286
                        } else {
-
 
287
                                $this->setHeadline("$sum_fixed fixed and $sum_unfixed unfixed issues found at $count domains", true);
-
 
288
                        }
284
                        }
-
 
285
                        $this->setHeadline("$sum_fixed fixed and ".($sum_unfixed + $sum_unfixed_ignored)." unfixed (including $sum_unfixed_ignored ignored) issues found at $count domains", true);
289
                } else {
286
                } else {
290
                        // Possibility 4: Single domain
287
                        // Possibility 4: Single domain
291
                        list($fixed, $unfixed) = $this->num_open_bugs_v1($domain);
288
                        list($sum_fixed, $sum_unfixed, $sum_unfixed_ignored) = $this->num_open_bugs_v1($domain);
292
                        if ($this->getVerbosityLevel() == VNag::VERBOSITY_SUMMARY) {
-
 
293
                                $this->setHeadline("$unfixed unfixed issues found at $domain", true);
-
 
294
                        } else {
-
 
295
                                $this->setHeadline("$fixed fixed and $unfixed unfixed issues found at $domain", true);
289
                        $this->setHeadline("$sum_fixed fixed and ".($sum_unfixed + $sum_unfixed_ignored)." unfixed (including $sum_unfixed_ignored ignored) issues found at $domain", true);
296
                        }
-
 
297
                }
290
                }
298
        }
291
        }
299
}
292
}
300
 
293