Lucene search
K

SSL Labs API Client

🗓️ 31 Aug 2024 00:00:00Reported by Denis Kolegov, Francois Chagnon, metasploit.comType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 258 Views

SSL Labs API Client for Metasploit. This module provides an interface to interact with the SSL Labs API for assessing SSL configurations and vulnerabilities. The class includes methods for requesting information, performing analysis, and retrieving endpoint data

Related
Code
ReporterTitlePublishedViews
Family
IBM Security Bulletins
Security Bulletin: IBM Sterling Connect:Enterprise for UNIX affected by the following OpenSSL vulnerability (CVE-2014-0224).
18 Dec 201901:14
ibm
IBM Security Bulletins
Security Bulletin: Tivoli Common Reporting iFixes for multiple Security Vulnerabilities (CVE-2014-3566,CVE-2014-6145,CVE-2014-1568,CVE-2014-4263,CVE-2014-3513,CVE-2014-3567,CVE-2014-3568,CVE-2014-0107,CVE-2014-0075,CVE-2014-0096,CVE-2014-0099,CVE-2014-011
17 Jun 201814:55
ibm
IBM Security Bulletins
Security Bulletin: Security vulnerabilities have been identified in IBM WebSphere MQ (CVE-2014-0224, CVE-2014-3470), Websphere Message Broker and IBM Integration Bus (CVE-2014-0224) shipped with Predictive Maintenance and Quality
15 Jun 201822:33
ibm
IBM Security Bulletins
Security Bulletins for IBM Tealeaf Customer Experience offerings
16 Jun 201819:35
ibm
IBM Security Bulletins
IBM Security Network Protection / IBM QRadar Network Security / XGS Technote Index
31 Jan 202100:10
ibm
IBM Security Bulletins
Security Bulletin: IBM Systems Director is affected by vulnerabilities in OpenSSL (CVE-2014-0224, CVE-2013-0169 and CVE-2014-3470)
31 Jan 201901:25
ibm
IBM Security Bulletins
Security Bulletins - IBM Planning Analytics, Cognos TM1 and Cognos Insight
18 Jul 201817:37
ibm
IBM Security Bulletins
Security Bulletin: Rational ClearCase is affected by OpenSSL vulnerabilities (CVE-2014-0224, CVE-2014-3470, CVE-2015-0292)
10 Jul 201808:34
ibm
IBM Security Bulletins
Security Bulletin:Security vulnerability has been identified in Rational Application Developer shipped with Rational Software Architect for Websphere (CVE-2014-0224, CVE-2014-0221, CVE-2014-0195, CVE-2014-0198, CVE-2010-5298, CVE-2014-3470)
17 Jun 201804:55
ibm
IBM Security Bulletins
Security Bulletin: IBM System x Integrated Management Module (IMM) is affected by the following OpenSSL vulnerabilities: CVE-2014-0224, CVE-2014-0076
31 Jan 201901:25
ibm
Rows per page
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
require 'active_support/inflector'  
require 'json'  
require 'active_support/core_ext/hash'  
  
class MetasploitModule < Msf::Auxiliary  
class InvocationError < StandardError; end  
class RequestRateTooHigh < StandardError; end  
class InternalError < StandardError; end  
class ServiceNotAvailable < StandardError; end  
class ServiceOverloaded < StandardError; end  
  
class Api  
attr_reader :max_assessments, :current_assessments  
  
def initialize  
@max_assessments = 0  
@current_assessments = 0  
end  
  
def request(name, params = {})  
api_host = "api.ssllabs.com"  
api_port = "443"  
api_path = "/api/v2/"  
user_agent = "Msf_ssllabs_scan"  
  
name = name.to_s.camelize(:lower)  
uri = api_path + name  
cli = Rex::Proto::Http::Client.new(api_host, api_port, {}, true, 'TLS')  
cli.connect  
req = cli.request_cgi({  
'uri' => uri,  
'agent' => user_agent,  
'method' => 'GET',  
'vars_get' => params  
})  
res = cli.send_recv(req)  
cli.close  
  
if res && res.code.to_i == 200  
@max_assessments = res.headers['X-Max-Assessments']  
@current_assessments = res.headers['X-Current-Assessments']  
r = JSON.load(res.body)  
fail InvocationError, "API returned: #{r['errors']}" if r.key?('errors')  
return r  
end  
  
case res.code.to_i  
when 400  
fail InvocationError  
when 429  
fail RequestRateTooHigh  
when 500  
fail InternalError  
when 503  
fail ServiceNotAvailable  
when 529  
fail ServiceOverloaded  
else  
fail StandardError, "HTTP error code #{r.code}", caller  
end  
end  
  
def report_unused_attrs(type, unused_attrs)  
unused_attrs.each do | attr |  
# $stderr.puts "#{type} request returned unknown parameter #{attr}"  
end  
end  
  
def info  
obj, unused_attrs = Info.load request(:info)  
report_unused_attrs('info', unused_attrs)  
obj  
end  
  
def analyse(params = {})  
obj, unused_attrs = Host.load request(:analyze, params)  
report_unused_attrs('analyze', unused_attrs)  
obj  
end  
  
def get_endpoint_data(params = {})  
obj, unused_attrs = Endpoint.load request(:get_endpoint_data, params)  
report_unused_attrs('get_endpoint_data', unused_attrs)  
obj  
end  
  
def get_status_codes  
obj, unused_attrs = StatusCodes.load request(:get_status_codes)  
report_unused_attrs('get_status_codes', unused_attrs)  
obj  
end  
end  
  
class ApiObject  
  
class << self;  
attr_accessor :all_attributes  
attr_accessor :fields  
attr_accessor :lists  
attr_accessor :refs  
end  
  
def self.inherited(base)  
base.all_attributes = []  
base.fields = []  
base.lists = {}  
base.refs = {}  
end  
  
def self.to_api_name(name)  
name.to_s.gsub(/\?$/, '').camelize(:lower)  
end  
  
def self.to_attr_name(name)  
name.to_s.gsub(/\?$/, '').underscore  
end  
  
def self.field_methods(name)  
is_bool = name.to_s.end_with?('?')  
attr_name = to_attr_name(name)  
api_name = to_api_name(name)  
class_eval <<-EOF, __FILE__, __LINE__  
def #{attr_name}#{'?' if is_bool}  
@#{api_name}  
end  
def #{attr_name}=(value)  
@#{api_name} = value  
end  
EOF  
end  
  
def self.has_fields(*names)  
names.each do |name|  
@all_attributes << to_api_name(name)  
@fields << to_api_name(name)  
field_methods(name)  
end  
end  
  
def self.has_objects_list(name, klass)  
@all_attributes << to_api_name(name)  
@lists[to_api_name(name)] = klass  
field_methods(name)  
end  
  
def self.has_object_ref(name, klass)  
@all_attributes << to_api_name(name)  
@refs[to_api_name(name)] = klass  
field_methods(name)  
end  
  
def self.load(attributes = {})  
obj = self.new  
unused_attrs = []  
attributes.each do |name, value|  
if @fields.include?(name)  
obj.instance_variable_set("@#{name}", value)  
elsif @lists.key?(name)  
unless value.nil?  
var = value.map do |v|  
val, ua = @lists[name].load(v)  
unused_attrs.concat ua  
val  
end  
obj.instance_variable_set("@#{name}", var)  
end  
elsif @refs.key?(name)  
unless value.nil?  
val, ua = @refs[name].load(value)  
unused_attrs.concat ua  
obj.instance_variable_set("@#{name}", val)  
end  
else  
unused_attrs << name  
end  
end  
return obj, unused_attrs  
end  
  
def to_json(opts = {})  
obj = {}  
self.class.all_attributes.each do |api_name|  
v = instance_variable_get("@#{api_name}")  
obj[api_name] = v  
end  
obj.to_json  
end  
end  
  
class Cert < ApiObject  
has_fields :subject,  
:commonNames,  
:altNames,  
:notBefore,  
:notAfter,  
:issuerSubject,  
:sigAlg,  
:issuerLabel,  
:revocationInfo,  
:crlURIs,  
:ocspURIs,  
:revocationStatus,  
:crlRevocationStatus,  
:ocspRevocationStatus,  
:sgc?,  
:validationType,  
:issues,  
:sct?,  
:mustStaple,  
:sha1Hash,  
:pinSha256  
  
def valid?  
issues == 0  
end  
  
def invalid?  
!valid?  
end  
end  
  
class ChainCert < ApiObject  
has_fields :subject,  
:label,  
:notBefore,  
:notAfter,  
:issuerSubject,  
:issuerLabel,  
:sigAlg,  
:issues,  
:keyAlg,  
:keySize,  
:keyStrength,  
:revocationStatus,  
:crlRevocationStatus,  
:ocspRevocationStatus,  
:raw,  
:sha1Hash,  
:pinSha256  
  
def valid?  
issues == 0  
end  
  
def invalid?  
!valid?  
end  
end  
  
class Chain < ApiObject  
has_objects_list :certs, ChainCert  
has_fields :issues  
  
def valid?  
issues == 0  
end  
  
def invalid?  
!valid?  
end  
end  
  
class Key < ApiObject  
has_fields :size,  
:strength,  
:alg,  
:debianFlaw?,  
:q  
  
def insecure?  
debian_flaw? || q == 0  
end  
  
def secure?  
!insecure?  
end  
end  
  
class Protocol < ApiObject  
has_fields :id,  
:name,  
:version,  
:v2SuitesDisabled?,  
:q  
  
def insecure?  
q == 0  
end  
  
def secure?  
!insecure?  
end  
  
end  
  
class Info < ApiObject  
has_fields :engineVersion,  
:criteriaVersion,  
:clientMaxAssessments,  
:maxAssessments,  
:currentAssessments,  
:messages,  
:newAssessmentCoolOff  
end  
  
class SimClient < ApiObject  
has_fields :id,  
:name,  
:platform,  
:version,  
:isReference?  
end  
  
class Simulation < ApiObject  
has_object_ref :client, SimClient  
has_fields :errorCode,  
:attempts,  
:protocolId,  
:suiteId,  
:kxInfo  
  
def success?  
error_code == 0  
end  
  
def error?  
!success?  
end  
end  
  
class SimDetails < ApiObject  
has_objects_list :results, Simulation  
end  
  
class StatusCodes < ApiObject  
has_fields :statusDetails  
  
def [](name)  
status_details[name]  
end  
end  
  
class Suite < ApiObject  
has_fields :id,  
:name,  
:cipherStrength,  
:dhStrength,  
:dhP,  
:dhG,  
:dhYs,  
:ecdhBits,  
:ecdhStrength,  
:q  
  
def insecure?  
q == 0  
end  
  
def secure?  
!insecure?  
end  
end  
  
class Suites < ApiObject  
has_objects_list :list, Suite  
has_fields :preference?  
end  
  
class EndpointDetails < ApiObject  
has_fields :hostStartTime  
has_object_ref :key, Key  
has_object_ref :cert, Cert  
has_object_ref :chain, Chain  
has_objects_list :protocols, Protocol  
has_object_ref :suites, Suites  
has_fields :serverSignature,  
:prefixDelegation?,  
:nonPrefixDelegation?,  
:vulnBeast?,  
:renegSupport,  
:stsResponseHeader,  
:stsMaxAge,  
:stsSubdomains?,  
:pkpResponseHeader,  
:sessionResumption,  
:compressionMethods,  
:supportsNpn?,  
:npnProtocols,  
:sessionTickets,  
:ocspStapling?,  
:staplingRevocationStatus,  
:staplingRevocationErrorMessage,  
:sniRequired?,  
:httpStatusCode,  
:httpForwarding,  
:supportsRc4?,  
:forwardSecrecy,  
:rc4WithModern?  
has_object_ref :sims, SimDetails  
has_fields :heartbleed?,  
:heartbeat?,  
:openSslCcs,  
:poodle?,  
:poodleTls,  
:fallbackScsv?,  
:freak?,  
:hasSct,  
:stsStatus,  
:stsPreload,  
:supportsAlpn,  
:rc4Only,  
:protocolIntolerance,  
:miscIntolerance,  
:openSSLLuckyMinus20,  
:logjam,  
:chaCha20Preference,  
:hstsPolicy,  
:hstsPreloads,  
:hpkpPolicy,  
:hpkpRoPolicy,  
:drownHosts,  
:drownErrors,  
:drownVulnerable  
end  
  
class Endpoint < ApiObject  
has_fields :ipAddress,  
:serverName,  
:statusMessage,  
:statusDetails,  
:statusDetailsMessage,  
:grade,  
:gradeTrustIgnored,  
:hasWarnings?,  
:isExceptional?,  
:progress,  
:duration,  
:eta,  
:delegation  
has_object_ref :details, EndpointDetails  
end  
  
class Host < ApiObject  
has_fields :host,  
:port,  
:protocol,  
:isPublic?,  
:status,  
:statusMessage,  
:startTime,  
:testTime,  
:engineVersion,  
:criteriaVersion,  
:cacheExpiryTime  
has_objects_list :endpoints, Endpoint  
has_fields :certHostnames  
end  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'SSL Labs API Client',  
'Description' => %q{  
This module is a simple client for the SSL Labs APIs, designed for  
SSL/TLS assessment during a penetration test.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Denis Kolegov <dnkolegov[at]gmail.com>',  
'Francois Chagnon' # ssllab.rb author (https://github.com/Shopify/ssllabs.rb)  
],  
'DefaultOptions' =>  
{  
'RPORT' => 443,  
'SSL' => true,  
}  
))  
register_options(  
[  
OptString.new('HOSTNAME', [true, 'The target hostname']),  
OptInt.new('DELAY', [true, 'The delay in seconds between API requests', 5]),  
OptBool.new('USECACHE', [true, 'Use cached results (if available), else force live scan', true]),  
OptBool.new('GRADE', [true, 'Output only the hostname: grade', false]),  
OptBool.new('IGNOREMISMATCH', [true, 'Proceed with assessments even when the server certificate doesn\'t match the assessment hostname', true])  
])  
end  
  
