Giter Site home page Giter Site logo

mattkeeley / spoofy Goto Github PK

View Code? Open in Web Editor NEW
604.0 10.0 56.0 983 KB

Spoofy is a program that checks if a list of domains can be spoofed based on SPF and DMARC records.

License: Creative Commons Zero v1.0 Universal

Python 100.00%
application-security appsec cybersecurity deliverability dmarc email-security emails infosec penetration-testing penetration-testing-tools pentesting python3 redteam security spf phishing python

spoofy's Introduction



Spoofy

forthebadge forthebadge forthebadge

WHAT

Spoofy is a program that checks if a list of domains can be spoofed based on SPF and DMARC records. You may be asking, "Why do we need another tool that can check if a domain can be spoofed?"

Well, Spoofy is different and here is why:

  1. Authoritative lookups on all lookups with known fallback (Cloudflare DNS)
  2. Accurate bulk lookups
  3. Custom, manually tested spoof logic (No guessing or speculating, real world test results)
  4. SPF DNS query counter

PASSING TESTS

Spoofy CI

HOW TO USE

Spoofy requires Python 3+. Python 2 is not supported. Usage is shown below:

Usage:
    ./spoofy.py -d [DOMAIN] -o [stdout or xls] -t [NUMBER_OF_THREADS]
    OR
    ./spoofy.py -iL [DOMAIN_LIST] -o [stdout or xls] -t [NUMBER_OF_THREADS]

Options:
    -d  : Process a single domain.
    -iL : Provide a file containing a list of domains to process.
    -o  : Specify the output format: stdout (default) or xls.
    -t  : Set the number of threads to use (default: 4).

Examples:
    ./spoofy.py -d example.com -t 10
    ./spoofy.py -iL domains.txt -o xls

Install Dependencies:
    pip3 install -r requirements.txt

HOW DO YOU KNOW ITS SPOOFABLE

(The spoofability table lists every combination of SPF and DMARC configurations that impact deliverability to the inbox, except for DKIM modifiers.) Download Here

METHODOLOGY

The creation of the spoofability table involved listing every relevant SPF and DMARC configuration, combining them, and then conducting SPF and DMARC information collection using an early version of Spoofy on a large number of US government domains. Testing if an SPF and DMARC combination was spoofable or not was done using the email security pentesting suite at emailspooftest using Microsoft 365. However, the initial testing was conducted using Protonmail and Gmail, but these services were found to utilize reverse lookup checks that affected the results, particularly for subdomain spoof testing. As a result, Microsoft 365 was used for the testing, as it offered greater control over the handling of mail.

After the initial testing using Microsoft 365, some combinations were retested using Protonmail and Gmail due to the differences in their handling of banners in emails. Protonmail and Gmail can place spoofed mail in the inbox with a banner or in spam without a banner, leading to some SPF and DMARC combinations being reported as "Mailbox Dependent" when using Spoofy. In contrast, Microsoft 365 places both conditions in spam. The testing and data collection process took several days to complete, after which a good master table was compiled and used as the basis for the Spoofy spoofability logic.

DISCLAIMER

This tool is only for testing and academic purposes and can only be used where strict consent has been given. Do not use it for illegal purposes! It is the end user’s responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this tool and software.

CREDIT

Lead / Only programmer & spoofability logic comprehension upgrades & lookup resiliency system / fix (main issue with other tools) & multithreading & feature additions: Matt Keeley

DMARC, SPF, DNS insights & Spoofability table creation/confirmation/testing & application accuracy/quality assurance: calamity.email / eman-ekaf

Logo: cobracode

Tool was inspired by Bishop Fox's project called spoofcheck.

LICENSE

This project is licensed under the Creative Commons Zero v1.0 Universal - see the LICENSE file for details

spoofy's People

Contributors

eman-ekaf avatar khnaz35 avatar mattkeeley avatar paulmolin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spoofy's Issues

Discuss the logic in is_spoofable

Some conditions in is_spoofable look weird, but I'm not sure if it's intended or not. I'm not an expert in email security, so the recommendations might not be correct, just want to know if these conditions make sense.

  • Line 49: p == "none" and sp == "reject" or sp == "quarentine"
    • Should it be p == "none" and (sp == "reject" or sp == "quarentine") ?
  • Line 62 and Line 64
    • 62: (p == "reject" or p == "quarentine") and aspf and sp == "none"
    • 64: (p == "reject" or p == "quarentine") and aspf is None and sp == "none"
    • These two cases return the same value (6), and the only difference is that whether the aspf is None or not, which also indicates that aspf can be ignored in this case. Maybe checking (p == "reject" or p == "quarentine") and sp == "none" is enough for this two cases
  • Line 70 and 72
    • 70: p == "none" and aspf == "s" or None and sp == "none"
    • 72: p == "none" and aspf == "s" or None and sp is None
    • These two cases have similar situations. Perhaps aspf == "s" or None should be (aspf == "s" or aspf is None)

