Detect web technologies, frameworks, and CMS.
| 9 | |
| 10 | class TechDetector(OSINTModule): |
| 11 | """Detect web technologies, frameworks, and CMS.""" |
| 12 | |
| 13 | name = "tech_detect" |
| 14 | description = "Identify web technologies, frameworks, and CMS platforms" |
| 15 | |
| 16 | SIGNATURES = { |
| 17 | "WordPress": { |
| 18 | "headers": {"x-powered-by": r"WordPress"}, |
| 19 | "body": [r"/wp-content/", r"/wp-includes/", r"wp-json"], |
| 20 | "meta": [r'name="generator" content="WordPress'], |
| 21 | }, |
| 22 | "Drupal": { |
| 23 | "headers": {"x-generator": r"Drupal", "x-drupal-cache": r".*"}, |
| 24 | "body": [r"/sites/default/files/", r"Drupal.settings"], |
| 25 | }, |
| 26 | "Joomla": { |
| 27 | "body": [r"/media/jui/", r"/administrator/"], |
| 28 | "meta": [r'name="generator" content="Joomla'], |
| 29 | }, |
| 30 | "React": {"body": [r"react\.production\.min\.js", r"_reactRootContainer"]}, |
| 31 | "Vue.js": {"body": [r"vue\.min\.js", r"vue\.runtime", r"__VUE__"]}, |
| 32 | "Angular": {"body": [r"ng-version=", r"angular\.min\.js"]}, |
| 33 | "nginx": {"headers": {"server": r"nginx"}}, |
| 34 | "Apache": {"headers": {"server": r"Apache"}}, |
| 35 | "IIS": {"headers": {"server": r"Microsoft-IIS"}}, |
| 36 | "Cloudflare": {"headers": {"server": r"cloudflare", "cf-ray": r".*"}}, |
| 37 | "PHP": {"headers": {"x-powered-by": r"PHP"}}, |
| 38 | "ASP.NET": {"headers": {"x-powered-by": r"ASP\.NET"}}, |
| 39 | "Node.js": {"headers": {"x-powered-by": r"Express"}}, |
| 40 | "Laravel": {"body": [r"laravel"], "cookies": ["laravel_session"]}, |
| 41 | "Django": {"body": [r"csrfmiddlewaretoken"], "cookies": ["csrftoken"]}, |
| 42 | } |
| 43 | |
| 44 | async def run(self, target: Target) -> ScanResult: |
| 45 | """Detect technologies used by target.""" |
| 46 | result = self.create_result(target) |
| 47 | url = self._build_url(target) |
| 48 | self.logger.info(f"Detecting technologies for {url}") |
| 49 | |
| 50 | try: |
| 51 | async with HTTPClient() as client: |
| 52 | response = await client.get(url) |
| 53 | headers = {k.lower(): v for k, v in response.headers.items()} |
| 54 | body = response.text |
| 55 | cookies = [c.name for c in response.cookies.jar] |
| 56 | |
| 57 | result.raw_data["url"] = str(response.url) |
| 58 | result.raw_data["status_code"] = response.status_code |
| 59 | |
| 60 | detected = [] |
| 61 | |
| 62 | for tech, sigs in self.SIGNATURES.items(): |
| 63 | if self._check_signatures(sigs, headers, body, cookies): |
| 64 | detected.append(tech) |
| 65 | |
| 66 | result.raw_data["technologies"] = detected |
| 67 | |
| 68 | if detected: |
no outgoing calls
no test coverage detected