def report_good(line)  
print_good line  
end  
  
def report_warning(line)  
print_warning line  
end  
  
def report_bad(line)  
print_warning line  
end  
  
def report_status(line)  
print_status line  
end  
  
def output_endpoint_data(r)  
ssl_protocols = [  
{ id: 771, name: "TLS", version: "1.2", secure: true, active: false },  
{ id: 770, name: "TLS", version: "1.1", secure: true, active: false },  
{ id: 769, name: "TLS", version: "1.0", secure: true, active: false },  
{ id: 768, name: "SSL", version: "3.0", secure: false, active: false },  
{ id: 2, name: "SSL", version: "2.0", secure: false, active: false }  
]  
  
report_status "-----------------------------------------------------------------"  
report_status "Report for #{r.server_name} (#{r.ip_address})"  
report_status "-----------------------------------------------------------------"  
  
case r.grade.to_s  
when "A+", "A", "A-"  
report_good "Overall rating: #{r.grade}"  
when "B"  
report_warning "Overall rating: #{r.grade}"  
when "C", "D", "E", "F"  
report_bad "Overall rating: #{r.grade}"  
when "M"  
report_bad "Overall rating: #{r.grade} - Certificate name mismatch"  
when "T"  
report_bad "Overall rating: #{r.grade} - Server's certificate is not trusted"  
end  
  