Multipart domain

I live in New Zealand where we have multipart domain names e.g. mydomain.co.nz. This kind of domain fails in the get_dmarc_record and get_dmarc_org_policy functions.
If I do something like:
def get_dmarc_record(domain):
if domain.endswith(".com") & domain.count('.') > 1: return get_dmarc_org_policy(domain)

or
def get_dmarc_record(domain):
if domain.find(".co.") < 1 & domain.count('.') > 1: return get_dmarc_org_policy(domain)

Then my domains work. The complication is that you have heaps of other top-level domains now, so using just ".com" isn't a solution:
.biz
.kiwi
.co
Also, there are a few places similar to Australia who use mydomain.com.au which will also cause issues.
I'm not good enough with Python to offer a robust solution for this, but I'm sure there is a way.

Spoofing not possible without SPF or DMARC record.

Since I do not have the knowledge, time or resources to test it I cannot confirm it, but I have found some situations where I think spoofy should either test harder or return a different result.

I have been using spoofy for some time (thank you), and since I have very little knowledge, I trusted kind of blindly, but I have come across (at least) two common situations where I think spoofy is not giving the correct answer.

The SPF record was created for a domain to say what IPs are allowed to send emails on behalf of it. So, if there is no SPF record, I understand the domain should be spoofable. The DMARC has been introduced to patch some SPF holes, and it needs either SPF and/or DKIM to specify how a receiving email is classified.


I have come across some SPF records without the all directive, which, according to the standard is treated as ?all, which is neutral (pass). To my surprise the domain was not spoofable acording to spoofy, even though there was no DMARC. I started to pay more attention to this detail and there has always been a redirect, example:

[*] Domain: redacted.com
[*] Is subdomain: False
[*] DNS Server: 1.1.1.1
[*] SPF record: v=spf1 redirect=spf.dominioabsoluto.net
[*] SPF does not contain an `All` items.
[*] SPF include count: 0
[?] No DMARC record found.
[-] Spoofing not possibel for redacted.com

Reviewing some auditories I have performed, I came across another example which also makes no sense:

  • No SPF record.
  • DMARC like this: v=DMARC1; p=none; rua=mailto:[email protected].
  • Result: "Spoofing not possible".
[*] Domain: sub.redacted.com
[*] Is subdomain: True
[*] DNS Server: 1.1.1.1
[?] No SPF record found.
[*] DMARC record: v=DMARC1; p=none; rua=mailto:[email protected]
[*] Found DMARC policy: none
[*] No DMARC pct found.
[*] No DMARC aspf found.
[*] No DMARC subdomain policy found.
[*] No DMARC forensics report location found.
[*] Aggregate reports will be sent to: mailto:[email protected]
[-] Spoofing not possible for sub.redacted.com

I have also checked them with caniphish, which stated that both were spoofable with a high risk pointing out the lack of one protocol, either SPF or DMARC.

DKIM Collection/Analysis

Love the tool! Have we considered adding DKIM support as well? There is research out there on bypassing DKIM requirements and it would be nice to have a single tool to identify and evaluate the DKIM record? My previous coworker had wrote some code here on how guessing common DKIM subdomains that may be helpful:

Some example of DKIM attacks:

Parsing TXT Records incorrectly

Description

If a TXT record is resolved with greater than 256 characters. The script replaces the " to concatenate the second TXT record.
Example if something like this appears "-al" "l" in seperated TXT records because of length the script does not recognize the setting, as it parses it from -al" "l" to -al l". This can be quickly fixed, we see this error with our own company domain.

I don't want to put in our explicit example from the logs, to not expose any details here on github.
I fixed this already in my local cloned version of you script, however I would like to address this as it may create false-positives for others.

Current Code

                spf_record = str(dns_data).replace('"','')

Code Change

                spf_record = str(dns_data).replace('" "','')

This will handle the concatenation correctly and makes "-al l" to "-all" and also of course any other strings that are split on the TXT size limit. :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.