| 212 | # ------------------------------------------------------------------ |
| 213 | |
| 214 | def check_ssl(self) -> list: |
| 215 | checks = [ |
| 216 | { |
| 217 | "id": "SSL_TRUST_ALL_CERTS", |
| 218 | "title": "Trust-All SSL Certificate Implementation", |
| 219 | "severity": "CRITICAL", |
| 220 | "owasp": "M5: Insecure Communication", |
| 221 | "description": ( |
| 222 | "Custom TrustManager that trusts all certificates disables SSL " |
| 223 | "validation entirely. Any certificate — including self-signed, " |
| 224 | "expired, or from a malicious CA — will be accepted, enabling MITM." |
| 225 | ), |
| 226 | "pattern": r'TrustAllCerts|ALLOW_ALL_HOSTNAME_VERIFIER|trustAllCerts|TrustAll', |
| 227 | }, |
| 228 | { |
| 229 | "id": "SSL_HOSTNAME_ALL", |
| 230 | "title": "HostnameVerifier Accepts Any Hostname", |
| 231 | "severity": "CRITICAL", |
| 232 | "owasp": "M5: Insecure Communication", |
| 233 | "description": ( |
| 234 | "A HostnameVerifier that always returns true bypasses hostname " |
| 235 | "verification. An attacker with any valid certificate can intercept " |
| 236 | "traffic destined for the real server." |
| 237 | ), |
| 238 | "pattern": r'verify\s*\(.*\)\s*\{[^}]*return\s+true|HostnameVerifier.*return\s+true', |
| 239 | }, |
| 240 | { |
| 241 | "id": "SSL_INSECURE_SOCKET", |
| 242 | "title": "Insecure SSLSocketFactory", |
| 243 | "severity": "CRITICAL", |
| 244 | "owasp": "M5: Insecure Communication", |
| 245 | "description": ( |
| 246 | "SSLSocketFactory.getInsecure() or equivalent creates a socket " |
| 247 | "factory that does not validate server certificates." |
| 248 | ), |
| 249 | "pattern": r'SSLSocketFactory\.getInsecure|TLS_ALLOW_ALL', |
| 250 | }, |
| 251 | { |
| 252 | "id": "SSL_LEGACY_SSL", |
| 253 | "title": "Legacy SSL Protocol in Use", |
| 254 | "severity": "MEDIUM", |
| 255 | "owasp": "M5: Insecure Communication", |
| 256 | "description": ( |
| 257 | 'SSLContext.getInstance("SSL") enables SSLv3 which is vulnerable ' |
| 258 | "to POODLE and other attacks. Use TLSv1.2 or TLSv1.3 explicitly." |
| 259 | ), |
| 260 | "pattern": r'SSLContext\.getInstance\s*\(\s*["\']SSL["\']', |
| 261 | }, |
| 262 | { |
| 263 | "id": "SSL_WEAK_TRUSTMANAGER", |
| 264 | "title": "Empty or Permissive TrustManager", |
| 265 | "severity": "CRITICAL", |
| 266 | "owasp": "M5: Insecure Communication", |
| 267 | "description": ( |
| 268 | "An X509TrustManager with an empty checkServerTrusted() method " |
| 269 | "accepts all server certificates without validation." |
| 270 | ), |
| 271 | "pattern": r'X509TrustManager|checkServerTrusted|checkClientTrusted', |