report_warning "Grade is #{r.grade_trust_ignored}, if trust issues are ignored)" if r.grade.to_s != r.grade_trust_ignored.to_s  
  
# Supported protocols  
r.details.protocols.each do |i|  
p = ssl_protocols.detect { |x| x[:id] == i.id }  
p.store(:active, true) if p  
end  
  
ssl_protocols.each do |proto|  
if proto[:active]  
if proto[:secure]  
report_good "#{proto[:name]} #{proto[:version]} - Yes"  
else  
report_bad "#{proto[:name]} #{proto[:version]} - Yes"  
end  
else  
report_good "#{proto[:name]} #{proto[:version]} - No"  
end  
end  
  
# Renegotiation  
case  
when r.details.reneg_support == 0  
report_warning "Secure renegotiation is not supported"  
when r.details.reneg_support[0] == 1  
report_bad "Insecure client-initiated renegotiation is supported"  
when r.details.reneg_support[1] == 1  
report_good "Secure renegotiation is supported"  
when r.details.reneg_support[2] == 1  
report_warning "Secure client-initiated renegotiation is supported"  
when r.details.reneg_support[3] == 1  
report_warning "Server requires secure renegotiation support"  
end  
  
# BEAST  
if r.details.vuln_beast?  
report_bad "BEAST attack - Yes"  
else  
report_good "BEAST attack - No"  
end  
  
