Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mullvad_DNS (New Analyzer) #2763

Merged
merged 16 commits into from
Feb 25, 2025
Merged

Conversation

AnshSinghal
Copy link

@AnshSinghal AnshSinghal commented Feb 20, 2025

Closes #2756

Description

This PR adds the "Mullvad_DNS" analyzer. The analyzer queries Mullvad's DNS-over-HTTPS service (using the "base" endpoint) to check a domain's DNS records. It supports two modes:
-"query": Returns raw DNS answer data.
-"malicious": Interprets an NXDOMAIN (rcode==3) as the domain being blocked (i.e., malicious).

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality).

Checklist

  • I have read and understood the rules about how to Contribute to this project
  • The pull request is for the branch develop
  • A new plugin (analyzer, connector, visualizer, playbook, pivot or ingestor) was added or changed, in which case:
    • I strictly followed the documentation "How to create a Plugin"
    • Usage file was updated. A link to the PR to the docs repo has been added as a comment here.
    • Advanced-Usage was updated (in case the plugin provides additional optional configuration). A link to the PR to the docs repo has been added as a comment here.
    • I have dumped the configuration from Django Admin using the dumpplugin command and added it in the project as a data migration. ("How to share a plugin with the community")
    • If a File analyzer was added and it supports a mimetype which is not already supported, you added a sample of that type inside the archive test_files.zip and you added the default tests for that mimetype in test_classes.py.
    • If you created a new analyzer and it is free (does not require any API key), please add it in the FREE_TO_USE_ANALYZERS playbook by following this guide.
    • Check if it could make sense to add that analyzer/connector to other freely available playbooks.
    • I have provided the resulting raw JSON of a finished analysis and a screenshot of the results.
    • If the plugin interacts with an external service, I have created an attribute called precisely url that contains this information. This is required for Health Checks.
    • If the plugin requires mocked testing, _monkeypatch() was used in its class to apply the necessary decorators.
    • I have added that raw JSON sample to the MockUpResponse of the _monkeypatch() method. This serves us to provide a valid sample for testing.
  • I have inserted the copyright banner at the start of the file: # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl # See the file 'LICENSE' for copying permission.
  • If external libraries/packages with restrictive licenses were used, they were added in the Legal Notice section.
  • Linters (Black, Flake, Isort) gave 0 errors. If you have correctly installed pre-commit, it does these checks and adjustments on your behalf.
  • I have added tests for the feature/bug I solved (see tests folder). All the tests (new and old ones) gave 0 errors.
  • If the GUI has been modified:
    • I have a provided a screenshot of the result in the PR.
    • I have created new frontend tests for the new component or updated existing ones.
  • After you had submitted the PR, if DeepSource, Django Doctors or other third-party linters have triggered any alerts during the CI checks, I have solved those alerts.

Important Rules

  • If you miss to compile the Checklist properly, your PR won't be reviewed by the maintainers.
  • Everytime you make changes to the PR and you think the work is done, you should explicitly ask for a review by using GitHub's reviewing system detailed here.

Raw Json for "malicious mode"

"analyzer_reports": [
    {
        "name": "Mullvad_DNS",
        "process_time": 5.45,
        "status": "SUCCESS",
        "end_time": "2025-02-20T16:29:18.921513Z",
        "parameters": {
            "mode": "malicious"
        },
        "type": "analyzer",
        "id": 6,
        "report": {
            "note": "Domain is blocked by Mullvad DNS content filtering.",
            "malicious": true,
            "observable": "mp3raid.com/music/krizz_kaliko.html"
        },
        "errors": [],
        "start_time": "2025-02-20T16:29:13.471848Z",
        "description": "This analyzer queries Mullvad's DNS-over-HTTPS service (using the \"base\" endpoint) to check a domain's DNS records. It supports two modes:\r\n- \"query\": returns raw DNS answer data.\r\n- \"malicious\": interprets an NXDOMAIN (rcode==3) as the domain being blocked (i.e., malicious).",
        "data_model": {}
    }
],

Raw Json for "query mode"

"analyzer_reports": [
    {
        "name": "Mullvad_DNS",
        "process_time": 3.12,
        "status": "SUCCESS",
        "end_time": "2025-02-20T16:19:16.859514Z",
        "parameters": {
            "mode": "query"
        },
        "type": "analyzer",
        "id": 2,
        "report": {
            "data": [
                "anshsinghal.tech. 1800 IN A 64.29.17.2\nanshsinghal.tech. 1800 IN A 66.33.60.34"
            ],
            "status": "success",
            "message": "DNS query for anshsinghal.tech completed successfully."
        },
        "errors": [],
        "start_time": "2025-02-20T16:19:13.735227Z",
        "description": "This analyzer queries Mullvad's DNS-over-HTTPS service (using the \"base\" endpoint) to check a domain's DNS records. It supports two modes:\r\n- \"query\": returns raw DNS answer data.\r\n- \"malicious\": interprets an NXDOMAIN (rcode==3) as the domain being blocked (i.e., malicious).",
        "data_model": {}
    }
],

