qualys 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -2
- data/.rubocop.yml +7 -0
- data/.rubocop_todo.yml +71 -0
- data/.travis.yml +13 -1
- data/Gemfile +3 -1
- data/Gemfile.lock +91 -0
- data/README.md +50 -10
- data/Rakefile +3 -4
- data/lib/qualys.rb +10 -11
- data/lib/qualys/api.rb +38 -47
- data/lib/qualys/auth.rb +11 -20
- data/lib/qualys/compliance.rb +3 -7
- data/lib/qualys/config.rb +3 -5
- data/lib/qualys/host.rb +17 -0
- data/lib/qualys/report.rb +90 -0
- data/lib/qualys/scans.rb +10 -22
- data/lib/qualys/version.rb +1 -1
- data/lib/qualys/vulnerability.rb +74 -0
- data/qualys.gemspec +18 -19
- data/spec/fixtures/vcr_cassettes/api_get.yml +52 -0
- data/spec/fixtures/vcr_cassettes/create_global_report.yml +68 -0
- data/spec/fixtures/vcr_cassettes/emptyscans.yml +35 -0
- data/spec/fixtures/vcr_cassettes/get.yml +107 -0
- data/spec/fixtures/vcr_cassettes/global_report.yml +17800 -0
- data/spec/fixtures/vcr_cassettes/load_global_report.yml +625 -0
- data/spec/fixtures/vcr_cassettes/login.yml +50 -0
- data/spec/fixtures/vcr_cassettes/logout.yml +50 -0
- data/spec/fixtures/vcr_cassettes/scan.yml +73 -0
- data/spec/fixtures/vcr_cassettes/scans.yml +89 -0
- data/spec/fixtures/vcr_cassettes/templates.yml +121 -0
- data/spec/fixtures/vcr_cassettes/try_load_not_existing_report.yml +63 -0
- data/spec/fixtures/vcr_cassettes/unlogged.yml +45 -0
- data/spec/fixtures/vcr_cassettes/wrong.yml +101 -0
- data/spec/qualys/api_spec.rb +27 -0
- data/spec/qualys/report_spec.rb +65 -0
- data/spec/qualys/scans_spec.rb +75 -0
- data/spec/qualys/version_spec.rb +11 -0
- data/spec/qualys/vulnerability_spec.rb +53 -0
- data/spec/qualys_spec.rb +20 -0
- data/spec/spec_helper.rb +37 -0
- metadata +61 -15
- data/.rock.yml +0 -17
- data/lib/qualys/reports.rb +0 -47
data/lib/qualys/auth.rb
CHANGED
@@ -6,37 +6,28 @@ module Qualys
|
|
6
6
|
|
7
7
|
# Do Login
|
8
8
|
def self.login
|
9
|
-
|
10
9
|
# Request a login
|
11
|
-
response =
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
})
|
18
|
-
|
10
|
+
response = api_post('/session/', body: {
|
11
|
+
action: 'login',
|
12
|
+
username: Qualys::Config.username,
|
13
|
+
password: Qualys::Config.password
|
14
|
+
})
|
15
|
+
|
19
16
|
# set the session key
|
20
17
|
Qualys::Config.session_key = response.header['Set-Cookie']
|
21
18
|
true
|
22
|
-
|
23
19
|
end
|
24
20
|
|
25
21
|
# Set Logout
|
26
22
|
def self.logout
|
27
|
-
|
28
23
|
# Request a login
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
})
|
34
|
-
|
24
|
+
api_post('/session/', body: {
|
25
|
+
action: 'logout'
|
26
|
+
})
|
27
|
+
|
35
28
|
# set the session key
|
36
29
|
Qualys::Config.session_key = nil
|
37
30
|
true
|
38
|
-
|
39
31
|
end
|
40
|
-
|
41
32
|
end
|
42
|
-
end
|
33
|
+
end
|
data/lib/qualys/compliance.rb
CHANGED
@@ -1,21 +1,17 @@
|
|
1
1
|
module Qualys
|
2
2
|
class Compliance < Api
|
3
|
-
|
4
3
|
def self.all
|
5
|
-
response = api_get(
|
4
|
+
response = api_get('/compliance/control/', query: { action: 'list' })
|
6
5
|
|
7
|
-
unless response.parsed_response['<COMPLIANCE_SCAN_RESULT_OUTPUT']['RESPONSE'].
|
6
|
+
unless response.parsed_response['<COMPLIANCE_SCAN_RESULT_OUTPUT']['RESPONSE'].key? 'COMPLIANCE_SCAN'
|
8
7
|
return []
|
9
8
|
end
|
10
9
|
|
11
10
|
response.parsed_response['COMPLIANCE_SCAN_RESULT_OUTPUT']['RESPONSE']['COMPLIANCE_SCAN']
|
12
|
-
|
13
11
|
end
|
14
12
|
|
15
13
|
def self.each
|
16
|
-
|
14
|
+
all
|
17
15
|
end
|
18
|
-
|
19
16
|
end
|
20
|
-
|
21
17
|
end
|
data/lib/qualys/config.rb
CHANGED
@@ -26,10 +26,8 @@ module Qualys
|
|
26
26
|
#
|
27
27
|
# @param [ String ] path The path to the file.
|
28
28
|
def load!(path)
|
29
|
-
settings = YAML.
|
30
|
-
if settings.is_a? Hash
|
31
|
-
from_hash(settings)
|
32
|
-
end
|
29
|
+
settings = YAML.safe_load(ERB.new(File.new(path).read).result)['api']
|
30
|
+
from_hash(settings) if settings.is_a? Hash
|
33
31
|
end
|
34
32
|
end
|
35
|
-
end
|
33
|
+
end
|
data/lib/qualys/host.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Qualys
|
4
|
+
# a scanned target
|
5
|
+
class Host
|
6
|
+
attr_accessor :ip, :tracking_method, :dns, :operating_system, :vuln_info_list, :vulnerabilities
|
7
|
+
|
8
|
+
def initialize(host, vulnerabilities = nil)
|
9
|
+
@ip = host['IP']
|
10
|
+
@tracking_method = host['TRACKING_METHOD']
|
11
|
+
@dns = host['DNS']
|
12
|
+
@operating_system = host['OPERATING_SYSTEM']
|
13
|
+
@vuln_info_list = host['VULN_INFO_LIST']
|
14
|
+
@vulnerabilities = vulnerabilities
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Qualys
|
4
|
+
# Qualys reports
|
5
|
+
class Report < Api
|
6
|
+
attr_accessor :header, :host_list, :glossary, :appendices
|
7
|
+
|
8
|
+
# accepted timeout in seconds
|
9
|
+
TIMEOUT = 60.0
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def find_by_id(id)
|
13
|
+
response = api_get('/report/', query: {
|
14
|
+
action: 'fetch',
|
15
|
+
id: id
|
16
|
+
})
|
17
|
+
|
18
|
+
# check if report exist
|
19
|
+
return unless response.parsed_response.keys.include?('ASSET_DATA_REPORT')
|
20
|
+
|
21
|
+
Report.new(response.parsed_response)
|
22
|
+
end
|
23
|
+
|
24
|
+
# returns the list of the templates
|
25
|
+
def templates
|
26
|
+
auth = { username: Qualys::Config.username, password: Qualys::Config.password }
|
27
|
+
response = HTTParty.get('https://qualysapi.qualys.eu/msp/report_template_list.php',
|
28
|
+
basic_auth: auth)
|
29
|
+
response.parsed_response['REPORT_TEMPLATE_LIST']['REPORT_TEMPLATE']
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete(id)
|
33
|
+
api_post('/report/', query: {
|
34
|
+
action: 'delete',
|
35
|
+
id: id
|
36
|
+
})
|
37
|
+
end
|
38
|
+
|
39
|
+
# returns the id of the report
|
40
|
+
def create_global_report
|
41
|
+
scan_template = templates.detect { |template| template['TITLE'] == 'Technical Report' }
|
42
|
+
response = api_post('/report/', query: {
|
43
|
+
action: 'launch',
|
44
|
+
report_title: 'Generated_by_Ruby_Qualys_gem',
|
45
|
+
report_type: 'Scan',
|
46
|
+
output_format: 'xml',
|
47
|
+
template_id: scan_template['ID']
|
48
|
+
})
|
49
|
+
|
50
|
+
response.parsed_response['SIMPLE_RETURN']['RESPONSE']['ITEM_LIST']['ITEM']['VALUE']
|
51
|
+
end
|
52
|
+
|
53
|
+
# returns a report global report object.
|
54
|
+
# This method can be time consuming and times out after 64 s
|
55
|
+
def global_report
|
56
|
+
report_id = create_global_report
|
57
|
+
report = find_by_id(report_id)
|
58
|
+
|
59
|
+
10.times do
|
60
|
+
sleep(TIMEOUT / 10)
|
61
|
+
report = find_by_id(report_id)
|
62
|
+
break unless report.nil?
|
63
|
+
end
|
64
|
+
|
65
|
+
raise Qualys::Report::Exception, 'Report generation timed out' if report.nil?
|
66
|
+
|
67
|
+
delete(report_id)
|
68
|
+
report
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialize(report)
|
73
|
+
@header = report['ASSET_DATA_REPORT']['HEADER']
|
74
|
+
@host_list = report['ASSET_DATA_REPORT']['HOST_LIST']['HOST']
|
75
|
+
@glossary = report['ASSET_DATA_REPORT']['GLOSSARY']['VULN_DETAILS_LIST']['VULN_DETAILS']
|
76
|
+
@appendices = report['ASSET_DATA_REPORT']['APPENDICES']
|
77
|
+
end
|
78
|
+
|
79
|
+
def hosts
|
80
|
+
hosts ||= host_list.map do |xml_host|
|
81
|
+
vulnerabilities = xml_host['VULN_INFO_LIST']['VULN_INFO'].map do |vuln|
|
82
|
+
Qualys::Vulnerability.new(vuln, @glossary)
|
83
|
+
end
|
84
|
+
Qualys::Host.new(xml_host, vulnerabilities)
|
85
|
+
end
|
86
|
+
|
87
|
+
hosts
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/qualys/scans.rb
CHANGED
@@ -1,37 +1,28 @@
|
|
1
1
|
module Qualys
|
2
2
|
class Scans < Api
|
3
|
-
|
4
3
|
def self.all
|
5
|
-
response = api_get(
|
6
|
-
unless response.parsed_response['SCAN_LIST_OUTPUT']['RESPONSE'].
|
4
|
+
response = api_get('/scan/', query: { action: 'list' })
|
5
|
+
unless response.parsed_response['SCAN_LIST_OUTPUT']['RESPONSE'].key? 'SCAN_LIST'
|
7
6
|
return []
|
8
7
|
end
|
9
8
|
|
10
9
|
scanlist = response.parsed_response['SCAN_LIST_OUTPUT']['RESPONSE']['SCAN_LIST']['SCAN']
|
11
|
-
scanlist.map!{|scan| Scan.new(scan)}
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.each
|
16
|
-
self.all
|
10
|
+
scanlist.map! { |scan| Scan.new(scan) }
|
17
11
|
end
|
18
12
|
|
19
13
|
def self.get(ref)
|
20
|
-
response = api_get(
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
}} )
|
14
|
+
response = api_get('/scan/', query: {
|
15
|
+
action: 'fetch',
|
16
|
+
scan_ref: ref,
|
17
|
+
mode: 'extended',
|
18
|
+
output_format: 'json'
|
19
|
+
})
|
27
20
|
|
28
21
|
JSON.parse(response.parsed_response)
|
29
22
|
end
|
30
|
-
|
31
23
|
end
|
32
24
|
|
33
25
|
class Scan
|
34
|
-
|
35
26
|
attr_accessor :ref, :title, :type, :date, :duration, :status, :target, :user
|
36
27
|
|
37
28
|
def initialize(scan)
|
@@ -50,15 +41,12 @@ module Qualys
|
|
50
41
|
end
|
51
42
|
|
52
43
|
def finished?
|
53
|
-
if @status.eql? 'Finished'
|
54
|
-
return true
|
55
|
-
end
|
44
|
+
return true if @status.eql? 'Finished'
|
56
45
|
|
57
46
|
false
|
58
47
|
end
|
59
48
|
end
|
60
49
|
|
61
50
|
class Details
|
62
|
-
|
63
51
|
end
|
64
52
|
end
|
data/lib/qualys/version.rb
CHANGED
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Qualys
|
4
|
+
# Qualys vulnerabilities from a report xml
|
5
|
+
class Vulnerability
|
6
|
+
attr_accessor :qid, :type, :port, :service, :protocol, :ssl, :result,
|
7
|
+
:first_found, :last_found, :times_found, :status, :details,
|
8
|
+
:cve_code_list, :title, :severity, :category, :threat, :impact,
|
9
|
+
:solution, :pci_flag, :correlation, :vendor_reference_list, :last_update,
|
10
|
+
:url
|
11
|
+
|
12
|
+
def initialize(vuln, glossary)
|
13
|
+
parse_vuln vuln
|
14
|
+
|
15
|
+
match_details glossary
|
16
|
+
|
17
|
+
parse_cve if @details['CVE_ID_LIST']
|
18
|
+
parse_details
|
19
|
+
# gives the url to the qualys knowledge base for this vulnerabitlty
|
20
|
+
parse_url
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
"#{qid}, #{title}, severity : #{severity}, cves: #{cve_code_list&.join(', ') || 'no cve'}"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def parse_cve
|
30
|
+
cve_xlm_array = if @details['CVE_ID_LIST']['CVE_ID'].is_a?(Array)
|
31
|
+
@details['CVE_ID_LIST']['CVE_ID']
|
32
|
+
else
|
33
|
+
[@details['CVE_ID_LIST']['CVE_ID']]
|
34
|
+
end
|
35
|
+
@cve_code_list = cve_xlm_array.map { |cve| cve['ID'] }
|
36
|
+
end
|
37
|
+
|
38
|
+
# this methods finds the details for this qid in the report's glossary
|
39
|
+
def match_details(glossary)
|
40
|
+
@details = glossary.select { |detail| detail['id'] == @qid }[0]
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse_details
|
44
|
+
@title = @details['TITLE']
|
45
|
+
@severity = @details['SEVERITY']
|
46
|
+
@category = @details['CATEGORY']
|
47
|
+
@threat = @details['THREAT']
|
48
|
+
@impact = @details['IMPACT']
|
49
|
+
@solution = @details['SOLUTION']
|
50
|
+
@pci_flag = @details['PCI_FLAG']
|
51
|
+
@correlation = @details['CORRELATION']
|
52
|
+
@vendor_reference_list = @details['VENDOR_REFERENCE_LIST']
|
53
|
+
@last_update = @details['BUGTRAQ_ID_LIST']
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_url
|
57
|
+
@url = 'https://qualysguard.qualys.eu/fo/common/vuln_info.php?id=' + @qid[4..-1]
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_vuln(vuln)
|
61
|
+
@qid = vuln['QID']['id']
|
62
|
+
@type = vuln['TYPE']
|
63
|
+
@port = vuln['PORT']
|
64
|
+
@service = vuln['SERVICE']
|
65
|
+
@protocol = vuln['PROTOCOL']
|
66
|
+
@ssl = vuln['SSL']
|
67
|
+
@result = vuln['RESULT']
|
68
|
+
@first_found = vuln['FIRST_FOUND']
|
69
|
+
@last_found = vuln['LAST_FOUND']
|
70
|
+
@times_found = vuln['TIMES_FOUND']
|
71
|
+
@status = vuln['VULN_STATUS']
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/qualys.gemspec
CHANGED
@@ -1,37 +1,36 @@
|
|
1
1
|
# Created by hand, like a real man
|
2
2
|
# coding: utf-8
|
3
|
+
|
3
4
|
lib = File.expand_path('../lib', __FILE__)
|
4
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
6
|
require 'qualys/version'
|
6
7
|
|
7
8
|
Gem::Specification.new do |s|
|
8
|
-
|
9
9
|
s.name = 'qualys'
|
10
10
|
s.version = Qualys::VERSION
|
11
|
-
s.date = '
|
12
|
-
s.summary =
|
13
|
-
s.description =
|
14
|
-
s.authors = [
|
11
|
+
s.date = '2017-12-17'
|
12
|
+
s.summary = 'qualys API Client'
|
13
|
+
s.description = 'Easily interface with the qualys for consuming events'
|
14
|
+
s.authors = ['Mike Mackintosh']
|
15
15
|
s.email = 'm@zyp.io'
|
16
16
|
s.homepage =
|
17
17
|
'http://github.com/mikemackintosh/ruby-qualys'
|
18
18
|
|
19
19
|
s.license = 'MIT'
|
20
|
-
|
21
|
-
s.require_paths = [
|
20
|
+
|
21
|
+
s.require_paths = ['lib']
|
22
22
|
s.files = `git ls-files -z`.split("\x0")
|
23
|
-
#s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
24
|
-
|
23
|
+
# s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
24
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
25
25
|
|
26
|
-
s.add_dependency 'json'
|
27
26
|
s.add_dependency 'erubis'
|
28
|
-
s.add_dependency 'httparty'
|
29
|
-
|
30
|
-
s.add_development_dependency "bundler"
|
31
|
-
s.add_development_dependency "rake"
|
32
|
-
s.add_development_dependency "rspec"
|
33
|
-
s.add_development_dependency "vcr"
|
34
|
-
s.add_development_dependency "webmock"
|
35
|
-
s.add_development_dependency "rubocop"
|
27
|
+
s.add_dependency 'httparty', '~> 0.15'
|
28
|
+
s.add_dependency 'json'
|
36
29
|
|
37
|
-
|
30
|
+
s.add_development_dependency 'bundler'
|
31
|
+
s.add_development_dependency 'rake'
|
32
|
+
s.add_development_dependency 'rspec'
|
33
|
+
s.add_development_dependency 'rubocop'
|
34
|
+
s.add_development_dependency 'vcr'
|
35
|
+
s.add_development_dependency 'webmock'
|
36
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://qualysapi.qualys.eu/api/2.0/fo/scan/?action=list
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
response:
|
10
|
+
status:
|
11
|
+
code: 200
|
12
|
+
message: OK
|
13
|
+
body:
|
14
|
+
encoding: UTF-8
|
15
|
+
string: "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE SCAN_LIST_OUTPUT
|
16
|
+
SYSTEM \"https://qualysapi.qualys.eu/api/2.0/fo/scan/scan_list_output.dtd\">\n<!--
|
17
|
+
This report was generated with an evaluation version of Qualys //--> \n<SCAN_LIST_OUTPUT>\n
|
18
|
+
\ <RESPONSE>\n <DATETIME>2017-12-11T12:49:00Z</DATETIME>\n <SCAN_LIST>\n
|
19
|
+
\ <SCAN>\n <REF>scan/XXXX633905.79357</REF>\n <TYPE>On-Demand</TYPE>\n
|
20
|
+
\ <TITLE><![CDATA[shellshock 20171207]]></TITLE>\n <USER_LOGIN>Thomas</USER_LOGIN>\n
|
21
|
+
\ <LAUNCH_DATETIME>2017-12-07T08:05:05Z</LAUNCH_DATETIME>\n <DURATION>00:01:43</DURATION>\n
|
22
|
+
\ <PROCESSING_PRIORITY>0 - No Priority</PROCESSING_PRIORITY>\n <PROCESSED>1</PROCESSED>\n
|
23
|
+
\ <STATUS>\n <STATE>Error</STATE>\n </STATUS>\n <TARGET><![CDATA[47.69.112.62]]></TARGET>\n
|
24
|
+
\ </SCAN>\n <SCAN>\n <REF>scan/1512633883.79354</REF>\n <TYPE>On-Demand</TYPE>\n
|
25
|
+
\ <TITLE><![CDATA[shellshock 20171207]]></TITLE>\n <USER_LOGIN>Thomas</USER_LOGIN>\n
|
26
|
+
\ <LAUNCH_DATETIME>2017-12-07T08:04:43Z</LAUNCH_DATETIME>\n <DURATION>00:07:02</DURATION>\n
|
27
|
+
\ <PROCESSING_PRIORITY>0 - No Priority</PROCESSING_PRIORITY>\n <PROCESSED>1</PROCESSED>\n
|
28
|
+
\ <STATUS>\n <STATE>Finished</STATE>\n </STATUS>\n <TARGET><![CDATA[47.69.112.62]]></TARGET>\n
|
29
|
+
\ </SCAN>\n <SCAN>\n <REF>scan/1512633720.79248</REF>\n <TYPE>On-Demand</TYPE>\n
|
30
|
+
\ <TITLE><![CDATA[shellshock]]></TITLE>\n <USER_LOGIN>Thomas</USER_LOGIN>\n
|
31
|
+
\ <LAUNCH_DATETIME>2017-12-07T08:01:59Z</LAUNCH_DATETIME>\n <DURATION>00:00:06</DURATION>\n
|
32
|
+
\ <PROCESSING_PRIORITY>0 - No Priority</PROCESSING_PRIORITY>\n <PROCESSED>1</PROCESSED>\n
|
33
|
+
\ <STATUS>\n <STATE>Error</STATE>\n </STATUS>\n <TARGET><![CDATA[47.69.112.62]]></TARGET>\n
|
34
|
+
\ </SCAN>\n <SCAN>\n <REF>scan/1512469561.67379</REF>\n <TYPE>On-Demand</TYPE>\n
|
35
|
+
\ <TITLE><![CDATA[test_vuln]]></TITLE>\n <USER_LOGIN>Thomas</USER_LOGIN>\n
|
36
|
+
\ <LAUNCH_DATETIME>2017-12-05T10:26:01Z</LAUNCH_DATETIME>\n <DURATION>00:04:48</DURATION>\n
|
37
|
+
\ <PROCESSING_PRIORITY>1 - Emergency</PROCESSING_PRIORITY>\n <PROCESSED>1</PROCESSED>\n
|
38
|
+
\ <STATUS>\n <STATE>Finished</STATE>\n </STATUS>\n <TARGET><![CDATA[192.168.1.100]]></TARGET>\n
|
39
|
+
\ </SCAN>\n <SCAN>\n <REF>scan/1512466786.67046</REF>\n <TYPE>On-Demand</TYPE>\n
|
40
|
+
\ <TITLE><![CDATA[test]]></TITLE>\n <USER_LOGIN>Thomas</USER_LOGIN>\n
|
41
|
+
\ <LAUNCH_DATETIME>2017-12-05T09:39:46Z</LAUNCH_DATETIME>\n <DURATION>00:07:56</DURATION>\n
|
42
|
+
\ <PROCESSING_PRIORITY>0 - No Priority</PROCESSING_PRIORITY>\n <PROCESSED>1</PROCESSED>\n
|
43
|
+
\ <STATUS>\n <STATE>Finished</STATE>\n </STATUS>\n <TARGET><![CDATA[88.78.187.177]]></TARGET>\n
|
44
|
+
\ </SCAN>\n </SCAN_LIST>\n </RESPONSE>\n</SCAN_LIST_OUTPUT>\n<!--
|
45
|
+
This report was generated with an evaluation version of Qualys //--> \n<!--
|
46
|
+
CONFIDENTIAL AND PROPRIETARY INFORMATION. Qualys provides the QualysGuard
|
47
|
+
Service \"As Is,\" without any warranty of any kind. Qualys makes no warranty
|
48
|
+
that the information contained in this report is complete or error-free. Copyright
|
49
|
+
2017, Qualys, Inc. //--> \n"
|
50
|
+
http_version:
|
51
|
+
recorded_at: Mon, 11 Dec 2017 12:49:00 GMT
|
52
|
+
recorded_with: VCR 4.0.0
|