swagger/scan/passive/
auth.rs1use super::*;
2
3pub trait PassiveAuthScan {
4 fn check_401(&self) -> Vec<Alert>;
5 fn check_403(&self) -> Vec<Alert>;
6 fn check_auth(&self) -> Vec<Alert>;
7 fn check_fn_auth(&self) -> Vec<Alert>;
8}
9impl<T: OAS + Serialize> PassiveAuthScan for PassiveSwaggerScan<T> {
10 fn check_401(&self) -> Vec<Alert> {
12 let mut alerts = vec![];
13 for (path, method, p_sec, resps) in get_path_responses(&self.swagger) {
14 if resps.get("401").is_none() && !p_sec.is_empty() {
15 alerts.push(Alert::new(
16 Level::Low,
17 "Operation has security defined, but no 401 response defined",
18 format!("swagger root path:{} method:{}", path, method),
19 ));
20 }
21 }
22 alerts
23 }
24 fn check_403(&self) -> Vec<Alert> {
25 let mut alerts = vec![];
26 for (path, method, p_sec, resps) in get_path_responses(&self.swagger) {
27 if resps.get("403").is_none() && !p_sec.is_empty() {
28 alerts.push(Alert::new(
29 Level::Low,
30 "Operation has security defined, but no 403 response defined",
31 format!("swagger root path:{} method:{}", path, method),
32 ));
33 }
34 }
35 alerts
36 }
37 fn check_auth(&self) -> Vec<Alert> {
39 let mut alerts = vec![];
40 if let Some(sec_schemes) = get_auth(&self.swagger) {
41 for (s_name, s_scheme) in sec_schemes {
42 let scheme = s_scheme.inner(&self.swagger_value);
43 if let Some(s) = scheme.scheme {
44 if s == "basic" {
45 alerts.push(Alert::new(
46 Level::High,
47 "The API uses BASIC authentication, which is highly unrecommended",
48 format!("swagger root components scheme:{}", s_name),
49 ));
50 }
51 }
52 }
53 } else {
54 alerts.push(Alert::new(
55 Level::Medium,
56 "The API doesn't have authentication defined",
57 "swagger root components".to_string(),
58 ));
59 }
60 alerts
61 }
62 fn check_fn_auth(&self) -> Vec<Alert> {
64 let mut alerts = vec![];
65 let general_auths: HashMap<String, SecScheme> = if let Some(auths) = get_auth(&self.swagger)
66 {
67 auths
68 .iter()
69 .map(|(s, r)| (s.clone(), r.inner(&self.swagger_value)))
70 .collect()
71 } else {
72 return vec![];
73 };
74 for (path, item) in &self.swagger.get_paths() {
75 for (m, op) in item.get_ops() {
76 let secs = if let Some(s) = &op.security {
77 s.iter().flat_map(|v| v.keys()).collect()
78 } else {
79 vec![]
80 };
81 if secs.is_empty() {
82 alerts.push(Alert::new(
83 Level::Medium,
84 "Endpoint does not use any security scheme",
85 format!("swagger root path:{} method:{}", path, m),
86 ));
87 continue;
88 }
89 for sec in secs {
90 if let Some(scheme) = general_auths.get(sec) {
91 if let Some(s) = &scheme.scheme {
92 if s == "basic" {
93 alerts.push(Alert::new(Level::High,"The API uses BASIC authentication, which is highly unrecommended",format!("swagger root path:{} method:{} scheme:{}",path,m,sec)));
94 }
95 }
96 } else {
97 alerts.push(Alert::new(
98 Level::Medium,
99 "Endpoint with a security scheme that does not exist",
100 format!("swagger root path:{} method:{}", path, m),
101 ));
102 }
103 }
104 }
105 }
106 alerts
107 }
108}