# POODLE (SSLv3)  
if r.details.poodle?  
report_bad "POODLE SSLv3 - Vulnerable"  
else  
report_good "POODLE SSLv3 - Not vulnerable"  
end  
  
# POODLE TLS  
case r.details.poodle_tls  
when -1  
report_warning "POODLE TLS - Test failed"  
when 0  
report_warning "POODLE TLS - Unknown"  
when 1  
report_good "POODLE TLS - Not vulnerable"  
when 2  
report_bad "POODLE TLS - Vulnerable"  
end  
  
# Downgrade attack prevention  
if r.details.fallback_scsv?  
report_good "Downgrade attack prevention - Yes, TLS_FALLBACK_SCSV supported"  
else  
report_bad "Downgrade attack prevention - No, TLS_FALLBACK_SCSV not supported"  
end  
  
# Freak  
if r.details.freak?  
report_bad "Freak - Vulnerable"  
else  
report_good "Freak - Not vulnerable"  
end  
  
# RC4  
if r.details.supports_rc4?  
report_warning "RC4 - Server supports at least one RC4 suite"  
else  
report_good "RC4 - No"  
end  
  
# RC4 with modern browsers  
report_warning "RC4 is used with modern clients" if r.details.rc4_with_modern?  
  
# Heartbeat  
if r.details.heartbeat?  
report_status "Heartbeat (extension) - Yes"  
else  
report_status "Heartbeat (extension) - No"  
end  
  
