def check_version(banner: str, raw: str, url: str) -> List[Result]: results = [] if not banner.startswith("PHP/"): return [] # we've got a PHP version results.append( Result( f"PHP Version Exposed: {banner}", Vulnerabilities.HTTP_PHP_VERSION_EXPOSED, url, raw, ) ) # parse the version, and get the latest version - see if the server is up to date ver = cast(version.Version, version.parse(banner.split("/")[1])) curr_version = version_checker.get_latest_version("php", ver) if curr_version is not None and curr_version > ver: results.append( Result( f"PHP Outdated: {ver} - Current: {curr_version}", Vulnerabilities.SERVER_PHP_OUTDATED, url, raw, ) ) return results
def identify(url: str) -> Tuple[Union[str, None], List[Result]]: results = [] # find WordPress res, path = _identify_by_path(url, "") if path is None: res, path = _identify_by_path(url, "blog/") # check to see if we have a valid hit if path is not None: # we have a WordPress install, let's see if we can get a version body = res.text ver = "Unknown" # this works for modern versions m = re.search(r"login.min.css\?ver=\d+\.\d+\.?\d*", body) if m: ver = m.group(0).split("=")[1] else: # the current method doesn't work, fall back to an older method m = re.search(r"load-styles.php\?[\w,;=&%]+;ver=\d+\.\d+\.?\d*", body) if m: ver = m.group(0).split("=")[-1] # report that we found WordPress results.append( Result.from_evidence( Evidence.from_response(res, {"version": ver}), f"Found WordPress v{ver} at {path}", Vulnerabilities.APP_WORDPRESS_VERSION, ) ) # is this a current version? ver = cast(version.Version, version.parse(ver)) curr_version = version_checker.get_latest_version("wordpress", ver) if curr_version is not None and curr_version > ver: results.append( Result.from_evidence( Evidence.from_response( res, { "installed_version": str(ver), "current_verison": str(curr_version), }, ), f"WordPress Outdated: {ver} - Current: {curr_version}", Vulnerabilities.APP_WORDPRESS_OUTDATED, ) ) return path, results else: return None, []
def check_banner(banner: str, raw: str, url: str) -> List[Result]: if not banner.startswith("nginx"): return [] results: List[Result] = [] if "/" in banner: # we've got a Nginx version results.append( Result( f"Nginx Version Exposed: {banner}", Vulnerabilities.HTTP_BANNER_NGINX_VERSION, url, { "response": raw, "banner": banner }, )) # parse the version, and get the latest version - see if the server is up to date ver = cast(version.Version, version.parse(banner.split("/")[1])) curr_version = version_checker.get_latest_version("nginx", ver) if curr_version is not None and curr_version > ver: results.append( Result( f"Nginx Outdated: {ver} - Current: {curr_version}", Vulnerabilities.SERVER_NGINX_OUTDATED, url, { "response": raw, "banner": banner }, )) else: # this means that it's just a generic banner, with no info results.append( Result( "Generic Nginx Server Banner Found", Vulnerabilities.HTTP_BANNER_GENERIC_NGINX, url, { "response": raw, "banner": banner }, )) return results
def _check_version_outdated(ver: str, url: str, body: str) -> List[Result]: results: List[Result] = [] # parse the version, and get the latest version - see if the server is up to date ver = cast(version.Version, version.parse(ver)) curr_version = version_checker.get_latest_version("apache_tomcat", ver) if curr_version is not None and curr_version > ver: results.append( Result( f"Apache Tomcat Outdated: {ver} - Current: {curr_version}", Vulnerabilities.SERVER_TOMCAT_OUTDATED, url, [ver, curr_version, body], )) return results
def check_version(banner: str, raw: str, url: str, headers: Dict) -> List[Result]: results: List[Result] = [] if not banner.startswith("Microsoft-IIS/"): return results # we've got an IIS version results.append( Result( f"IIS Version Exposed: {banner}", Vulnerabilities.HTTP_BANNER_IIS_VERSION, url, raw, ) ) # parse the version, and get the latest version - see if the server is up to date ver = cast(version.Version, version.parse(banner.split("/")[1])) curr_version = version_checker.get_latest_version("iis", ver) if curr_version is not None and curr_version > ver: results.append( Result( f"IIS Outdated: {ver} - Current: {curr_version}", Vulnerabilities.SERVER_IIS_OUTDATED, url, raw, ) ) # IIS servers may expose a couple other versions, related to ASP.NET, check for those if "X-AspNetMvc-Version" in headers: results.append( Result( f'ASP.NET MVC Version Exposed: {headers["X-AspNetMvc-Version"]}', Vulnerabilities.HTTP_HEADER_X_ASPNETMVC_VERSION, url, raw, ) ) ver = cast(version.Version, version.parse(headers["X-AspNetMvc-Version"])) curr_version = version_checker.get_latest_version("aspnet_mvc", ver) if curr_version is not None and curr_version > ver: results.append( Result( f"ASP.NET MVC Outdated: {ver} - Current: {curr_version}", Vulnerabilities.SERVER_ASPNETMVC_OUTDATED, url, raw, ) ) if "X-AspNet-Version" in headers: results.append( Result( f'ASP.NET CLR Version Exposed: {headers["X-AspNet-Version"]}', Vulnerabilities.HTTP_HEADER_X_ASPNET_VERSION, url, raw, ) ) ver = cast(version.Version, version.parse(headers["X-AspNet-Version"])) curr_version = version_checker.get_latest_version("aspnet", ver) if curr_version is not None and curr_version > ver: results.append( Result( f"ASP.NET Outdated: {ver} - Current: {curr_version}", Vulnerabilities.SERVER_ASPNET_OUTDATED, url, raw, ) ) return results
def check_banner(banner: str, raw: str, url: str) -> List[Result]: # don't bother if this doesn't look like Apache if "Apache" not in banner or "Apache-" in banner: return [] results = [] if "/" in banner: # this means that we have a version modules = banner.split(" ") # double check that we have a '/' in the first part if "/" in modules[0]: # we have a version results.append( Result( f"Apache Server Version Exposed: {modules[0]}", Vulnerabilities.HTTP_BANNER_APACHE_VERSION, url, raw, )) # parse the version, and get the latest version - see if the server is up to date ver = cast(version.Version, version.parse(modules[0].split("/")[1])) curr_version = version_checker.get_latest_version( "apache_httpd", ver) if curr_version is not None and curr_version > ver: results.append( Result( f"Apache Server Outdated: {ver} - Current: {curr_version}", Vulnerabilities.SERVER_APACHE_OUTDATED, url, raw, )) # check to see what else we have if len(modules) > 1: if modules[1].startswith("("): # this is a distro string, garbage modules.remove(modules[1]) for module in modules: if module.startswith("PHP/"): results += php.check_version(module, raw, url) if module.startswith("OpenSSL/"): results.append( Result( f"OpenSSL Version Exposed: {module}", Vulnerabilities.HTTP_BANNER_OPENSSL_VERSION, url, raw, )) else: # this means that it's just a generic 'Apache' banner, with no info results.append( Result( "Generic Apache Server Banner Found", Vulnerabilities.HTTP_BANNER_GENERIC_APACHE, url, raw, )) return results