| 12547 | return {"Status": " RDAP non disponibile"} |
| 12548 | |
| 12549 | def shodan_host(self, ip): |
| 12550 | key = (self.creds.get("shodan_key") or "").strip() |
| 12551 | if not key: |
| 12552 | return None |
| 12553 | ip = (ip or "").strip() |
| 12554 | if not ip: |
| 12555 | return None |
| 12556 | try: |
| 12557 | url = f"https://api.shodan.io/shodan/host/{urllib.parse.quote(ip, safe='')}" |
| 12558 | r = requests.get(url, params={"key": key}, timeout=10) |
| 12559 | if r.status_code != 200: |
| 12560 | return {"Status": f" Shodan {r.status_code}"} |
| 12561 | j = r.json() |
| 12562 | out = {"Status": " Shodan OK"} |
| 12563 | if j.get("org"): out["Org"] = str(j.get("org")) |
| 12564 | if j.get("isp"): out["ISP"] = str(j.get("isp")) |
| 12565 | if j.get("asn"): out["ASN"] = str(j.get("asn")) |
| 12566 | if j.get("os"): out["OS"] = str(j.get("os")) |
| 12567 | if j.get("ports"): out["Ports"] = ", ".join([str(p) for p in j.get("ports", [])][:50]) |
| 12568 | if j.get("hostnames"): out["Hostnames"] = ", ".join(j.get("hostnames", [])[:20]) |
| 12569 | if j.get("domains"): out["Domains"] = ", ".join(j.get("domains", [])[:20]) |
| 12570 | if j.get("tags"): out["Tags"] = ", ".join(j.get("tags", [])[:20]) |
| 12571 | if j.get("vulns"): |
| 12572 | vul = j.get("vulns") |
| 12573 | if isinstance(vul, dict): |
| 12574 | out["Vulns"] = ", ".join(list(vul.keys())[:20]) |
| 12575 | elif isinstance(vul, list): |
| 12576 | out["Vulns"] = ", ".join([str(x) for x in vul][:20]) |
| 12577 | if j.get("last_update"): out["Last Update"] = str(j.get("last_update")) |
| 12578 | if j.get("country_name") or j.get("city"): |
| 12579 | out["Geo"] = ", ".join([x for x in [j.get("city"), j.get("country_name")] if x]) |
| 12580 | return out |
| 12581 | except Exception as e: |
| 12582 | return {"Status": f" Shodan error: {e}"} |
| 12583 | |
| 12584 | def build_ip_graph(self, domain): |
| 12585 | domain = self._domain_only(domain) |