image

@AnshSinghal
Copy link
Author

@fgibertoni if you can please review

Copy link
Member

@g4ze g4ze left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to begin with, pls have a look at the comments i made and rectify.

@g4ze
Copy link
Member

g4ze commented Feb 21, 2025

also, pls look into the ci error checks. It might be something related to a bad migration.

@AnshSinghal
Copy link
Author

also, pls look into the ci error checks. It might be something related to a bad migration.

After carefully reviewing the CLI logs, my migration file and analyzer code, the issue seems to be due to environmental misconfigurations
missing .env.start.test
Docker image tag errors and an invalid export statement.

@AnshSinghal AnshSinghal requested a review from g4ze February 21, 2025 12:36
@g4ze
Copy link
Member

g4ze commented Feb 21, 2025

umm no. just saw, your migration number is not right, it should be 152 technically and be dependant upon 151 :)

@AnshSinghal AnshSinghal requested a review from g4ze February 21, 2025 17:11
"type": "observable",
"docker_based": False,
"maximum_tlp": "RED",
"observable_supported": ["url", "domain", "generic"],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you let me know why support generic as well? maybe lmk an example?

Copy link
Author

@AnshSinghal AnshSinghal Feb 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generic support covers full URLs with paths like 'mp3raid.com/music/krizz_kaliko.html' that don't clearly fall into 'domain' or 'url' categories.
example- urls like "mp3raid.com" returns NOERROR but mp3raid.com/music/krizz_kaliko.html returns NXDOMAIN.

Copy link
Member

@g4ze g4ze Feb 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mp3raid.com/music/krizz_kaliko.html

should classify as a url, if not you'd have to make sure that you verify all the requests coming through generic that they are something similar to what you want and not random names or numbers

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it. I will remove the generic from the analyzer config

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just crosscheck with and without it once for a string like mp3raid.com/music/krizz_kaliko.html

@g4ze
Copy link
Member

g4ze commented Feb 21, 2025

pls add docs as well

@AnshSinghal AnshSinghal requested a review from g4ze February 22, 2025 05:04
@AnshSinghal
Copy link
Author

pls add docs as well

Sure! once the issues in the code gets resolved I will update the Usage docs as well in the final PR

@g4ze
Copy link
Member

g4ze commented Feb 22, 2025

one more change and then i think @mlodic can have a look at it. lgtm.

@g4ze g4ze linked an issue Feb 22, 2025 that may be closed by this pull request
@g4ze g4ze requested a review from mlodic February 22, 2025 11:05
@AnshSinghal AnshSinghal marked this pull request as ready for review February 22, 2025 13:59
@AnshSinghal AnshSinghal changed the title Draft PR for Mullvad_DNS Mullvad_DNS (New Analyzer) Feb 23, 2025
Copy link
Contributor

@fgibertoni fgibertoni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your work, I added some considerations.

@AnshSinghal AnshSinghal requested a review from mlodic February 24, 2025 17:59
@AnshSinghal
Copy link
Author

Hi @mlodic if this looks good can you please merge it so that I can work on another analyzer BBot.

Copy link
Contributor

@fgibertoni fgibertoni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm! thank you for your work @AnshSinghal!

@fgibertoni
Copy link
Contributor

We can wait for Matteo's final feedback and merge but I think you can start working on the other analyzer. I assigned it to you 😄

Copy link
Member

@mlodic mlodic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

last little things and then we can merge

encoded_query = (
base64.urlsafe_b64encode(wire_query).rstrip(b"=").decode("ascii")
)
logger.info(f"Encoded query: {encoded_query}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for each log, it is important to keep track of the original observable, otherwise there is no way to distinguish one analyzer execution from another

observable = self.observable_name

if self.observable_classification == Classification.URL:
logger.info(f"Extracting hostname from URL {observable}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

either debug level or removed


encoded_query = self.encode_query(observable)
complete_url = f"{self.url}?dns={encoded_query}"
logger.info(f"Requesting Mullvad DNS at: {complete_url}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

observable reference missing

@AnshSinghal AnshSinghal requested a review from mlodic February 25, 2025 11:37
@fgibertoni fgibertoni merged commit 425a5d3 into intelowlproject:develop Feb 25, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Analyzer] Mullvad_DNS
4 participants