swagger/scan/passive/
auth.rs

1use 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    ///Rule fucntion
11    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    //Checks for auth existance and type and alerts if non existant or basic
38    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    //Checks if the function uses the authentication scheme, and if the auth scheme is basic
63    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}