# Heartbleed  
if r.details.heartbleed?  
report_bad "Heartbleed (vulnerability) - Yes"  
else  
report_good "Heartbleed (vulnerability) - No"  
end  
  
# OpenSSL CCS  
case r.details.open_ssl_ccs  
when -1  
report_warning "OpenSSL CCS vulnerability (CVE-2014-0224) - Test failed"  
when 0  
report_warning "OpenSSL CCS vulnerability (CVE-2014-0224) - Unknown"  
when 1  
report_good "OpenSSL CCS vulnerability (CVE-2014-0224) - No"  
when 2  
report_bad "OpenSSL CCS vulnerability (CVE-2014-0224) - Possibly vulnerable, but not exploitable"  
when 3  
report_bad "OpenSSL CCS vulnerability (CVE-2014-0224) - Vulnerable and exploitable"  
end  
  
# Forward Secrecy  
case  
when r.details.forward_secrecy == 0  
report_bad "Forward Secrecy - No"  
when r.details.forward_secrecy[0] == 1  
report_bad "Forward Secrecy - With some browsers"  
when r.details.forward_secrecy[1] == 1  
report_good "Forward Secrecy - With modern browsers"  
when r.details.forward_secrecy[2] == 1  
report_good "Forward Secrecy - Yes (with most browsers)"  
end  
  
# HSTS  
if r.details.sts_response_header  
str = "Strict Transport Security (HSTS) - Yes"  
if r.details.sts_max_age && r.details.sts_max_age != -1  
str += ":max-age=#{r.details.sts_max_age}"  
end  
str += ":includeSubdomains" if r.details.sts_subdomains?  
report_good str  
else  
report_bad "Strict Transport Security (HSTS) - No"  
end  
  
# HPKP  
if r.details.pkp_response_header  
report_good "Public Key Pinning (HPKP) - Yes"  
else  
report_warning "Public Key Pinning (HPKP) - No"  
end  
  
# Compression  
if r.details.compression_methods == 0  
report_good "Compression - No"  
elsif (r.details.session_tickets & 1) != 0  
report_warning "Compression - Yes (Deflate)"  
end  
  
# Session Resumption  
case r.details.session_resumption  
when 0  
print_status "Session resumption - No"  
when 1  
report_warning "Session resumption - No (IDs assigned but not accepted)"  
when 2  
print_status "Session resumption - Yes"  
end  
  
# Session Tickets  
case  
when r.details.session_tickets == 0  
print_status "Session tickets - No"  
when r.details.session_tickets[0] == 1  
print_status "Session tickets - Yes"  
when r.details.session_tickets[1] == 1  
report_good "Session tickets - Implementation is faulty"  
when r.details.session_tickets[2] == 1  
report_warning "Session tickets - Server is intolerant to the extension"  
end  
  
# OCSP stapling  
if r.details.ocsp_stapling?  
print_status "OCSP Stapling - Yes"  
else  
print_status "OCSP Stapling - No"  
end  
  
# NPN  
if r.details.supports_npn?  
print_status "Next Protocol Negotiation (NPN) - Yes (#{r.details.npn_protocols})"  
else  
print_status "Next Protocol Negotiation (NPN) - No"  
end  
  
# SNI  
print_status "SNI Required - Yes" if r.details.sni_required?  
end  
  
