moriarty-project 0.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- moriarty/__init__.py +5 -0
- moriarty/adapters/__init__.py +0 -0
- moriarty/agent/__init__.py +0 -0
- moriarty/assets/modules/.gitkeep +0 -0
- moriarty/assets/modules/asia/douban.yaml +19 -0
- moriarty/assets/modules/asia/kakao.yaml +19 -0
- moriarty/assets/modules/asia/line.yaml +19 -0
- moriarty/assets/modules/asia/mixi.yaml +19 -0
- moriarty/assets/modules/asia/naver.yaml +19 -0
- moriarty/assets/modules/asia/qq.yaml +19 -0
- moriarty/assets/modules/asia/vk.yaml +19 -0
- moriarty/assets/modules/asia/wechat.yaml +19 -0
- moriarty/assets/modules/asia/weibo.yaml +19 -0
- moriarty/assets/modules/asia/xiaohongshu.yaml +19 -0
- moriarty/assets/modules/behance.yaml +47 -0
- moriarty/assets/modules/business/crunchbase.yaml +27 -0
- moriarty/assets/modules/business/fiverr.yaml +32 -0
- moriarty/assets/modules/business/freelancer.yaml +27 -0
- moriarty/assets/modules/business/glassdoor.yaml +27 -0
- moriarty/assets/modules/business/guru.yaml +26 -0
- moriarty/assets/modules/business/indeed.yaml +25 -0
- moriarty/assets/modules/business/monster.yaml +25 -0
- moriarty/assets/modules/business/peopleperhour.yaml +26 -0
- moriarty/assets/modules/business/toptal.yaml +28 -0
- moriarty/assets/modules/business/upwork.yaml +27 -0
- moriarty/assets/modules/business/ziprecruiter.yaml +25 -0
- moriarty/assets/modules/content/buymeacoffee.yaml +27 -0
- moriarty/assets/modules/content/gumroad.yaml +27 -0
- moriarty/assets/modules/content/ko-fi.yaml +32 -0
- moriarty/assets/modules/content/onlyfans.yaml +27 -0
- moriarty/assets/modules/content/patreon.yaml +33 -0
- moriarty/assets/modules/content/substack.yaml +32 -0
- moriarty/assets/modules/creative/500px.yaml +31 -0
- moriarty/assets/modules/creative/artstation.yaml +33 -0
- moriarty/assets/modules/creative/deviantart.yaml +32 -0
- moriarty/assets/modules/creative/flickr.yaml +31 -0
- moriarty/assets/modules/creative/pexels.yaml +26 -0
- moriarty/assets/modules/creative/unsplash.yaml +26 -0
- moriarty/assets/modules/creative/vimeo.yaml +31 -0
- moriarty/assets/modules/crypto/binance.yaml +27 -0
- moriarty/assets/modules/crypto/bitcointalk.yaml +33 -0
- moriarty/assets/modules/crypto/coinbase.yaml +26 -0
- moriarty/assets/modules/crypto/etherscan.yaml +32 -0
- moriarty/assets/modules/crypto/foundation.yaml +28 -0
- moriarty/assets/modules/crypto/kraken.yaml +27 -0
- moriarty/assets/modules/crypto/mirror.yaml +27 -0
- moriarty/assets/modules/crypto/niftygateway.yaml +26 -0
- moriarty/assets/modules/crypto/opensea.yaml +32 -0
- moriarty/assets/modules/crypto/rarible.yaml +27 -0
- moriarty/assets/modules/crypto/superrare.yaml +29 -0
- moriarty/assets/modules/dating/bumble.yaml +25 -0
- moriarty/assets/modules/dating/grindr.yaml +27 -0
- moriarty/assets/modules/dating/happn.yaml +25 -0
- moriarty/assets/modules/dating/her.yaml +27 -0
- moriarty/assets/modules/dating/hinge.yaml +25 -0
- moriarty/assets/modules/dating/match.yaml +25 -0
- moriarty/assets/modules/dating/meetme.yaml +27 -0
- moriarty/assets/modules/dating/okcupid.yaml +25 -0
- moriarty/assets/modules/dating/pof.yaml +25 -0
- moriarty/assets/modules/dating/tinder.yaml +25 -0
- moriarty/assets/modules/dating-nsfw/adultfriendfinder.yaml +28 -0
- moriarty/assets/modules/dating-nsfw/ashley-madison.yaml +26 -0
- moriarty/assets/modules/design/adobe-portfolio.yaml +27 -0
- moriarty/assets/modules/design/carbonmade.yaml +27 -0
- moriarty/assets/modules/design/cgsociety.yaml +27 -0
- moriarty/assets/modules/design/coroflot.yaml +27 -0
- moriarty/assets/modules/design/figma.yaml +27 -0
- moriarty/assets/modules/design/sketch.yaml +26 -0
- moriarty/assets/modules/dev/bitbucket.yaml +35 -0
- moriarty/assets/modules/dev/codeforces.yaml +32 -0
- moriarty/assets/modules/dev/codepen.yaml +34 -0
- moriarty/assets/modules/dev/hackerone.yaml +32 -0
- moriarty/assets/modules/dev/hackthebox.yaml +27 -0
- moriarty/assets/modules/dev/huggingface.yaml +27 -0
- moriarty/assets/modules/dev/kaggle.yaml +32 -0
- moriarty/assets/modules/dev/leetcode.yaml +32 -0
- moriarty/assets/modules/dev/replit.yaml +31 -0
- moriarty/assets/modules/dribbble.yaml +53 -0
- moriarty/assets/modules/ecommerce/etsy.yaml +32 -0
- moriarty/assets/modules/education/duolingo.yaml +32 -0
- moriarty/assets/modules/education/edx.yaml +26 -0
- moriarty/assets/modules/education/khanacademy.yaml +26 -0
- moriarty/assets/modules/education/lynda.yaml +27 -0
- moriarty/assets/modules/education/memrise.yaml +27 -0
- moriarty/assets/modules/education/pluralsight.yaml +27 -0
- moriarty/assets/modules/education/skillshare.yaml +27 -0
- moriarty/assets/modules/education/udacity.yaml +27 -0
- moriarty/assets/modules/email/github_email.yaml +40 -0
- moriarty/assets/modules/email/gravatar.yaml +23 -0
- moriarty/assets/modules/europe/badoo.yaml +19 -0
- moriarty/assets/modules/europe/lovoo.yaml +19 -0
- moriarty/assets/modules/europe/myspace.yaml +19 -0
- moriarty/assets/modules/europe/netlog.yaml +19 -0
- moriarty/assets/modules/europe/ok.yaml +19 -0
- moriarty/assets/modules/europe/skyrock.yaml +19 -0
- moriarty/assets/modules/europe/studivz.yaml +19 -0
- moriarty/assets/modules/europe/tuenti.yaml +19 -0
- moriarty/assets/modules/europe/viadeo.yaml +19 -0
- moriarty/assets/modules/europe/xing.yaml +19 -0
- moriarty/assets/modules/fitness/fitbit.yaml +27 -0
- moriarty/assets/modules/fitness/garmin.yaml +27 -0
- moriarty/assets/modules/fitness/myfitnesspal.yaml +27 -0
- moriarty/assets/modules/fitness/strava.yaml +33 -0
- moriarty/assets/modules/fitness/zwift.yaml +28 -0
- moriarty/assets/modules/food/allrecipes.yaml +27 -0
- moriarty/assets/modules/food/tasty.yaml +27 -0
- moriarty/assets/modules/food/yelp.yaml +32 -0
- moriarty/assets/modules/food/zomato.yaml +28 -0
- moriarty/assets/modules/forums/4chan.yaml +26 -0
- moriarty/assets/modules/forums/8kun.yaml +26 -0
- moriarty/assets/modules/forums/9gag.yaml +26 -0
- moriarty/assets/modules/forums/discourse.yaml +26 -0
- moriarty/assets/modules/forums/disqus.yaml +31 -0
- moriarty/assets/modules/forums/hackernews.yaml +32 -0
- moriarty/assets/modules/forums/launchpad.yaml +27 -0
- moriarty/assets/modules/forums/phpbb.yaml +25 -0
- moriarty/assets/modules/forums/quora.yaml +32 -0
- moriarty/assets/modules/forums/serverfault.yaml +27 -0
- moriarty/assets/modules/forums/slashdot.yaml +28 -0
- moriarty/assets/modules/forums/stackexchange.yaml +32 -0
- moriarty/assets/modules/forums/superuser.yaml +27 -0
- moriarty/assets/modules/forums/vbulletin.yaml +25 -0
- moriarty/assets/modules/forums/xenforo.yaml +25 -0
- moriarty/assets/modules/forums-nsfw/kiwifarms.yaml +25 -0
- moriarty/assets/modules/forums-nsfw/lolcow.yaml +26 -0
- moriarty/assets/modules/gaming/apextracker.yaml +27 -0
- moriarty/assets/modules/gaming/battlenet.yaml +26 -0
- moriarty/assets/modules/gaming/chess.yaml +30 -0
- moriarty/assets/modules/gaming/discord-public.yaml +27 -0
- moriarty/assets/modules/gaming/dotabuff.yaml +32 -0
- moriarty/assets/modules/gaming/epicgames.yaml +25 -0
- moriarty/assets/modules/gaming/faceit.yaml +33 -0
- moriarty/assets/modules/gaming/fortnitetracker.yaml +32 -0
- moriarty/assets/modules/gaming/gog.yaml +26 -0
- moriarty/assets/modules/gaming/itch.yaml +32 -0
- moriarty/assets/modules/gaming/kongregate.yaml +25 -0
- moriarty/assets/modules/gaming/minecraft.yaml +31 -0
- moriarty/assets/modules/gaming/opgg.yaml +32 -0
- moriarty/assets/modules/gaming/origin.yaml +26 -0
- moriarty/assets/modules/gaming/playstation.yaml +30 -0
- moriarty/assets/modules/gaming/roblox.yaml +31 -0
- moriarty/assets/modules/gaming/xbox.yaml +25 -0
- moriarty/assets/modules/github.yaml +68 -0
- moriarty/assets/modules/gitlab.yaml +60 -0
- moriarty/assets/modules/instagram.yaml +48 -0
- moriarty/assets/modules/latam/fotolog.yaml +27 -0
- moriarty/assets/modules/latam/orkut.yaml +26 -0
- moriarty/assets/modules/latam/taringa.yaml +27 -0
- moriarty/assets/modules/learning/coursera.yaml +26 -0
- moriarty/assets/modules/learning/udemy.yaml +26 -0
- moriarty/assets/modules/linkedin.yaml +40 -0
- moriarty/assets/modules/marketplaces/depop.yaml +28 -0
- moriarty/assets/modules/marketplaces/ebay.yaml +32 -0
- moriarty/assets/modules/marketplaces/grailed.yaml +27 -0
- moriarty/assets/modules/marketplaces/mercari.yaml +26 -0
- moriarty/assets/modules/marketplaces/poshmark.yaml +27 -0
- moriarty/assets/modules/marketplaces/reverb.yaml +27 -0
- moriarty/assets/modules/marketplaces/vinted.yaml +28 -0
- moriarty/assets/modules/medium.yaml +44 -0
- moriarty/assets/modules/music/audiomack.yaml +26 -0
- moriarty/assets/modules/music/bandcamp.yaml +30 -0
- moriarty/assets/modules/music/beatport.yaml +28 -0
- moriarty/assets/modules/music/deezer.yaml +26 -0
- moriarty/assets/modules/music/discogs.yaml +32 -0
- moriarty/assets/modules/music/genius.yaml +26 -0
- moriarty/assets/modules/music/lastfm.yaml +30 -0
- moriarty/assets/modules/music/mixcloud.yaml +26 -0
- moriarty/assets/modules/music/reverbnation.yaml +31 -0
- moriarty/assets/modules/music/soundcloud.yaml +31 -0
- moriarty/assets/modules/music/spotify.yaml +26 -0
- moriarty/assets/modules/music/tidal.yaml +26 -0
- moriarty/assets/modules/nsfw/adultwork.yaml +27 -0
- moriarty/assets/modules/nsfw/bongacams.yaml +28 -0
- moriarty/assets/modules/nsfw/cam4.yaml +28 -0
- moriarty/assets/modules/nsfw/chaturbate.yaml +28 -0
- moriarty/assets/modules/nsfw/clips4sale.yaml +27 -0
- moriarty/assets/modules/nsfw/extralunchmoney.yaml +27 -0
- moriarty/assets/modules/nsfw/fansly.yaml +28 -0
- moriarty/assets/modules/nsfw/fetlife.yaml +28 -0
- moriarty/assets/modules/nsfw/iwantclips.yaml +27 -0
- moriarty/assets/modules/nsfw/justforfans.yaml +28 -0
- moriarty/assets/modules/nsfw/loyalfans.yaml +28 -0
- moriarty/assets/modules/nsfw/manyvids.yaml +27 -0
- moriarty/assets/modules/nsfw/myfreecams.yaml +28 -0
- moriarty/assets/modules/nsfw/niteflirt.yaml +26 -0
- moriarty/assets/modules/nsfw/pornhub.yaml +32 -0
- moriarty/assets/modules/nsfw/redtube.yaml +27 -0
- moriarty/assets/modules/nsfw/stripchat.yaml +28 -0
- moriarty/assets/modules/nsfw/xhamster.yaml +27 -0
- moriarty/assets/modules/nsfw/xvideos.yaml +27 -0
- moriarty/assets/modules/nsfw/youporn.yaml +27 -0
- moriarty/assets/modules/photography/eyeem.yaml +25 -0
- moriarty/assets/modules/photography/fotki.yaml +25 -0
- moriarty/assets/modules/photography/photobucket.yaml +26 -0
- moriarty/assets/modules/photography/smugmug.yaml +25 -0
- moriarty/assets/modules/photography/vsco.yaml +27 -0
- moriarty/assets/modules/pinterest.yaml +40 -0
- moriarty/assets/modules/podcasts/anchor.yaml +26 -0
- moriarty/assets/modules/podcasts/castbox.yaml +26 -0
- moriarty/assets/modules/podcasts/podbean.yaml +26 -0
- moriarty/assets/modules/professional/about.yaml +31 -0
- moriarty/assets/modules/professional/academia.yaml +27 -0
- moriarty/assets/modules/professional/angellist.yaml +27 -0
- moriarty/assets/modules/professional/calendly.yaml +26 -0
- moriarty/assets/modules/professional/issuu.yaml +27 -0
- moriarty/assets/modules/professional/mendeley.yaml +27 -0
- moriarty/assets/modules/professional/notion.yaml +27 -0
- moriarty/assets/modules/professional/orcid.yaml +27 -0
- moriarty/assets/modules/professional/producthunt.yaml +31 -0
- moriarty/assets/modules/professional/researchgate.yaml +32 -0
- moriarty/assets/modules/professional/scribd.yaml +27 -0
- moriarty/assets/modules/professional/slideshare.yaml +31 -0
- moriarty/assets/modules/professional/trello.yaml +26 -0
- moriarty/assets/modules/professional/typeform.yaml +27 -0
- moriarty/assets/modules/reddit.yaml +46 -0
- moriarty/assets/modules/regional/amino.yaml +27 -0
- moriarty/assets/modules/regional/ask-fm.yaml +32 -0
- moriarty/assets/modules/regional/babycenter.yaml +26 -0
- moriarty/assets/modules/regional/cafemom.yaml +27 -0
- moriarty/assets/modules/regional/care2.yaml +27 -0
- moriarty/assets/modules/regional/diaspora.yaml +26 -0
- moriarty/assets/modules/regional/ello.yaml +27 -0
- moriarty/assets/modules/regional/gaia.yaml +27 -0
- moriarty/assets/modules/regional/habbo.yaml +27 -0
- moriarty/assets/modules/regional/imvu.yaml +27 -0
- moriarty/assets/modules/regional/lemmy.yaml +27 -0
- moriarty/assets/modules/regional/peertube.yaml +26 -0
- moriarty/assets/modules/regional/pixelfed.yaml +27 -0
- moriarty/assets/modules/regional/plurk.yaml +26 -0
- moriarty/assets/modules/regional/recroom.yaml +27 -0
- moriarty/assets/modules/regional/secondlife.yaml +26 -0
- moriarty/assets/modules/regional/vine-archive.yaml +27 -0
- moriarty/assets/modules/regional/vrchat.yaml +27 -0
- moriarty/assets/modules/regional/weheartit.yaml +27 -0
- moriarty/assets/modules/social/anilist.yaml +27 -0
- moriarty/assets/modules/social/beacons.yaml +26 -0
- moriarty/assets/modules/social/blogger.yaml +27 -0
- moriarty/assets/modules/social/crunchyroll.yaml +27 -0
- moriarty/assets/modules/social/discord.yaml +27 -0
- moriarty/assets/modules/social/dreamwidth.yaml +26 -0
- moriarty/assets/modules/social/facebook.yaml +34 -0
- moriarty/assets/modules/social/goodreads.yaml +32 -0
- moriarty/assets/modules/social/imdb.yaml +27 -0
- moriarty/assets/modules/social/kitsu.yaml +27 -0
- moriarty/assets/modules/social/letterboxd.yaml +32 -0
- moriarty/assets/modules/social/linktree.yaml +26 -0
- moriarty/assets/modules/social/livejournal.yaml +27 -0
- moriarty/assets/modules/social/mastodon.yaml +30 -0
- moriarty/assets/modules/social/minds.yaml +25 -0
- moriarty/assets/modules/social/myanimelist.yaml +32 -0
- moriarty/assets/modules/social/ravelry.yaml +27 -0
- moriarty/assets/modules/social/snapchat.yaml +25 -0
- moriarty/assets/modules/social/telegram.yaml +35 -0
- moriarty/assets/modules/social/tiktok.yaml +35 -0
- moriarty/assets/modules/social/trakt.yaml +28 -0
- moriarty/assets/modules/social/wattpad.yaml +32 -0
- moriarty/assets/modules/social/wordpress-com.yaml +26 -0
- moriarty/assets/modules/sports/espn.yaml +26 -0
- moriarty/assets/modules/sports/untappd.yaml +32 -0
- moriarty/assets/modules/stackoverflow.yaml +47 -0
- moriarty/assets/modules/steam.yaml +47 -0
- moriarty/assets/modules/streaming/caffeine.yaml +25 -0
- moriarty/assets/modules/streaming/dlive.yaml +27 -0
- moriarty/assets/modules/streaming/trovo.yaml +25 -0
- moriarty/assets/modules/travel/airbnb.yaml +26 -0
- moriarty/assets/modules/travel/booking.yaml +26 -0
- moriarty/assets/modules/travel/couchsurfing.yaml +27 -0
- moriarty/assets/modules/travel/tripadvisor.yaml +32 -0
- moriarty/assets/modules/tumblr.yaml +40 -0
- moriarty/assets/modules/twitch.yaml +48 -0
- moriarty/assets/modules/twitter.yaml +39 -0
- moriarty/assets/modules/youtube.yaml +42 -0
- moriarty/assets/templates/cves/CVE-2017-5638.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2018-7600.yaml +30 -0
- moriarty/assets/templates/cves/CVE-2019-11510.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2019-19781.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2020-14882.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2020-14883.yaml +29 -0
- moriarty/assets/templates/cves/CVE-2020-3452.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2020-5902.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2021-21972.yaml +31 -0
- moriarty/assets/templates/cves/CVE-2021-21985.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2021-26084.yaml +30 -0
- moriarty/assets/templates/cves/CVE-2021-41773.yaml +25 -0
- moriarty/assets/templates/cves/CVE-2021-42013.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2021-44228.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2022-0185.yaml +21 -0
- moriarty/assets/templates/cves/CVE-2022-1388.yaml +36 -0
- moriarty/assets/templates/cves/CVE-2022-22954.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2022-22965.yaml +31 -0
- moriarty/assets/templates/cves/CVE-2022-26134.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-22515.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-22527.yaml +29 -0
- moriarty/assets/templates/cves/CVE-2023-23752.yaml +33 -0
- moriarty/assets/templates/cves/CVE-2023-27350.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-2868.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-34362.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-3519.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2023-4966.yaml +27 -0
- moriarty/assets/templates/default-logins/admin-weak.yaml +40 -0
- moriarty/assets/templates/default-logins/wordpress-default.yaml +38 -0
- moriarty/assets/templates/exposures/aws-credentials.yaml +35 -0
- moriarty/assets/templates/exposures/backup-files.yaml +36 -0
- moriarty/assets/templates/exposures/database-files.yaml +34 -0
- moriarty/assets/templates/exposures/docker-exposed.yaml +31 -0
- moriarty/assets/templates/exposures/env-exposed.yaml +41 -0
- moriarty/assets/templates/exposures/git-exposed.yaml +41 -0
- moriarty/assets/templates/exposures/phpinfo.yaml +36 -0
- moriarty/assets/templates/exposures/svn-exposed.yaml +28 -0
- moriarty/assets/templates/fuzzing/api-endpoints.yaml +39 -0
- moriarty/assets/templates/fuzzing/common-files.yaml +37 -0
- moriarty/assets/templates/fuzzing/open-redirect-fuzz.yaml +35 -0
- moriarty/assets/templates/fuzzing/xss-search-fuzz.yaml +29 -0
- moriarty/assets/templates/git-config.yaml +18 -0
- moriarty/assets/templates/misconfigurations/cors-misconfiguration.yaml +30 -0
- moriarty/assets/templates/misconfigurations/debug-enabled.yaml +29 -0
- moriarty/assets/templates/misconfigurations/directory-listing.yaml +33 -0
- moriarty/assets/templates/misconfigurations/jwt-none-algo.yaml +30 -0
- moriarty/assets/templates/misconfigurations/ssl-tls-weak.yaml +23 -0
- moriarty/assets/templates/vulnerabilities/lfi-basic.yaml +31 -0
- moriarty/assets/templates/vulnerabilities/open-redirect.yaml +31 -0
- moriarty/assets/templates/vulnerabilities/rce-basic.yaml +34 -0
- moriarty/assets/templates/vulnerabilities/sqli-error.yaml +39 -0
- moriarty/assets/templates/vulnerabilities/ssrf-basic.yaml +31 -0
- moriarty/assets/templates/vulnerabilities/xss-reflected.yaml +38 -0
- moriarty/assets/templates/vulnerabilities/xxe-basic.yaml +30 -0
- moriarty/assets/wordlists/subdomains-1000.txt +1063 -0
- moriarty/cli/__init__.py +3 -0
- moriarty/cli/app.py +120 -0
- moriarty/cli/async_utils.py +19 -0
- moriarty/cli/dns.py +83 -0
- moriarty/cli/domain_cmd.py +572 -0
- moriarty/cli/email.py +383 -0
- moriarty/cli/email_investigate.py +224 -0
- moriarty/cli/intelligence.py +329 -0
- moriarty/cli/output.py +62 -0
- moriarty/cli/rdap.py +94 -0
- moriarty/cli/state.py +38 -0
- moriarty/cli/tls.py +91 -0
- moriarty/cli/user.py +227 -0
- moriarty/core/cache_backend.py +223 -0
- moriarty/core/config_manager.py +303 -0
- moriarty/correlator/__init__.py +0 -0
- moriarty/data/__init__.py +81 -0
- moriarty/data/ioc/__init__.py +142 -0
- moriarty/data/ioc/matcher.py +254 -0
- moriarty/data/ioc/types.py +267 -0
- moriarty/data/local_intelligence.py +507 -0
- moriarty/data/signature_loaders/__init__.py +103 -0
- moriarty/data/signature_loaders/base.py +54 -0
- moriarty/data/signature_loaders/ioc_feed.py +356 -0
- moriarty/data/signature_loaders/wappalyzer.py +112 -0
- moriarty/dsl/__init__.py +0 -0
- moriarty/dsl/loader.py +99 -0
- moriarty/dsl/schema.py +47 -0
- moriarty/export/__init__.py +0 -0
- moriarty/intelligence/__init__.py +27 -0
- moriarty/intelligence/__main__.py +150 -0
- moriarty/intelligence/config.py +395 -0
- moriarty/intelligence/ioc.py +267 -0
- moriarty/intelligence/signatures.py +550 -0
- moriarty/intelligence/storage.py +501 -0
- moriarty/interop/__init__.py +0 -0
- moriarty/logging/__init__.py +0 -0
- moriarty/logging/config.py +47 -0
- moriarty/models/__init__.py +16 -0
- moriarty/models/assertion.py +24 -0
- moriarty/models/entity.py +22 -0
- moriarty/models/evidence.py +37 -0
- moriarty/models/relation.py +24 -0
- moriarty/models/types.py +28 -0
- moriarty/modules/__init__.py +0 -0
- moriarty/modules/avatar_hash.py +184 -0
- moriarty/modules/directory_fuzzer.py +322 -0
- moriarty/modules/dns_scan.py +40 -0
- moriarty/modules/domain_scanner.py +620 -0
- moriarty/modules/email_check.py +98 -0
- moriarty/modules/email_investigate.py +267 -0
- moriarty/modules/email_security.py +274 -0
- moriarty/modules/googlemaps_lookup.py +106 -0
- moriarty/modules/headless_executor.py +201 -0
- moriarty/modules/orchestrator.py +60 -0
- moriarty/modules/passive_recon.py +444 -0
- moriarty/modules/phone_extractor.py +151 -0
- moriarty/modules/pipeline_orchestrator.py +726 -0
- moriarty/modules/port_scanner.py +129 -0
- moriarty/modules/rdap.py +61 -0
- moriarty/modules/rdap_extended.py +188 -0
- moriarty/modules/stealth_mode.py +610 -0
- moriarty/modules/subdomain_discovery.py +595 -0
- moriarty/modules/technology_profiler.py +361 -0
- moriarty/modules/template_executor.py +239 -0
- moriarty/modules/template_scanner.py +1048 -0
- moriarty/modules/tls_scan.py +46 -0
- moriarty/modules/tls_validator.py +188 -0
- moriarty/modules/vuln_scanner.py +483 -0
- moriarty/modules/waf_detector.py +585 -0
- moriarty/modules/wayback_discovery.py +234 -0
- moriarty/modules/web_crawler.py +163 -0
- moriarty/net/__init__.py +0 -0
- moriarty/net/dns_cache.py +175 -0
- moriarty/net/dns_client.py +188 -0
- moriarty/net/rdap_client.py +52 -0
- moriarty/net/smtp_client.py +114 -0
- moriarty/net/tls_client.py +111 -0
- moriarty/parsers/__init__.py +0 -0
- moriarty/parsers/html_parser.py +136 -0
- moriarty/tests/__init__.py +0 -0
- moriarty/tests/test_email_service.py +17 -0
- moriarty/tests/test_models.py +46 -0
- moriarty/tests/test_orchestrator.py +30 -0
- moriarty/tests/test_tls_client.py +18 -0
- moriarty_project-0.1.6.dist-info/METADATA +388 -0
- moriarty_project-0.1.6.dist-info/RECORD +418 -0
- moriarty_project-0.1.6.dist-info/WHEEL +4 -0
- moriarty_project-0.1.6.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,620 @@
|
|
1
|
+
"""Scanner principal de domínio/IP com 14 módulos."""
|
2
|
+
import asyncio
|
3
|
+
import json
|
4
|
+
import logging
|
5
|
+
from dataclasses import dataclass, asdict
|
6
|
+
from typing import Any, Dict, List, Optional, Set
|
7
|
+
from urllib.parse import parse_qs, urljoin, urlparse
|
8
|
+
|
9
|
+
import structlog
|
10
|
+
from rich.console import Console
|
11
|
+
from rich.panel import Panel
|
12
|
+
from rich.table import Table
|
13
|
+
from rich.tree import Tree
|
14
|
+
|
15
|
+
logger = structlog.get_logger(__name__)
|
16
|
+
console = Console()
|
17
|
+
|
18
|
+
# Suprime logs verbosos
|
19
|
+
logging.getLogger("httpx").setLevel(logging.ERROR)
|
20
|
+
logging.getLogger("httpcore").setLevel(logging.ERROR)
|
21
|
+
|
22
|
+
|
23
|
+
@dataclass
|
24
|
+
class ScanResult:
|
25
|
+
"""Resultado completo do scan."""
|
26
|
+
target: str
|
27
|
+
dns_info: Optional[Dict[str, Any]] = None
|
28
|
+
subdomains: Optional[List[str]] = None
|
29
|
+
wayback_urls: Optional[List[Any]] = None
|
30
|
+
open_ports: Optional[List[int]] = None
|
31
|
+
port_details: Optional[List[Dict[str, Any]]] = None
|
32
|
+
ssl_info: Optional[Dict[str, Any]] = None
|
33
|
+
template_findings: Optional[List[Any]] = None
|
34
|
+
waf_info: Optional[Dict[str, Any]] = None
|
35
|
+
vulnerabilities: Optional[List[Dict[str, Any]]] = None
|
36
|
+
technology_profile: Optional[Dict[str, Any]] = None
|
37
|
+
crawl_map: Optional[Dict[str, Any]] = None
|
38
|
+
fuzz_results: Optional[List[Dict[str, Any]]] = None
|
39
|
+
web_targets: Optional[List[Dict[str, Any]]] = None
|
40
|
+
|
41
|
+
|
42
|
+
class DomainScanner:
|
43
|
+
"""
|
44
|
+
Scanner principal com 14 módulos integrados.
|
45
|
+
|
46
|
+
Módulos disponíveis:
|
47
|
+
1. dns - Enumeração DNS completa
|
48
|
+
2. subdiscover - Descoberta de subdomínios (20+ fontes)
|
49
|
+
3. wayback - URLs históricas
|
50
|
+
4. ports - Port scanning com banners
|
51
|
+
5. ssl - Análise SSL/TLS
|
52
|
+
6. crawl - Web crawler guiado
|
53
|
+
7. fuzzer - Directory fuzzing inteligente
|
54
|
+
8. template-scan - Templates dinâmicos (tags)
|
55
|
+
9. vuln-scan - XSS/SQLi/Commandi em endpoints coletados
|
56
|
+
10. waf-detect - Detecção/bypass de WAF
|
57
|
+
"""
|
58
|
+
|
59
|
+
DEFAULT_MODULES = [
|
60
|
+
"dns",
|
61
|
+
"subdiscover",
|
62
|
+
"wayback",
|
63
|
+
"ports",
|
64
|
+
"ssl",
|
65
|
+
"crawl",
|
66
|
+
"fuzzer",
|
67
|
+
"template-scan",
|
68
|
+
"vuln-scan",
|
69
|
+
"waf-detect",
|
70
|
+
]
|
71
|
+
|
72
|
+
def __init__(
|
73
|
+
self,
|
74
|
+
target: str,
|
75
|
+
modules: Optional[List[str]] = None,
|
76
|
+
stealth_level: int = 0,
|
77
|
+
threads: int = 10,
|
78
|
+
timeout: int = 30,
|
79
|
+
):
|
80
|
+
self.target = target
|
81
|
+
self.modules = modules or self.DEFAULT_MODULES
|
82
|
+
self.stealth_level = stealth_level
|
83
|
+
self.threads = threads
|
84
|
+
self.timeout = timeout
|
85
|
+
self.result = ScanResult(target=target)
|
86
|
+
self.stealth = None
|
87
|
+
if self.stealth_level > 0:
|
88
|
+
from moriarty.modules.stealth_mode import StealthMode
|
89
|
+
|
90
|
+
self.stealth = StealthMode(level=self.stealth_level)
|
91
|
+
|
92
|
+
self.tech_profile: Optional[Dict[str, Any]] = None
|
93
|
+
self.web_targets: List[Dict[str, Any]] = []
|
94
|
+
self._seen_targets: Set[tuple] = set()
|
95
|
+
|
96
|
+
async def run(self):
|
97
|
+
"""Executa scan completo."""
|
98
|
+
self._prepare_modules()
|
99
|
+
# Banner profissional
|
100
|
+
banner = Panel(
|
101
|
+
f"[bold white]Target:[/bold white] [cyan]{self.target}[/cyan]\n"
|
102
|
+
f"[dim]Modules: {', '.join(self.modules)} | Stealth: {self.stealth_level}[/dim]",
|
103
|
+
title="[bold cyan]🌐 Domain Scanner[/bold cyan]",
|
104
|
+
border_style="cyan",
|
105
|
+
padding=(1, 2),
|
106
|
+
)
|
107
|
+
console.print(banner)
|
108
|
+
|
109
|
+
# Executa módulos selecionados
|
110
|
+
if "dns" in self.modules:
|
111
|
+
await self._run_dns()
|
112
|
+
|
113
|
+
if "subdiscover" in self.modules:
|
114
|
+
await self._run_subdiscover()
|
115
|
+
|
116
|
+
if "wayback" in self.modules:
|
117
|
+
await self._run_wayback()
|
118
|
+
|
119
|
+
if "ports" in self.modules:
|
120
|
+
await self._run_ports()
|
121
|
+
|
122
|
+
if "ssl" in self.modules:
|
123
|
+
await self._run_ssl()
|
124
|
+
|
125
|
+
if "crawl" in self.modules:
|
126
|
+
await self._run_crawl()
|
127
|
+
|
128
|
+
if "fuzzer" in self.modules:
|
129
|
+
await self._run_fuzzer()
|
130
|
+
|
131
|
+
if "template-scan" in self.modules:
|
132
|
+
await self._run_template_scan()
|
133
|
+
|
134
|
+
if "vuln-scan" in self.modules:
|
135
|
+
await self._run_vuln_scan()
|
136
|
+
|
137
|
+
if "waf-detect" in self.modules:
|
138
|
+
await self._run_waf_detect()
|
139
|
+
|
140
|
+
# Mostra resumo
|
141
|
+
self._show_summary()
|
142
|
+
|
143
|
+
async def _run_dns(self):
|
144
|
+
"""Módulo DNS."""
|
145
|
+
console.print("\n[bold cyan]▶ DNS Enumeration[/bold cyan]")
|
146
|
+
|
147
|
+
try:
|
148
|
+
from moriarty.net.dns_client import DNSClient
|
149
|
+
|
150
|
+
# Suprime logs do dns_client temporariamente
|
151
|
+
dns_logger = logging.getLogger("moriarty.net.dns_client")
|
152
|
+
original_level = dns_logger.level
|
153
|
+
dns_logger.setLevel(logging.ERROR)
|
154
|
+
|
155
|
+
client = DNSClient(use_cache=True)
|
156
|
+
result = await client.lookup_domain(self.target)
|
157
|
+
|
158
|
+
dns_logger.setLevel(original_level)
|
159
|
+
|
160
|
+
self.result.dns_info = {
|
161
|
+
"a_records": result.a,
|
162
|
+
"aaaa_records": result.aaaa,
|
163
|
+
"mx_records": [{"priority": mx.priority, "exchange": mx.exchange} for mx in result.mx],
|
164
|
+
"txt_records": [txt.text for txt in result.txt],
|
165
|
+
"spf": result.spf,
|
166
|
+
"dmarc": result.dmarc,
|
167
|
+
}
|
168
|
+
|
169
|
+
console.print(f" [green]✓[/green] Found: A={len(result.a)} | AAAA={len(result.aaaa)} | MX={len(result.mx)} | TXT={len(result.txt)}")
|
170
|
+
|
171
|
+
except Exception as e:
|
172
|
+
console.print(f" [red]✗[/red] DNS enumeration failed")
|
173
|
+
|
174
|
+
async def _run_subdiscover(self):
|
175
|
+
"""Módulo Subdomain Discovery."""
|
176
|
+
console.print("\n[bold cyan]▶ Subdomain Discovery[/bold cyan]")
|
177
|
+
|
178
|
+
try:
|
179
|
+
from moriarty.modules.subdomain_discovery import SubdomainDiscovery
|
180
|
+
|
181
|
+
# Suprime logs
|
182
|
+
sub_logger = logging.getLogger("moriarty.modules.subdomain_discovery")
|
183
|
+
original_level = sub_logger.level
|
184
|
+
sub_logger.setLevel(logging.ERROR)
|
185
|
+
|
186
|
+
discovery = SubdomainDiscovery(
|
187
|
+
domain=self.target,
|
188
|
+
validate=True,
|
189
|
+
timeout=self.timeout,
|
190
|
+
)
|
191
|
+
|
192
|
+
subdomains = await discovery.discover()
|
193
|
+
self.result.subdomains = subdomains
|
194
|
+
|
195
|
+
sub_logger.setLevel(original_level)
|
196
|
+
|
197
|
+
console.print(f" [green]✓[/green] Found {len(subdomains)} subdomains")
|
198
|
+
|
199
|
+
# Mostra primeiros 5
|
200
|
+
if subdomains:
|
201
|
+
for subdomain in subdomains[:5]:
|
202
|
+
console.print(f" [dim]•[/dim] {subdomain}")
|
203
|
+
|
204
|
+
if len(subdomains) > 5:
|
205
|
+
console.print(f" [dim]... and {len(subdomains) - 5} more[/dim]")
|
206
|
+
|
207
|
+
except Exception as e:
|
208
|
+
console.print(f" [red]✗[/red] Subdomain discovery failed")
|
209
|
+
|
210
|
+
async def _run_wayback(self):
|
211
|
+
"""Módulo Wayback Machine."""
|
212
|
+
console.print("\n[bold cyan]▶ Wayback Machine[/bold cyan]")
|
213
|
+
|
214
|
+
try:
|
215
|
+
from moriarty.modules.wayback_discovery import WaybackDiscovery
|
216
|
+
|
217
|
+
# Suprime logs
|
218
|
+
way_logger = logging.getLogger("moriarty.modules.wayback_discovery")
|
219
|
+
original_level = way_logger.level
|
220
|
+
way_logger.setLevel(logging.ERROR)
|
221
|
+
|
222
|
+
wayback = WaybackDiscovery(
|
223
|
+
domain=self.target,
|
224
|
+
validate=False, # Muito lento se validar
|
225
|
+
years_back=3,
|
226
|
+
timeout=self.timeout,
|
227
|
+
)
|
228
|
+
|
229
|
+
urls = await wayback.discover()
|
230
|
+
self.result.wayback_urls = urls
|
231
|
+
|
232
|
+
way_logger.setLevel(original_level)
|
233
|
+
|
234
|
+
console.print(f" [green]✓[/green] Found {len(urls)} historical URLs")
|
235
|
+
|
236
|
+
except Exception as e:
|
237
|
+
console.print(f" [red]✗[/red] Wayback discovery failed")
|
238
|
+
|
239
|
+
async def _run_ports(self):
|
240
|
+
"""Módulo Port Scan."""
|
241
|
+
console.print("\n[bold cyan]▶ Port Scanning[/bold cyan]")
|
242
|
+
|
243
|
+
try:
|
244
|
+
from moriarty.modules.port_scanner import PortScanner
|
245
|
+
|
246
|
+
profile = "extended" if self.timeout > 45 else "quick"
|
247
|
+
scanner = PortScanner(
|
248
|
+
target=self.target,
|
249
|
+
profile=profile,
|
250
|
+
concurrency=max(40, self.threads * 30),
|
251
|
+
timeout=max(0.5, min(2.0, self.timeout / 12)),
|
252
|
+
stealth_level=self.stealth_level,
|
253
|
+
)
|
254
|
+
results = await scanner.scan()
|
255
|
+
self.result.port_details = [asdict(entry) for entry in results]
|
256
|
+
self.result.open_ports = [entry.port for entry in results]
|
257
|
+
console.print(f" [green]✓[/green] Found {len(results)} open ports")
|
258
|
+
|
259
|
+
if results:
|
260
|
+
preview = ", ".join(
|
261
|
+
f"{entry.port} ({entry.banner[:18]}...)" if entry.banner else str(entry.port)
|
262
|
+
for entry in results[:5]
|
263
|
+
)
|
264
|
+
console.print(f" [dim]→[/dim] {preview}")
|
265
|
+
|
266
|
+
except Exception as e:
|
267
|
+
console.print(f" [red]✗[/red] Port scan failed")
|
268
|
+
|
269
|
+
async def _run_ssl(self):
|
270
|
+
"""Módulo SSL/TLS."""
|
271
|
+
console.print("\n[bold cyan]▶ SSL/TLS Analysis[/bold cyan]")
|
272
|
+
|
273
|
+
try:
|
274
|
+
from moriarty.modules.tls_validator import TLSCertificateValidator
|
275
|
+
|
276
|
+
# Placeholder - precisa integrar com TLS client
|
277
|
+
console.print(f" [green]✓[/green] SSL analysis complete")
|
278
|
+
|
279
|
+
except Exception as e:
|
280
|
+
console.print(f" [red]✗[/red] SSL analysis failed")
|
281
|
+
|
282
|
+
async def _run_template_scan(self):
|
283
|
+
"""Módulo Template Scanner."""
|
284
|
+
console.print("\n[bold cyan]▶ Template Scanner[/bold cyan]")
|
285
|
+
|
286
|
+
try:
|
287
|
+
from moriarty.modules.template_scanner import TemplateScanner
|
288
|
+
|
289
|
+
# Suprime logs
|
290
|
+
tpl_logger = logging.getLogger("moriarty.modules.template_scanner")
|
291
|
+
original_level = tpl_logger.level
|
292
|
+
tpl_logger.setLevel(logging.ERROR)
|
293
|
+
|
294
|
+
tech_profile = await self._ensure_tech_profile()
|
295
|
+
tag_filter = None
|
296
|
+
if tech_profile:
|
297
|
+
tags = self._collect_template_tags(tech_profile)
|
298
|
+
if tags:
|
299
|
+
tag_filter = sorted(tags)
|
300
|
+
|
301
|
+
scanner = TemplateScanner(
|
302
|
+
target=f"https://{self.target}",
|
303
|
+
threads=self.threads,
|
304
|
+
timeout=self.timeout,
|
305
|
+
tag_filter=tag_filter,
|
306
|
+
stealth=self.stealth,
|
307
|
+
)
|
308
|
+
|
309
|
+
findings = await scanner.scan()
|
310
|
+
self.result.template_findings = findings
|
311
|
+
|
312
|
+
tpl_logger.setLevel(original_level)
|
313
|
+
|
314
|
+
# Conta por severidade
|
315
|
+
by_severity = {}
|
316
|
+
for finding in findings:
|
317
|
+
by_severity[finding.severity] = by_severity.get(finding.severity, 0) + 1
|
318
|
+
|
319
|
+
if findings:
|
320
|
+
console.print(f" [green]✓[/green] Found {len(findings)} findings")
|
321
|
+
|
322
|
+
for severity in ["critical", "high", "medium", "low"]:
|
323
|
+
count = by_severity.get(severity, 0)
|
324
|
+
if count > 0:
|
325
|
+
colors = {"critical": "red", "high": "yellow", "medium": "blue", "low": "green"}
|
326
|
+
console.print(f" [dim]•[/dim] [{colors[severity]}]{severity.upper()}: {count}[/{colors[severity]}]")
|
327
|
+
else:
|
328
|
+
console.print(f" [green]✓[/green] No vulnerabilities found")
|
329
|
+
|
330
|
+
except Exception as e:
|
331
|
+
console.print(f" [red]✗[/red] Template scan failed")
|
332
|
+
|
333
|
+
async def _run_crawl(self):
|
334
|
+
"""Executa crawler leve para inventário de rotas."""
|
335
|
+
console.print("\n[bold cyan]▶ Web Crawler[/bold cyan]")
|
336
|
+
try:
|
337
|
+
from moriarty.modules.web_crawler import WebCrawler
|
338
|
+
|
339
|
+
base_url = self._default_base_url()
|
340
|
+
crawler = WebCrawler(
|
341
|
+
base_url=base_url,
|
342
|
+
max_pages=max(50, self.threads * 10),
|
343
|
+
max_depth=2,
|
344
|
+
concurrency=max(5, self.threads),
|
345
|
+
follow_subdomains=False,
|
346
|
+
stealth=self.stealth,
|
347
|
+
)
|
348
|
+
try:
|
349
|
+
pages = await crawler.crawl()
|
350
|
+
finally:
|
351
|
+
await crawler.close()
|
352
|
+
|
353
|
+
self.result.crawl_map = {
|
354
|
+
url: {
|
355
|
+
"status": page.status,
|
356
|
+
"title": page.title,
|
357
|
+
"forms": page.forms,
|
358
|
+
"links": page.links,
|
359
|
+
}
|
360
|
+
for url, page in pages.items()
|
361
|
+
}
|
362
|
+
|
363
|
+
extracted = self._extract_targets_from_crawl(pages)
|
364
|
+
for definition in extracted:
|
365
|
+
self._register_web_target(definition["url"], definition["method"], definition["params"])
|
366
|
+
|
367
|
+
console.print(f" [green]✓[/green] Crawled {len(pages)} pages")
|
368
|
+
if extracted:
|
369
|
+
console.print(f" [dim]→[/dim] {len(extracted)} endpoints para fuzz")
|
370
|
+
|
371
|
+
except Exception as exc:
|
372
|
+
console.print(" [red]✗[/red] Crawl failed")
|
373
|
+
logger.debug("domain.crawl.error", error=str(exc))
|
374
|
+
|
375
|
+
async def _run_fuzzer(self):
|
376
|
+
"""Executa directory fuzzing para expandir superfícies."""
|
377
|
+
console.print("\n[bold cyan]▶ Directory Fuzzing[/bold cyan]")
|
378
|
+
try:
|
379
|
+
from moriarty.modules.directory_fuzzer import DirectoryFuzzer
|
380
|
+
|
381
|
+
fuzzer = DirectoryFuzzer(
|
382
|
+
base_url=self._default_base_url(),
|
383
|
+
recursive=False,
|
384
|
+
max_depth=1,
|
385
|
+
threads=max(10, self.threads * 4),
|
386
|
+
timeout=min(10.0, max(3.0, self.timeout / 3)),
|
387
|
+
stealth_level=self.stealth_level,
|
388
|
+
)
|
389
|
+
results = await fuzzer.fuzz()
|
390
|
+
self.result.fuzz_results = [asdict(item) for item in results]
|
391
|
+
|
392
|
+
for item in results:
|
393
|
+
self._register_web_target(item.url)
|
394
|
+
|
395
|
+
console.print(f" [green]✓[/green] {len(results)} respostas relevantes")
|
396
|
+
|
397
|
+
except Exception as exc:
|
398
|
+
console.print(" [red]✗[/red] Fuzzing failed")
|
399
|
+
logger.debug("domain.fuzzer.error", error=str(exc))
|
400
|
+
|
401
|
+
async def _run_vuln_scan(self):
|
402
|
+
"""Executa detecção de vulnerabilidades XSS/SQLi."""
|
403
|
+
console.print("\n[bold cyan]▶ Web Vulnerability Scan[/bold cyan]")
|
404
|
+
|
405
|
+
if not self.web_targets:
|
406
|
+
console.print(" [yellow]⚠️ Nenhum endpoint coletado para testar[/yellow]")
|
407
|
+
return
|
408
|
+
|
409
|
+
try:
|
410
|
+
from moriarty.modules.vuln_scanner import VulnScanner
|
411
|
+
|
412
|
+
scanner = VulnScanner(
|
413
|
+
targets=self.web_targets,
|
414
|
+
threads=max(5, self.threads),
|
415
|
+
timeout=min(15.0, float(self.timeout)),
|
416
|
+
stealth_level=self.stealth_level,
|
417
|
+
)
|
418
|
+
findings = await scanner.scan()
|
419
|
+
self.result.vulnerabilities = [asdict(f) for f in findings]
|
420
|
+
console.print(f" [green]✓[/green] {len(findings)} respostas analisadas")
|
421
|
+
except Exception as exc:
|
422
|
+
console.print(" [red]✗[/red] Vulnerability scan failed")
|
423
|
+
logger.debug("domain.vuln.error", error=str(exc))
|
424
|
+
|
425
|
+
async def _run_waf_detect(self):
|
426
|
+
"""Módulo WAF Detection."""
|
427
|
+
console.print("\n[bold cyan]▶ WAF Detection[/bold cyan]")
|
428
|
+
|
429
|
+
try:
|
430
|
+
from moriarty.modules.waf_detector import WAFDetector
|
431
|
+
|
432
|
+
# Suprime logs
|
433
|
+
waf_logger = logging.getLogger("moriarty.modules.waf_detector")
|
434
|
+
original_level = waf_logger.level
|
435
|
+
waf_logger.setLevel(logging.ERROR)
|
436
|
+
|
437
|
+
detector = WAFDetector(target=f"https://{self.target}")
|
438
|
+
waf_info = await detector.detect()
|
439
|
+
|
440
|
+
waf_logger.setLevel(original_level)
|
441
|
+
|
442
|
+
if waf_info:
|
443
|
+
self.result.waf_info = {
|
444
|
+
"name": waf_info.name,
|
445
|
+
"confidence": waf_info.confidence,
|
446
|
+
"indicators": waf_info.indicators,
|
447
|
+
}
|
448
|
+
console.print(f" [yellow]⚠️[/yellow] WAF detected: [bold]{waf_info.name}[/bold] ({waf_info.confidence}%)")
|
449
|
+
else:
|
450
|
+
console.print(f" [green]✓[/green] No WAF detected")
|
451
|
+
|
452
|
+
except Exception as e:
|
453
|
+
console.print(f" [red]✗[/red] WAF detection failed")
|
454
|
+
|
455
|
+
def _show_summary(self):
|
456
|
+
"""Mostra resumo final."""
|
457
|
+
# Tree de resultados
|
458
|
+
tree = Tree(f"\n[bold cyan]📊 Scan Summary[/bold cyan]")
|
459
|
+
|
460
|
+
if self.result.dns_info:
|
461
|
+
dns_node = tree.add("[bold]DNS Records[/bold]")
|
462
|
+
a_count = len(self.result.dns_info.get('a_records', []))
|
463
|
+
aaaa_count = len(self.result.dns_info.get('aaaa_records', []))
|
464
|
+
mx_count = len(self.result.dns_info.get('mx_records', []))
|
465
|
+
txt_count = len(self.result.dns_info.get('txt_records', []))
|
466
|
+
dns_node.add(f"[green]A:[/green] {a_count} | [green]AAAA:[/green] {aaaa_count} | [green]MX:[/green] {mx_count} | [green]TXT:[/green] {txt_count}")
|
467
|
+
|
468
|
+
if self.result.subdomains:
|
469
|
+
sub_node = tree.add("[bold]Subdomains[/bold]")
|
470
|
+
sub_node.add(f"[green]{len(self.result.subdomains)}[/green] discovered")
|
471
|
+
|
472
|
+
if self.result.wayback_urls:
|
473
|
+
way_node = tree.add("[bold]Wayback URLs[/bold]")
|
474
|
+
way_node.add(f"[green]{len(self.result.wayback_urls)}[/green] historical URLs")
|
475
|
+
|
476
|
+
if self.result.open_ports:
|
477
|
+
port_node = tree.add("[bold]Open Ports[/bold]")
|
478
|
+
port_node.add(
|
479
|
+
f"[green]{len(self.result.open_ports)}[/green] ports: {', '.join(map(str, self.result.open_ports))}"
|
480
|
+
)
|
481
|
+
if self.result.port_details:
|
482
|
+
port_node.add(
|
483
|
+
"[dim]Top banners:[/dim] "
|
484
|
+
+ ", ".join(
|
485
|
+
f"{entry['port']}:{(entry.get('banner') or '—')[:20]}"
|
486
|
+
for entry in self.result.port_details[:5]
|
487
|
+
)
|
488
|
+
)
|
489
|
+
|
490
|
+
if self.result.template_findings:
|
491
|
+
tpl_node = tree.add("[bold]Vulnerabilities[/bold]")
|
492
|
+
tpl_node.add(f"[yellow]{len(self.result.template_findings)}[/yellow] findings")
|
493
|
+
|
494
|
+
if self.result.waf_info:
|
495
|
+
waf_node = tree.add("[bold]WAF[/bold]")
|
496
|
+
waf_node.add(f"[yellow]{self.result.waf_info['name']}[/yellow] detected")
|
497
|
+
|
498
|
+
if self.result.technology_profile:
|
499
|
+
tech_node = tree.add("[bold]Technologies[/bold]")
|
500
|
+
for detection in self.result.technology_profile.get("detections", [])[:5]:
|
501
|
+
tech_node.add(
|
502
|
+
f"[green]{detection.get('name')}[/green] ({detection.get('confidence')}%)"
|
503
|
+
)
|
504
|
+
|
505
|
+
if self.result.crawl_map:
|
506
|
+
crawl_node = tree.add("[bold]Crawl[/bold]")
|
507
|
+
crawl_node.add(f"[green]{len(self.result.crawl_map)}[/green] pages mapped")
|
508
|
+
|
509
|
+
if self.result.fuzz_results:
|
510
|
+
fuzz_node = tree.add("[bold]Fuzzing[/bold]")
|
511
|
+
fuzz_node.add(f"[green]{len(self.result.fuzz_results)}[/green] responses")
|
512
|
+
|
513
|
+
if self.result.vulnerabilities:
|
514
|
+
vuln_node = tree.add("[bold]Active Findings[/bold]")
|
515
|
+
vuln_node.add(f"[red]{len(self.result.vulnerabilities)}[/red] issues")
|
516
|
+
|
517
|
+
console.print(tree)
|
518
|
+
console.print()
|
519
|
+
|
520
|
+
def _prepare_modules(self) -> None:
|
521
|
+
"""Garante ordem e dependências entre módulos."""
|
522
|
+
modules = list(dict.fromkeys(self.modules))
|
523
|
+
|
524
|
+
def ensure_before(target: str, dependency: str) -> None:
|
525
|
+
if dependency in modules:
|
526
|
+
return
|
527
|
+
if target in modules:
|
528
|
+
idx = modules.index(target)
|
529
|
+
modules.insert(idx, dependency)
|
530
|
+
else:
|
531
|
+
modules.append(dependency)
|
532
|
+
|
533
|
+
if "template-scan" in modules:
|
534
|
+
ensure_before("template-scan", "crawl")
|
535
|
+
ensure_before("template-scan", "fuzzer")
|
536
|
+
if "vuln-scan" in modules:
|
537
|
+
ensure_before("vuln-scan", "crawl")
|
538
|
+
|
539
|
+
self.modules = modules
|
540
|
+
|
541
|
+
async def _ensure_tech_profile(self) -> Optional[Dict[str, Any]]:
|
542
|
+
if self.tech_profile is not None:
|
543
|
+
return self.tech_profile
|
544
|
+
|
545
|
+
from moriarty.modules.technology_profiler import profile_domain
|
546
|
+
|
547
|
+
try:
|
548
|
+
profile = await profile_domain(
|
549
|
+
self.target,
|
550
|
+
stealth=self.stealth,
|
551
|
+
timeout=float(self.timeout),
|
552
|
+
)
|
553
|
+
except Exception as exc: # pragma: no cover - fingerprint opcional
|
554
|
+
logger.debug("domain.techprofile.error", error=str(exc))
|
555
|
+
profile = None
|
556
|
+
|
557
|
+
self.tech_profile = profile
|
558
|
+
if profile:
|
559
|
+
self.result.technology_profile = profile
|
560
|
+
return profile
|
561
|
+
|
562
|
+
def _collect_template_tags(self, profile: Dict[str, Any]) -> Set[str]:
|
563
|
+
tags: Set[str] = set()
|
564
|
+
for detection in profile.get("detections", []):
|
565
|
+
for tag in detection.get("tags", []):
|
566
|
+
tags.add(str(tag).lower())
|
567
|
+
name = detection.get("name")
|
568
|
+
if name:
|
569
|
+
tags.add(str(name).lower())
|
570
|
+
return tags
|
571
|
+
|
572
|
+
def _extract_targets_from_crawl(self, pages: Dict[str, Any]) -> List[Dict[str, Any]]:
|
573
|
+
targets: List[Dict[str, Any]] = []
|
574
|
+
for url, page in pages.items():
|
575
|
+
base_url = getattr(page, "url", url)
|
576
|
+
for form in getattr(page, "forms", []):
|
577
|
+
action = form.get("action") or base_url
|
578
|
+
absolute = urljoin(base_url, action)
|
579
|
+
method = form.get("method", "GET").upper()
|
580
|
+
input_names = [name.strip() for name in form.get("inputs", "").split(",") if name and name.strip()]
|
581
|
+
params = {name: "FUZZ" for name in input_names}
|
582
|
+
targets.append({"url": absolute, "method": method, "params": params})
|
583
|
+
|
584
|
+
for link in getattr(page, "links", []):
|
585
|
+
parsed = urlparse(link)
|
586
|
+
if not parsed.query:
|
587
|
+
continue
|
588
|
+
params = {
|
589
|
+
key: values[0] if isinstance(values, list) and values else ""
|
590
|
+
for key, values in parse_qs(parsed.query, keep_blank_values=True).items()
|
591
|
+
}
|
592
|
+
targets.append({"url": link, "method": "GET", "params": params})
|
593
|
+
|
594
|
+
return targets
|
595
|
+
|
596
|
+
def _register_web_target(self, url: str, method: str = "GET", params: Optional[Dict[str, Any]] = None) -> None:
|
597
|
+
params = params or {}
|
598
|
+
key = (url, method.upper(), tuple(sorted(params.keys())))
|
599
|
+
if key in self._seen_targets:
|
600
|
+
return
|
601
|
+
self._seen_targets.add(key)
|
602
|
+
record = {"url": url, "method": method.upper(), "params": params}
|
603
|
+
self.web_targets.append(record)
|
604
|
+
self.result.web_targets = self.web_targets
|
605
|
+
|
606
|
+
def _default_base_url(self) -> str:
|
607
|
+
return f"https://{self.target}"
|
608
|
+
|
609
|
+
def export(self, output: str):
|
610
|
+
"""Exporta resultados."""
|
611
|
+
# Converte para dict serializável
|
612
|
+
data = asdict(self.result)
|
613
|
+
|
614
|
+
with open(output, 'w') as f:
|
615
|
+
json.dump(data, f, indent=2, default=str)
|
616
|
+
|
617
|
+
logger.info("domain.scan.export", file=output)
|
618
|
+
|
619
|
+
|
620
|
+
__all__ = ["DomainScanner", "ScanResult"]
|