1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use super::*;
use crate::scan::active::*;
use crate::scan::passive::*;
use comfy_table::*;
use strum_macros::EnumIter;
impl Default for PassiveChecks {
fn default() -> Self {
Self::CheckServerUrl(vec![])
}
}
pub trait Check {
fn alerts_text(&self) -> Cell;
fn top_severity(&self) -> Level;
fn result(&self) -> &'static str;
}
impl Check for PassiveChecks {
fn alerts_text(&self) -> Cell {
match self.inner().len() {
0 => Cell::new(self.inner().len())
.fg(Color::Green)
.add_attribute(Attribute::Bold),
1..=10 => Cell::new(self.inner().len())
.fg(Color::Yellow)
.add_attribute(Attribute::Bold),
11..=99 => Cell::new(self.inner().len())
.fg(Color::Red)
.add_attribute(Attribute::Bold),
_ => Cell::new(self.inner().len())
.fg(Color::Red)
.add_attribute(Attribute::Bold)
.add_attribute(Attribute::SlowBlink),
}
}
fn top_severity(&self) -> Level {
let mut top = Level::Info;
for alert in self.inner() {
if alert.level > top {
top = alert.level;
}
}
top
}
fn result(&self) -> &'static str {
if self.inner().is_empty() {
"PASSED"
} else {
"FAILED"
}
}
}
impl Check for ActiveChecks {
fn alerts_text(&self) -> Cell {
match self.inner().len() {
0 => Cell::new(self.inner().len())
.fg(Color::Green)
.add_attribute(Attribute::Bold),
1..=10 => Cell::new(self.inner().len())
.fg(Color::Yellow)
.add_attribute(Attribute::Bold),
11..=99 => Cell::new(self.inner().len())
.fg(Color::Red)
.add_attribute(Attribute::Bold),
_ => Cell::new(self.inner().len())
.fg(Color::Red)
.add_attribute(Attribute::Bold)
.add_attribute(Attribute::SlowBlink),
}
}
fn top_severity(&self) -> Level {
let mut top = Level::Info;
for alert in self.inner() {
if alert.level > top {
top = alert.level;
}
}
top
}
fn result(&self) -> &'static str {
if !self.inner().is_empty() {
"FAILED"
} else {
"PASSED"
}
}
}
impl_passive_checks![
(CheckServerUrl,check_server_url,"SERVER URL","Checks for server url misconfigurations"),
(CheckAdditionalProperties,check_additional_properties,"ADDITIONAL PROPERTIES","Checks for bad defaults in object additional properties, alerts if the swagger is using the default configuration"),
(CheckDefaultResponse,check_default_response,"DEFAULT RESPONSE","Checks for the definition of a default response, and alerts if none is defined"),
(CheckResponseBodySchema,check_response_body_schema,"RESPONSE BODY SCHEMA","Checks the response body schema, and alerts when there is none"),
(CheckDefaultType,check_default_type,"DEFAULT TYPE","Checks that the default type is the same as the parameter type"),
(CheckEnumType,check_enum_type,"ENUM TYPE","Checks that the Enum type is the same as the parameter type"),
(CheckUnusedSchema,check_unused_schema,"UNUSED SCHEMA","Checks for unused schemas"),
(Check401,check_401,"401","Checks for a 401 response if there is authentication necessary"),
(Check403,check_403,"403","Checks for a 403 response if there is authentication necessary"),
(CheckSuccesses,check_successes,"RESPONSE SUCCESSES (2xx)","Checks for successful responses (2xx) in every operation"),
(CheckAuth,check_auth,"AUTH","Checks for a global authentication definition"),
(CheckFNAuth,check_fn_auth,"ENDPOINT AUTH","Checks for an authentication definition for each endpoint"),
(CheckIntAttrs,check_int_attrs,"INTEGER ATTRIBUTES","Checks for the definition of integer type attributes - maximum, minimum"),
(CheckStrAttrs,check_str_attrs,"STRING ATTRIBUTES","Checks for the definition of string type attributes - max_length, min_length, pattern"),
(CheckArrAttrs,check_arr_attrs,"ARRAY ATTRIBUTES","Checks for the definition of array type attributes - max_items, min_items"),
(CheckObjAttrs,check_obj_attrs,"OBJECT ATTRIBUTES","Checks for the definition of object type attributes - max_properties, properties"),
(CheckValidResponses,check_valid_responses,"VALID RESPONSES","Checks for valid responses codes"),
(CheckMethodPermissions, check_method_permissions, "METHOD PERMISSIONS", "Checks for correct permission configuration for GET/PUT/POST requests"),
(CheckContainsOperation, check_contains_operation, "CONTAINS OPERATION", "Checks that each path contains at least one operation"),
(CheckValidEncodings, check_valid_encoding, "VALID ENCODINGS", "Checks that all content types are valid"),
(CheckDescription, check_description, "DESCRIPTION", "Checks that all operations have a description"),
(CheckContainsResponse, check_contains_response, "CONTAINS RESPONSE", "Checks that each operation has a response")
];
impl_active_checks![
(CheckMinMax,check_min_max,is_2xx,"NUMBER LIMITS ENFORCED","checks that the api enforces the number limits in the OAS"),
(CheckOpenRedirect,check_open_redirect,is_2xx,"OPEN REDIRECT","Check if the API may be vulnerable to open redirect"),
(CheckStringMaxLength,check_string_length_max,is_2xx,"STRING LENGTH ENFORCED","check that the api validate the String length"),
(CheckParameterPollution,check_parameter_pollution,reflected_and_2xx,"PARAMETER POLLUTION","Check if the endpoint is vulnerable to http pollution"),
(CheckSSL,check_ssl,is_2xx,"SSL ENFORCED","Check if the connection is secure"),
(CheckMethodPermissionsActive,check_method_permissions_active,is_2xx,"METHOD PERMISSION","Check if the endpoint is correctly configured")
];