def output_grades_only(r)  
r.endpoints.each do |e|  
if e.status_message == "Ready"  
print_status "Server: #{e.server_name} (#{e.ip_address}) - Grade:#{e.grade}"  
else  
print_status "Server: #{e.server_name} (#{e.ip_address} - Status:#{e.status_message}"  
end  
end  
end  
  
def output_common_info(r)  
return unless r  
print_status "Host: #{r.host}"  
  
r.endpoints.each do |e|  
print_status "\t #{e.ip_address}"  
end  
end  
  
def output_result(r, grade)  
return unless r  
output_common_info(r)  
if grade  
output_grades_only(r)  
else  
r.endpoints.each do |e|  
if e.status_message == "Ready"  
output_endpoint_data(e)  
else  
print_status "#{e.status_message}"  
end  
end  
end  
end  
  
def output_testing_details(r)  
return unless r.status == "IN_PROGRESS"  
  
if r.endpoints.length == 1  
print_status "#{r.host} (#{r.endpoints[0].ip_address}) - Progress #{[r.endpoints[0].progress, 0].max}% (#{r.endpoints[0].status_details_message})"  
elsif r.endpoints.length > 1  
in_progress_srv_num = 0  
ready_srv_num = 0  
pending_srv_num = 0  
r.endpoints.each do |e|  
case e.status_message.to_s  
when "In progress"  
in_progress_srv_num += 1  
print_status "Scanned host: #{e.ip_address} (#{e.server_name})- #{[e.progress, 0].max}% complete (#{e.status_details_message})"  
when "Pending"  
pending_srv_num += 1  
when "Ready"  
ready_srv_num += 1  
end  
end  
progress = ((ready_srv_num.to_f / (pending_srv_num + in_progress_srv_num + ready_srv_num)) * 100.0).round(0)  
print_status "Ready: #{ready_srv_num}, In progress: #{in_progress_srv_num}, Pending: #{pending_srv_num}"  
print_status "#{r.host} - Progress #{progress}%"  
end  
end  
  
def valid_hostname?(hostname)  
hostname =~ /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/  
end  
  
def run  
delay = datastore['DELAY']  
hostname = datastore['HOSTNAME']  
unless valid_hostname?(hostname)  
print_status "Invalid hostname"  
return  
end  
  
usecache = datastore['USECACHE']  
grade = datastore['GRADE']  
  
# Use cached results  
if usecache  
from_cache = 'on'  
start_new = 'off'  
else  
from_cache = 'off'  
start_new = 'on'  
end  
  
# Ignore mismatch  
ignore_mismatch = datastore['IGNOREMISMATCH'] ? 'on' : 'off'  
  
api = Api.new  
info = api.info  
print_status "SSL Labs API info"  
print_status "API version: #{info.engine_version}"  
print_status "Evaluation criteria: #{info.criteria_version}"  
print_status "Running assessments: #{info.current_assessments} (max #{info.max_assessments})"  
  
if api.current_assessments >= api.max_assessments  
print_status "Too many active assessments"  
return  
end  
  
if usecache  
r = api.analyse(host: hostname, fromCache: from_cache, ignoreMismatch: ignore_mismatch, all: 'done')  
else  
r = api.analyse(host: hostname, startNew: start_new, ignoreMismatch: ignore_mismatch, all: 'done')  
end  
  
loop do  
case r.status  
when "DNS"  
print_status "Server: #{r.host} - #{r.status_message}"  
when "IN_PROGRESS"  
output_testing_details(r)  
when "READY"  
output_result(r, grade)  
return  
when "ERROR"  
print_error "#{r.status_message}"  
return  
else  
print_error "Unknown assessment status"  
return  
end  
sleep delay  
r = api.analyse(host: hostname, all: 'done')  
end  
  
rescue RequestRateTooHigh  
print_error "Request rate is too high, please slow down"  
rescue InternalError  
print_error "Service encountered an error, sleep 5 minutes"  
rescue ServiceNotAvailable  
print_error "Service is not available, sleep 15 minutes"  
rescue ServiceOverloaded  
print_error "Service is overloaded, sleep 30 minutes"  
rescue  
print_error "Invalid parameters"  
end  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

31 Aug 2024 00:00Current
7.5High risk
Vulners AI Score7.5
CVSS 25.8
CVSS 3.17.4
EPSS0.89694
258