From 5ae73fea473f66f78b7caddce6220df6f0b22c80 Mon Sep 17 00:00:00 2001 From: pranjalg1331 Date: Tue, 7 Jan 2025 18:31:58 +0530 Subject: [PATCH 01/10] initial Signed-off-by: pranjalg1331 --- .../observable_analyzers/abusewhois.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 api_app/analyzers_manager/observable_analyzers/abusewhois.py diff --git a/api_app/analyzers_manager/observable_analyzers/abusewhois.py b/api_app/analyzers_manager/observable_analyzers/abusewhois.py new file mode 100644 index 0000000000..35b6ffa51a --- /dev/null +++ b/api_app/analyzers_manager/observable_analyzers/abusewhois.py @@ -0,0 +1,21 @@ +# This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl +# See the file 'LICENSE' for copying permission. + + +from api_app.analyzers_manager import classes + + +class AbuseWHOIS(classes.ObservableAnalyzer): + + @classmethod + def update(cls) -> bool: + pass + + def run(self): + """Run the analyzer""" + return None + + @classmethod + def _monkeypatch(cls): + patches = [] + return super()._monkeypatch(patches=patches) From 31e2316de959f58dfa368e6d3a6cbc70f2b2f10b Mon Sep 17 00:00:00 2001 From: pranjalg1331 Date: Thu, 16 Jan 2025 20:49:41 +0530 Subject: [PATCH 02/10] abuse analyzer completed Signed-off-by: pranjalg1331 --- .../observable_analyzers/abusewhois.py | 180 +++++++++++++++++- docker/Dockerfile | 4 +- requirements/project-requirements.txt | 2 +- 3 files changed, 183 insertions(+), 3 deletions(-) diff --git a/api_app/analyzers_manager/observable_analyzers/abusewhois.py b/api_app/analyzers_manager/observable_analyzers/abusewhois.py index 35b6ffa51a..4a4d22bcc9 100644 --- a/api_app/analyzers_manager/observable_analyzers/abusewhois.py +++ b/api_app/analyzers_manager/observable_analyzers/abusewhois.py @@ -2,6 +2,10 @@ # See the file 'LICENSE' for copying permission. +import asyncio + +from abuse_whois import get_abuse_contacts + from api_app.analyzers_manager import classes @@ -11,9 +15,183 @@ class AbuseWHOIS(classes.ObservableAnalyzer): def update(cls) -> bool: pass + def _clean_contact_info(self, contact): + """Remove null values and replace with REDACTED if appropriate""" + if not any(contact.values()): + return {"status": "REDACTED FOR PRIVACY"} + return {k: v for k, v in contact.items() if v is not None} + + def _parse_raw_whois_text(self, raw_text): + """Extract network information from raw WHOIS text""" + info = {} + for line in raw_text.split("\n"): + line = line.strip() + if not line or line.startswith("#"): + continue + + if ":" in line: + key, value = line.split(":", 1) + key = key.strip() + value = value.strip() + if value: + info[key] = value + + return info + + def _format_ip_data(self, result): + """Format IP address WHOIS data""" + raw_info = self._parse_raw_whois_text(result.records.ip_address.raw_text) + + return { + "network": { + "address": result.address, + "hostname": result.hostname, + "ip_address": result.ip_address, + "range": raw_info.get("NetRange"), + "cidr": raw_info.get("CIDR"), + "name": raw_info.get("NetName"), + "type": raw_info.get("NetType"), + "origin_as": raw_info.get("OriginAS"), + }, + "organization": { + "name": raw_info.get("OrgName"), + "id": raw_info.get("OrgId"), + "address": raw_info.get("Address"), + "city": raw_info.get("City"), + "state": raw_info.get("StateProv"), + "postal_code": raw_info.get("PostalCode"), + "country": raw_info.get("Country"), + "registration_date": raw_info.get("RegDate"), + "last_updated": raw_info.get("Updated"), + }, + "contacts": { + "abuse": { + "email": raw_info.get("OrgAbuseEmail"), + "phone": raw_info.get("OrgAbusePhone"), + "name": raw_info.get("OrgAbuseName"), + }, + "technical": { + "email": raw_info.get("OrgTechEmail"), + "phone": raw_info.get("OrgTechPhone"), + "name": raw_info.get("OrgTechName"), + }, + }, + } + + def _format_domain_data(self, result): + """Format domain WHOIS data""" + return { + "domain": { + "name": result.address, + "ip_address": result.ip_address, + "registrar": { + "provider": result.registrar.provider if result.registrar else None, + "email": result.registrar.address if result.registrar else None, + "type": result.registrar.type if result.registrar else None, + }, + }, + "domain_info": { + "nameservers": ( + result.records.domain.name_servers if result.records.domain else [] + ), + "statuses": ( + result.records.domain.statuses if result.records.domain else [] + ), + "expires_at": ( + result.records.domain.expires_at.isoformat() + if result.records.domain and result.records.domain.expires_at + else None + ), + "updated_at": ( + result.records.domain.updated_at.isoformat() + if result.records.domain and result.records.domain.updated_at + else None + ), + }, + "contacts": { + "registrant": self._clean_contact_info( + { + "organization": ( + result.records.domain.registrant.organization + if result.records.domain + else None + ), + "email": ( + result.records.domain.registrant.email + if result.records.domain + else None + ), + "name": ( + result.records.domain.registrant.name + if result.records.domain + else None + ), + "telephone": ( + result.records.domain.registrant.telephone + if result.records.domain + else None + ), + } + ), + "abuse": self._clean_contact_info( + { + "email": ( + result.records.domain.abuse.email + if result.records.domain + else None + ), + "telephone": ( + result.records.domain.abuse.telephone + if result.records.domain + else None + ), + } + ), + "technical": self._clean_contact_info( + { + "organization": ( + result.records.domain.tech.organization + if result.records.domain + else None + ), + "email": ( + result.records.domain.tech.email + if result.records.domain + else None + ), + "name": ( + result.records.domain.tech.name + if result.records.domain + else None + ), + "telephone": ( + result.records.domain.tech.telephone + if result.records.domain + else None + ), + } + ), + }, + } + + async def _get_whois_data(self): + """Get and format WHOIS data""" + result = await get_abuse_contacts(self.observable_name) + + # Determine if this is an IP address or domain lookup and format accordingly + formatted_data = ( + self._format_ip_data(result) + if result.records.domain is None + else self._format_domain_data(result) + ) + + # Remove any remaining null values at the top level + return {k: v for k, v in formatted_data.items() if v is not None} + def run(self): """Run the analyzer""" - return None + report = asyncio.run(self._get_whois_data()) + return report @classmethod def _monkeypatch(cls): diff --git a/docker/Dockerfile b/docker/Dockerfile index e1f7191024..7361375fc6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -52,7 +52,9 @@ WORKDIR $PYTHONPATH RUN pip3 install --no-cache-dir --compile -r project-requirements.txt \ && pip3 install --no-cache-dir pycti==${PYCTI_VERSION} \ - && pip3 install --no-cache-dir --compile -r certego-requirements.txt + && pip3 install --no-cache-dir --compile -r certego-requirements.txt + +RUN pip3 install abuse_whois==0.10.1 COPY . $PYTHONPATH diff --git a/requirements/project-requirements.txt b/requirements/project-requirements.txt index 6f0a5296e2..8c629f9213 100644 --- a/requirements/project-requirements.txt +++ b/requirements/project-requirements.txt @@ -88,7 +88,7 @@ docxpy==0.8.5 pylnk3==0.4.2 androguard==3.4.0a1 # version >=4.x of androguard raises a dependency conflict with quark-engine==25.1.1 wad==0.4.6 - +starlette==0.45.2 # this is required because XLMMacroDeobfuscator does not pin the following packages pyxlsb2==0.0.8 xlrd2==1.3.4 From 625a2a2e673e282b1684a8579c318c4a8b4283fc Mon Sep 17 00:00:00 2001 From: pranjalg1331 Date: Thu, 16 Jan 2025 20:56:57 +0530 Subject: [PATCH 03/10] migration Signed-off-by: pranjalg1331 --- .../0147_analyzer_config_abusewhois.py | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 api_app/analyzers_manager/migrations/0147_analyzer_config_abusewhois.py diff --git a/api_app/analyzers_manager/migrations/0147_analyzer_config_abusewhois.py b/api_app/analyzers_manager/migrations/0147_analyzer_config_abusewhois.py new file mode 100644 index 0000000000..e1df211caa --- /dev/null +++ b/api_app/analyzers_manager/migrations/0147_analyzer_config_abusewhois.py @@ -0,0 +1,125 @@ +from django.db import migrations +from django.db.models.fields.related_descriptors import ( + ForwardManyToOneDescriptor, + ForwardOneToOneDescriptor, + ManyToManyDescriptor, + ReverseManyToOneDescriptor, + ReverseOneToOneDescriptor, +) + +plugin = { + "python_module": { + "health_check_schedule": None, + "update_schedule": None, + "module": "abusewhois.AbuseWHOIS", + "base_path": "api_app.analyzers_manager.observable_analyzers", + }, + "name": "AbuseWhois", + "description": "A Sigma and RDAP/Whois-based abuse contacts finder.", + "disabled": False, + "soft_time_limit": 30, + "routing_key": "default", + "health_check_status": True, + "type": "observable", + "docker_based": False, + "maximum_tlp": "AMBER", + "observable_supported": ["ip", "url", "domain"], + "supported_filetypes": [], + "run_hash": False, + "run_hash_type": "", + "not_supported_filetypes": [], + "mapping_data_model": {}, + "model": "analyzers_manager.AnalyzerConfig", +} + +params = [] + +values = [] + + +def _get_real_obj(Model, field, value): + def _get_obj(Model, other_model, value): + if isinstance(value, dict): + real_vals = {} + for key, real_val in value.items(): + real_vals[key] = _get_real_obj(other_model, key, real_val) + value = other_model.objects.get_or_create(**real_vals)[0] + # it is just the primary key serialized + else: + if isinstance(value, int): + if Model.__name__ == "PluginConfig": + value = other_model.objects.get(name=plugin["name"]) + else: + value = other_model.objects.get(pk=value) + else: + value = other_model.objects.get(name=value) + return value + + if ( + type(getattr(Model, field)) + in [ + ForwardManyToOneDescriptor, + ReverseManyToOneDescriptor, + ReverseOneToOneDescriptor, + ForwardOneToOneDescriptor, + ] + and value + ): + other_model = getattr(Model, field).get_queryset().model + value = _get_obj(Model, other_model, value) + elif type(getattr(Model, field)) in [ManyToManyDescriptor] and value: + other_model = getattr(Model, field).rel.model + value = [_get_obj(Model, other_model, val) for val in value] + return value + + +def _create_object(Model, data): + mtm, no_mtm = {}, {} + for field, value in data.items(): + value = _get_real_obj(Model, field, value) + if type(getattr(Model, field)) is ManyToManyDescriptor: + mtm[field] = value + else: + no_mtm[field] = value + try: + o = Model.objects.get(**no_mtm) + except Model.DoesNotExist: + o = Model(**no_mtm) + o.full_clean() + o.save() + for field, value in mtm.items(): + attribute = getattr(o, field) + if value is not None: + attribute.set(value) + return False + return True + + +def migrate(apps, schema_editor): + Parameter = apps.get_model("api_app", "Parameter") + PluginConfig = apps.get_model("api_app", "PluginConfig") + python_path = plugin.pop("model") + Model = apps.get_model(*python_path.split(".")) + if not Model.objects.filter(name=plugin["name"]).exists(): + exists = _create_object(Model, plugin) + if not exists: + for param in params: + _create_object(Parameter, param) + for value in values: + _create_object(PluginConfig, value) + + +def reverse_migrate(apps, schema_editor): + python_path = plugin.pop("model") + Model = apps.get_model(*python_path.split(".")) + Model.objects.get(name=plugin["name"]).delete() + + +class Migration(migrations.Migration): + atomic = False + dependencies = [ + ("api_app", "0065_job_mpnodesearch"), + ("analyzers_manager", "0146_analyzer_config_wad"), + ] + + operations = [migrations.RunPython(migrate, reverse_migrate)] From 4d47a44bc1605f88f63b617bdcdc9e3e252de8ad Mon Sep 17 00:00:00 2001 From: pranjalg1331 Date: Fri, 17 Jan 2025 11:01:22 +0530 Subject: [PATCH 04/10] add to playbook Signed-off-by: pranjalg1331 --- .../0059_add_abuse_whois_to_free_to_use.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 api_app/playbooks_manager/migrations/0059_add_abuse_whois_to_free_to_use.py diff --git a/api_app/playbooks_manager/migrations/0059_add_abuse_whois_to_free_to_use.py b/api_app/playbooks_manager/migrations/0059_add_abuse_whois_to_free_to_use.py new file mode 100644 index 0000000000..495c80cffd --- /dev/null +++ b/api_app/playbooks_manager/migrations/0059_add_abuse_whois_to_free_to_use.py @@ -0,0 +1,55 @@ +# This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl +# See the file 'LICENSE' for copying permission. + + +from django.db import migrations + + +def migrate(apps, schema_editor): + playbook_config = apps.get_model("playbooks_manager", "PlaybookConfig") + AnalyzerConfig = apps.get_model("analyzers_manager", "AnalyzerConfig") + pc = playbook_config.objects.get(name="FREE_TO_USE_ANALYZERS") + pc2 = playbook_config.objects.get(name="Dns") + pc.analyzers.add( + AnalyzerConfig.objects.get(name="UltraDNS_DNS").id, + AnalyzerConfig.objects.get(name="UltraDNS_Malicious_Detector").id, + ) + pc2.analyzers.add( + AnalyzerConfig.objects.get(name="UltraDNS_DNS").id, + AnalyzerConfig.objects.get(name="UltraDNS_Malicious_Detector").id, + ) + pc.full_clean() + pc.save() + pc2.full_clean() + pc2.save() + + +def reverse_migrate(apps, schema_editor): + playbook_config = apps.get_model("playbooks_manager", "PlaybookConfig") + AnalyzerConfig = apps.get_model("analyzers_manager", "AnalyzerConfig") + pc = playbook_config.objects.get(name="FREE_TO_USE_ANALYZERS") + pc2 = playbook_config.objects.get(name="Dns") + + pc.analyzers.remove( + AnalyzerConfig.objects.get(name="UltraDNS_DNS").id, + AnalyzerConfig.objects.get(name="UltraDNS_Malicious_Detector").id, + ) + pc.full_clean() + pc.save() + pc2.analyzers.remove( + AnalyzerConfig.objects.get(name="UltraDNS_DNS").id, + AnalyzerConfig.objects.get(name="UltraDNS_Malicious_Detector").id, + ) + pc2.full_clean() + pc2.save() + + +class Migration(migrations.Migration): + dependencies = [ + ("playbooks_manager", "0057_alter_phishing_extractor_add_domain"), + ("analyzers_manager", "0145_analyzer_config_ultradns_malicious_detector"), + ] + + operations = [ + migrations.RunPython(migrate, reverse_migrate), + ] From 1f3dba2338e04190d3749655af40d5d2f822e5be Mon Sep 17 00:00:00 2001 From: pranjalg1331 Date: Sat, 18 Jan 2025 11:56:24 +0530 Subject: [PATCH 05/10] dependency resolve --- docker/Dockerfile | 2 +- requirements/abusewhois-requirements.txt | 2 ++ requirements/project-requirements.txt | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 requirements/abusewhois-requirements.txt diff --git a/docker/Dockerfile b/docker/Dockerfile index 7361375fc6..8c5c5789d8 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -54,7 +54,7 @@ RUN pip3 install --no-cache-dir --compile -r project-requirements.txt \ && pip3 install --no-cache-dir pycti==${PYCTI_VERSION} \ && pip3 install --no-cache-dir --compile -r certego-requirements.txt -RUN pip3 install abuse_whois==0.10.1 +# RUN pip3 install --no-cache-dir --compile -r abusewhois-requirements.txt COPY . $PYTHONPATH diff --git a/requirements/abusewhois-requirements.txt b/requirements/abusewhois-requirements.txt new file mode 100644 index 0000000000..70284e9a23 --- /dev/null +++ b/requirements/abusewhois-requirements.txt @@ -0,0 +1,2 @@ +starlette==0.45.2 +abuse_whois==0.10.1 \ No newline at end of file diff --git a/requirements/project-requirements.txt b/requirements/project-requirements.txt index 8c629f9213..1ccf9bdb43 100644 --- a/requirements/project-requirements.txt +++ b/requirements/project-requirements.txt @@ -88,7 +88,6 @@ docxpy==0.8.5 pylnk3==0.4.2 androguard==3.4.0a1 # version >=4.x of androguard raises a dependency conflict with quark-engine==25.1.1 wad==0.4.6 -starlette==0.45.2 # this is required because XLMMacroDeobfuscator does not pin the following packages pyxlsb2==0.0.8 xlrd2==1.3.4 From 6d72bd6e746074745729e6e3d949d2d47e077d38 Mon Sep 17 00:00:00 2001 From: pranjalg1331 Date: Sun, 19 Jan 2025 12:09:51 +0530 Subject: [PATCH 06/10] requirements complete Signed-off-by: pranjalg1331 --- .../migrations/0059_add_abuse_whois_to_free_to_use.py | 4 ++-- docker/Dockerfile | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api_app/playbooks_manager/migrations/0059_add_abuse_whois_to_free_to_use.py b/api_app/playbooks_manager/migrations/0059_add_abuse_whois_to_free_to_use.py index 495c80cffd..f89b371960 100644 --- a/api_app/playbooks_manager/migrations/0059_add_abuse_whois_to_free_to_use.py +++ b/api_app/playbooks_manager/migrations/0059_add_abuse_whois_to_free_to_use.py @@ -46,8 +46,8 @@ def reverse_migrate(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ - ("playbooks_manager", "0057_alter_phishing_extractor_add_domain"), - ("analyzers_manager", "0145_analyzer_config_ultradns_malicious_detector"), + ("playbooks_manager", "0058_add_ultradns_to_free_to_use_and_dns"), + ("analyzers_manager", "0147_analyzer_config_abusewhois"), ] operations = [ diff --git a/docker/Dockerfile b/docker/Dockerfile index 8c5c5789d8..8ab2f49212 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -48,13 +48,13 @@ RUN cpan -T Email::Outlook::Message COPY requirements/project-requirements.txt $PYTHONPATH/project-requirements.txt COPY requirements/certego-requirements.txt $PYTHONPATH/certego-requirements.txt +COPY requirements/abusewhois-requirements.txt $PYTHONPATH/abusewhois-requirements.txt WORKDIR $PYTHONPATH RUN pip3 install --no-cache-dir --compile -r project-requirements.txt \ && pip3 install --no-cache-dir pycti==${PYCTI_VERSION} \ - && pip3 install --no-cache-dir --compile -r certego-requirements.txt - -# RUN pip3 install --no-cache-dir --compile -r abusewhois-requirements.txt + && pip3 install --no-cache-dir --compile -r certego-requirements.txt \ + && pip3 install --no-cache-dir --compile -r abusewhois-requirements.txt COPY . $PYTHONPATH From 0252b817233b6c59576d912841ba1b2764cc9706 Mon Sep 17 00:00:00 2001 From: pranjalg1331 Date: Sun, 19 Jan 2025 15:20:06 +0530 Subject: [PATCH 07/10] cyclomatic funtion removed Signed-off-by: pranjalg1331 --- .../observable_analyzers/abusewhois.py | 125 ++++++++---------- 1 file changed, 57 insertions(+), 68 deletions(-) diff --git a/api_app/analyzers_manager/observable_analyzers/abusewhois.py b/api_app/analyzers_manager/observable_analyzers/abusewhois.py index 4a4d22bcc9..da2d4adefa 100644 --- a/api_app/analyzers_manager/observable_analyzers/abusewhois.py +++ b/api_app/analyzers_manager/observable_analyzers/abusewhois.py @@ -15,12 +15,7 @@ class AbuseWHOIS(classes.ObservableAnalyzer): def update(cls) -> bool: pass - def _clean_contact_info(self, contact): - """Remove null values and replace with REDACTED if appropriate""" - if not any(contact.values()): - return {"status": "REDACTED FOR PRIVACY"} - return {k: v for k, v in contact.items() if v is not None} - + @staticmethod def _parse_raw_whois_text(self, raw_text): """Extract network information from raw WHOIS text""" info = {} @@ -109,68 +104,62 @@ def _format_domain_data(self, result): ), }, "contacts": { - "registrant": self._clean_contact_info( - { - "organization": ( - result.records.domain.registrant.organization - if result.records.domain - else None - ), - "email": ( - result.records.domain.registrant.email - if result.records.domain - else None - ), - "name": ( - result.records.domain.registrant.name - if result.records.domain - else None - ), - "telephone": ( - result.records.domain.registrant.telephone - if result.records.domain - else None - ), - } - ), - "abuse": self._clean_contact_info( - { - "email": ( - result.records.domain.abuse.email - if result.records.domain - else None - ), - "telephone": ( - result.records.domain.abuse.telephone - if result.records.domain - else None - ), - } - ), - "technical": self._clean_contact_info( - { - "organization": ( - result.records.domain.tech.organization - if result.records.domain - else None - ), - "email": ( - result.records.domain.tech.email - if result.records.domain - else None - ), - "name": ( - result.records.domain.tech.name - if result.records.domain - else None - ), - "telephone": ( - result.records.domain.tech.telephone - if result.records.domain - else None - ), - } - ), + "registrant": { + "organization": ( + result.records.domain.registrant.organization + if result.records.domain + else None + ), + "email": ( + result.records.domain.registrant.email + if result.records.domain + else None + ), + "name": ( + result.records.domain.registrant.name + if result.records.domain + else None + ), + "telephone": ( + result.records.domain.registrant.telephone + if result.records.domain + else None + ), + }, + "abuse": { + "email": ( + result.records.domain.abuse.email + if result.records.domain + else None + ), + "telephone": ( + result.records.domain.abuse.telephone + if result.records.domain + else None + ), + }, + "technical": { + "organization": ( + result.records.domain.tech.organization + if result.records.domain + else None + ), + "email": ( + result.records.domain.tech.email + if result.records.domain + else None + ), + "name": ( + result.records.domain.tech.name + if result.records.domain + else None + ), + "telephone": ( + result.records.domain.tech.telephone + if result.records.domain + else None + ), + }, }, } From 90ef4842772225c77807efb6429e4d4cdeda553b Mon Sep 17 00:00:00 2001 From: pranjalg1331 Date: Sun, 19 Jan 2025 15:44:23 +0530 Subject: [PATCH 08/10] deep source python correction Signed-off-by: pranjalg1331 --- .../observable_analyzers/abusewhois.py | 84 ++++--------------- 1 file changed, 18 insertions(+), 66 deletions(-) diff --git a/api_app/analyzers_manager/observable_analyzers/abusewhois.py b/api_app/analyzers_manager/observable_analyzers/abusewhois.py index da2d4adefa..456ac14e0e 100644 --- a/api_app/analyzers_manager/observable_analyzers/abusewhois.py +++ b/api_app/analyzers_manager/observable_analyzers/abusewhois.py @@ -15,7 +15,6 @@ class AbuseWHOIS(classes.ObservableAnalyzer): def update(cls) -> bool: pass - @staticmethod def _parse_raw_whois_text(self, raw_text): """Extract network information from raw WHOIS text""" info = {} @@ -73,16 +72,17 @@ def _format_ip_data(self, result): }, } - def _format_domain_data(self, result): + @staticmethod + def _format_domain_data(result): """Format domain WHOIS data""" return { "domain": { "name": result.address, "ip_address": result.ip_address, "registrar": { - "provider": result.registrar.provider if result.registrar else None, - "email": result.registrar.address if result.registrar else None, - "type": result.registrar.type if result.registrar else None, + "provider": result.registrar.provider, + "email": result.registrar.address, + "type": result.registrar.type, }, }, "domain_info": { @@ -92,73 +92,25 @@ def _format_domain_data(self, result): "statuses": ( result.records.domain.statuses if result.records.domain else [] ), - "expires_at": ( - result.records.domain.expires_at.isoformat() - if result.records.domain and result.records.domain.expires_at - else None - ), - "updated_at": ( - result.records.domain.updated_at.isoformat() - if result.records.domain and result.records.domain.updated_at - else None - ), + "expires_at": (result.records.domain.expires_at.isoformat()), + "updated_at": (result.records.domain.updated_at.isoformat()), }, "contacts": { "registrant": { - "organization": ( - result.records.domain.registrant.organization - if result.records.domain - else None - ), - "email": ( - result.records.domain.registrant.email - if result.records.domain - else None - ), - "name": ( - result.records.domain.registrant.name - if result.records.domain - else None - ), - "telephone": ( - result.records.domain.registrant.telephone - if result.records.domain - else None - ), + "organization": (result.records.domain.registrant.organization), + "email": (result.records.domain.registrant.email), + "name": (result.records.domain.registrant.name), + "telephone": (result.records.domain.registrant.telephone), }, "abuse": { - "email": ( - result.records.domain.abuse.email - if result.records.domain - else None - ), - "telephone": ( - result.records.domain.abuse.telephone - if result.records.domain - else None - ), + "email": (result.records.domain.abuse.email), + "telephone": (result.records.domain.abuse.telephone), }, "technical": { - "organization": ( - result.records.domain.tech.organization - if result.records.domain - else None - ), - "email": ( - result.records.domain.tech.email - if result.records.domain - else None - ), - "name": ( - result.records.domain.tech.name - if result.records.domain - else None - ), - "telephone": ( - result.records.domain.tech.telephone - if result.records.domain - else None - ), + "organization": (result.records.domain.tech.organization), + "email": (result.records.domain.tech.email), + "name": (result.records.domain.tech.name), + "telephone": (result.records.domain.tech.telephone), }, }, } @@ -171,7 +123,7 @@ async def _get_whois_data(self): formatted_data = ( self._format_ip_data(result) if result.records.domain is None - else self._format_domain_data(result) + else AbuseWHOIS._format_domain_data(result) ) # Remove any remaining null values at the top level From f91cdca74a1d81174d19cb982802c432585518ef Mon Sep 17 00:00:00 2001 From: pranjalg1331 Date: Sun, 19 Jan 2025 15:48:49 +0530 Subject: [PATCH 09/10] deep source python correction 2 Signed-off-by: pranjalg1331 --- .../analyzers_manager/observable_analyzers/abusewhois.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api_app/analyzers_manager/observable_analyzers/abusewhois.py b/api_app/analyzers_manager/observable_analyzers/abusewhois.py index 456ac14e0e..235d21f75f 100644 --- a/api_app/analyzers_manager/observable_analyzers/abusewhois.py +++ b/api_app/analyzers_manager/observable_analyzers/abusewhois.py @@ -15,7 +15,8 @@ class AbuseWHOIS(classes.ObservableAnalyzer): def update(cls) -> bool: pass - def _parse_raw_whois_text(self, raw_text): + @staticmethod + def _parse_raw_whois_text(raw_text): """Extract network information from raw WHOIS text""" info = {} for line in raw_text.split("\n"): @@ -72,8 +73,7 @@ def _format_ip_data(self, result): }, } - @staticmethod - def _format_domain_data(result): + def _format_domain_data(self, result): """Format domain WHOIS data""" return { "domain": { From ed93e2e20a62458b67fe8f839cb804a900ae6cf0 Mon Sep 17 00:00:00 2001 From: pranjalg1331 Date: Sun, 19 Jan 2025 15:57:06 +0530 Subject: [PATCH 10/10] deep source python correction 3 Signed-off-by: pranjalg1331 --- api_app/analyzers_manager/observable_analyzers/abusewhois.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_app/analyzers_manager/observable_analyzers/abusewhois.py b/api_app/analyzers_manager/observable_analyzers/abusewhois.py index 235d21f75f..b83e7ba46a 100644 --- a/api_app/analyzers_manager/observable_analyzers/abusewhois.py +++ b/api_app/analyzers_manager/observable_analyzers/abusewhois.py @@ -123,7 +123,7 @@ async def _get_whois_data(self): formatted_data = ( self._format_ip_data(result) if result.records.domain is None - else AbuseWHOIS._format_domain_data(result) + else self._format_domain_data(result) ) # Remove any remaining null values at the top level