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,356 @@
|
|
1
|
+
"""Carregador de feeds de IOCs (Indicadores de Comprometimento)."""
|
2
|
+
import json
|
3
|
+
import re
|
4
|
+
from datetime import datetime
|
5
|
+
from pathlib import Path
|
6
|
+
from typing import Dict, List, Any, Union, Optional, Pattern, Set
|
7
|
+
|
8
|
+
import yaml
|
9
|
+
import requests
|
10
|
+
from urllib.parse import urlparse
|
11
|
+
|
12
|
+
from .base import BaseSignatureLoader
|
13
|
+
|
14
|
+
class IOCFeedLoader(BaseSignatureLoader):
|
15
|
+
"""Carrega IOCs de várias fontes (JSON, CSV, MISP, etc.)."""
|
16
|
+
|
17
|
+
def __init__(self, source: Union[str, Path, Dict[str, Any]]):
|
18
|
+
super().__init__(source)
|
19
|
+
self.ioc_types = {
|
20
|
+
'ip': self._is_ip,
|
21
|
+
'domain': self._is_domain,
|
22
|
+
'url': self._is_url,
|
23
|
+
'hash': self._is_hash,
|
24
|
+
'email': self._is_email,
|
25
|
+
'cve': self._is_cve,
|
26
|
+
'btc': self._is_btc,
|
27
|
+
'md5': self._is_md5,
|
28
|
+
'sha1': self._is_sha1,
|
29
|
+
'sha256': self._is_sha256,
|
30
|
+
'ssdeep': self._is_ssdeep,
|
31
|
+
'yara': self._is_yara,
|
32
|
+
'snort': self._is_snort,
|
33
|
+
'suricata': self._is_suricata,
|
34
|
+
}
|
35
|
+
|
36
|
+
def load(self) -> List[Dict[str, Any]]:
|
37
|
+
"""Carrega IOCs da fonte especificada."""
|
38
|
+
if isinstance(self.source, (str, Path)) and str(self.source).startswith(('http://', 'https://')):
|
39
|
+
return self._load_from_url(self.source)
|
40
|
+
elif isinstance(self.source, (str, Path)):
|
41
|
+
return self._load_from_file(self.source)
|
42
|
+
elif isinstance(self.source, dict):
|
43
|
+
return self._load_from_dict(self.source)
|
44
|
+
else:
|
45
|
+
raise ValueError(f"Fonte de IOCs não suportada: {type(self.source)}")
|
46
|
+
|
47
|
+
def _load_from_url(self, url: str) -> List[Dict[str, Any]]:
|
48
|
+
"""Carrega IOCs de uma URL remota."""
|
49
|
+
try:
|
50
|
+
response = requests.get(url, timeout=30)
|
51
|
+
response.raise_for_status()
|
52
|
+
|
53
|
+
content_type = response.headers.get('content-type', '')
|
54
|
+
if 'json' in content_type:
|
55
|
+
return self._parse_json(response.json())
|
56
|
+
elif 'yaml' in content_type or 'x-yaml' in content_type:
|
57
|
+
return self._parse_yaml(response.text)
|
58
|
+
else:
|
59
|
+
# Tenta detectar o formato pelo conteúdo
|
60
|
+
try:
|
61
|
+
return self._parse_json(response.json())
|
62
|
+
except:
|
63
|
+
try:
|
64
|
+
return self._parse_yaml(response.text)
|
65
|
+
except:
|
66
|
+
return self._parse_text(response.text)
|
67
|
+
except Exception as e:
|
68
|
+
print(f"Erro ao carregar IOCs de {url}: {e}")
|
69
|
+
return []
|
70
|
+
|
71
|
+
def _load_from_file(self, file_path: Union[str, Path]) -> List[Dict[str, Any]]:
|
72
|
+
"""Carrega IOCs de um arquivo local."""
|
73
|
+
file_path = Path(file_path)
|
74
|
+
if not file_path.exists():
|
75
|
+
print(f"Arquivo não encontrado: {file_path}")
|
76
|
+
return []
|
77
|
+
|
78
|
+
try:
|
79
|
+
if file_path.suffix.lower() == '.json':
|
80
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
81
|
+
return self._parse_json(json.load(f))
|
82
|
+
elif file_path.suffix.lower() in ('.yaml', '.yml'):
|
83
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
84
|
+
return self._parse_yaml(f.read())
|
85
|
+
else:
|
86
|
+
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
87
|
+
return self._parse_text(f.read())
|
88
|
+
except Exception as e:
|
89
|
+
print(f"Erro ao processar arquivo {file_path}: {e}")
|
90
|
+
return []
|
91
|
+
|
92
|
+
def _load_from_dict(self, data: Dict[str, Any]) -> List[Dict[str, Any]]:
|
93
|
+
"""Carrega IOCs de um dicionário Python."""
|
94
|
+
if 'iocs' in data:
|
95
|
+
return self._parse_iocs(data['iocs'])
|
96
|
+
elif 'indicators' in data:
|
97
|
+
return self._parse_indicators(data['indicators'])
|
98
|
+
elif 'data' in data and isinstance(data['data'], list):
|
99
|
+
return self._parse_generic(data['data'])
|
100
|
+
else:
|
101
|
+
return self._parse_generic([data])
|
102
|
+
|
103
|
+
def _parse_json(self, data: Any) -> List[Dict[str, Any]]:
|
104
|
+
"""Analisa dados JSON."""
|
105
|
+
if isinstance(data, dict):
|
106
|
+
return self._load_from_dict(data)
|
107
|
+
elif isinstance(data, list):
|
108
|
+
return self._parse_generic(data)
|
109
|
+
else:
|
110
|
+
return []
|
111
|
+
|
112
|
+
def _parse_yaml(self, yaml_str: str) -> List[Dict[str, Any]]:
|
113
|
+
"""Analisa dados YAML."""
|
114
|
+
data = yaml.safe_load(yaml_str)
|
115
|
+
return self._parse_json(data)
|
116
|
+
|
117
|
+
def _parse_text(self, text: str) -> List[Dict[str, Any]]:
|
118
|
+
"""Analisa texto simples, um IOC por linha."""
|
119
|
+
iocs = []
|
120
|
+
for line in text.splitlines():
|
121
|
+
line = line.strip()
|
122
|
+
if not line or line.startswith('#'):
|
123
|
+
continue
|
124
|
+
|
125
|
+
ioc_type = self.detect_ioc_type(line)
|
126
|
+
if ioc_type:
|
127
|
+
iocs.append({
|
128
|
+
'type': ioc_type,
|
129
|
+
'value': line,
|
130
|
+
'source': 'text_import',
|
131
|
+
'first_seen': datetime.utcnow().isoformat(),
|
132
|
+
'last_seen': datetime.utcnow().isoformat(),
|
133
|
+
})
|
134
|
+
return iocs
|
135
|
+
|
136
|
+
def _parse_iocs(self, iocs: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
137
|
+
"""Analisa uma lista de IOCs no formato padrão."""
|
138
|
+
result = []
|
139
|
+
for ioc in iocs:
|
140
|
+
if not isinstance(ioc, dict):
|
141
|
+
continue
|
142
|
+
|
143
|
+
ioc_type = ioc.get('type')
|
144
|
+
value = ioc.get('value')
|
145
|
+
|
146
|
+
if not ioc_type or not value:
|
147
|
+
continue
|
148
|
+
|
149
|
+
result.append({
|
150
|
+
'type': ioc_type.lower(),
|
151
|
+
'value': value,
|
152
|
+
'threat_type': ioc.get('threat_type', 'unknown'),
|
153
|
+
'source': ioc.get('source', 'unknown'),
|
154
|
+
'first_seen': ioc.get('first_seen') or datetime.utcnow().isoformat(),
|
155
|
+
'last_seen': ioc.get('last_seen') or datetime.utcnow().isoformat(),
|
156
|
+
'confidence': int(ioc.get('confidence', 50)),
|
157
|
+
'metadata': ioc.get('metadata', {})
|
158
|
+
})
|
159
|
+
return result
|
160
|
+
|
161
|
+
def _parse_indicators(self, indicators: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
162
|
+
"""Analisa indicadores no formato MISP/STIX."""
|
163
|
+
result = []
|
164
|
+
for indicator in indicators:
|
165
|
+
if not isinstance(indicator, dict):
|
166
|
+
continue
|
167
|
+
|
168
|
+
ioc_type = indicator.get('type')
|
169
|
+
value = indicator.get('value')
|
170
|
+
|
171
|
+
if not ioc_type or not value:
|
172
|
+
continue
|
173
|
+
|
174
|
+
result.append({
|
175
|
+
'type': ioc_type.lower(),
|
176
|
+
'value': value,
|
177
|
+
'threat_type': indicator.get('threat_type', 'unknown'),
|
178
|
+
'source': 'misp' if 'misp' in str(indicator).lower() else 'stix',
|
179
|
+
'first_seen': indicator.get('first_seen') or datetime.utcnow().isoformat(),
|
180
|
+
'last_seen': indicator.get('last_seen') or datetime.utcnow().isoformat(),
|
181
|
+
'confidence': int(indicator.get('confidence', 50)),
|
182
|
+
'metadata': indicator.get('metadata', {})
|
183
|
+
})
|
184
|
+
return result
|
185
|
+
|
186
|
+
def _parse_generic(self, items: List[Any]) -> List[Dict[str, Any]]:
|
187
|
+
"""Tenta analisar uma lista genérica de itens."""
|
188
|
+
result = []
|
189
|
+
for item in items:
|
190
|
+
if not item:
|
191
|
+
continue
|
192
|
+
|
193
|
+
if isinstance(item, str):
|
194
|
+
ioc_type = self.detect_ioc_type(item)
|
195
|
+
if ioc_type:
|
196
|
+
result.append({
|
197
|
+
'type': ioc_type,
|
198
|
+
'value': item,
|
199
|
+
'source': 'generic_import',
|
200
|
+
'first_seen': datetime.utcnow().isoformat(),
|
201
|
+
'last_seen': datetime.utcnow().isoformat(),
|
202
|
+
})
|
203
|
+
elif isinstance(item, dict):
|
204
|
+
# Tenta extrair tipo e valor automaticamente
|
205
|
+
ioc_type = None
|
206
|
+
value = None
|
207
|
+
|
208
|
+
for key, val in item.items():
|
209
|
+
if not isinstance(val, str):
|
210
|
+
continue
|
211
|
+
|
212
|
+
detected_type = self.detect_ioc_type(val)
|
213
|
+
if detected_type:
|
214
|
+
ioc_type = detected_type
|
215
|
+
value = val
|
216
|
+
break
|
217
|
+
|
218
|
+
if ioc_type and value:
|
219
|
+
result.append({
|
220
|
+
'type': ioc_type,
|
221
|
+
'value': value,
|
222
|
+
'threat_type': item.get('threat_type', 'unknown'),
|
223
|
+
'source': item.get('source', 'generic_dict'),
|
224
|
+
'first_seen': item.get('first_seen') or datetime.utcnow().isoformat(),
|
225
|
+
'last_seen': item.get('last_seen') or datetime.utcnow().isoformat(),
|
226
|
+
'confidence': int(item.get('confidence', 50)),
|
227
|
+
'metadata': {k: v for k, v in item.items()
|
228
|
+
if k not in {'type', 'value', 'threat_type',
|
229
|
+
'source', 'first_seen', 'last_seen', 'confidence'}}
|
230
|
+
})
|
231
|
+
return result
|
232
|
+
|
233
|
+
def detect_ioc_type(self, value: str) -> Optional[str]:
|
234
|
+
"""Detecta o tipo de IOC com base no valor."""
|
235
|
+
if not value or not isinstance(value, str):
|
236
|
+
return None
|
237
|
+
|
238
|
+
value = value.strip()
|
239
|
+
|
240
|
+
# Verifica cada tipo de IOC conhecido
|
241
|
+
for ioc_type, check_func in self.ioc_types.items():
|
242
|
+
if check_func(value):
|
243
|
+
return ioc_type
|
244
|
+
|
245
|
+
return None
|
246
|
+
|
247
|
+
# Funções de verificação de tipos de IOC
|
248
|
+
|
249
|
+
@staticmethod
|
250
|
+
def _is_ip(value: str) -> bool:
|
251
|
+
"""Verifica se o valor é um endereço IP."""
|
252
|
+
import ipaddress
|
253
|
+
try:
|
254
|
+
ipaddress.ip_address(value)
|
255
|
+
return True
|
256
|
+
except ValueError:
|
257
|
+
return False
|
258
|
+
|
259
|
+
@staticmethod
|
260
|
+
def _is_domain(value: str) -> bool:
|
261
|
+
"""Verifica se o valor é um domínio válido."""
|
262
|
+
if not value or len(value) > 253:
|
263
|
+
return False
|
264
|
+
|
265
|
+
# Verifica se é um domínio válido
|
266
|
+
domain_regex = r'^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$'
|
267
|
+
return bool(re.match(domain_regex, value))
|
268
|
+
|
269
|
+
@staticmethod
|
270
|
+
def _is_url(value: str) -> bool:
|
271
|
+
"""Verifica se o valor é uma URL válida."""
|
272
|
+
try:
|
273
|
+
result = urlparse(value)
|
274
|
+
return all([result.scheme in ('http', 'https', 'ftp', 'ftps'),
|
275
|
+
result.netloc])
|
276
|
+
except:
|
277
|
+
return False
|
278
|
+
|
279
|
+
@staticmethod
|
280
|
+
def _is_hash(value: str) -> bool:
|
281
|
+
"""Verifica se o valor é um hash conhecido."""
|
282
|
+
if not value:
|
283
|
+
return False
|
284
|
+
|
285
|
+
# MD5 (32 caracteres hexadecimais)
|
286
|
+
if re.match(r'^[a-fA-F0-9]{32}$', value):
|
287
|
+
return True
|
288
|
+
|
289
|
+
# SHA-1 (40 caracteres hexadecimais)
|
290
|
+
if re.match(r'^[a-fA-F0-9]{40}$', value):
|
291
|
+
return True
|
292
|
+
|
293
|
+
# SHA-256 (64 caracteres hexadecimais)
|
294
|
+
if re.match(r'^[a-fA-F0-9]{64}$', value):
|
295
|
+
return True
|
296
|
+
|
297
|
+
# SHA-512 (128 caracteres hexadecimais)
|
298
|
+
if re.match(r'^[a-fA-F0-9]{128}$', value):
|
299
|
+
return True
|
300
|
+
|
301
|
+
return False
|
302
|
+
|
303
|
+
@staticmethod
|
304
|
+
def _is_email(value: str) -> bool:
|
305
|
+
"""Verifica se o valor é um endereço de e-mail válido."""
|
306
|
+
email_regex = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
307
|
+
return bool(re.match(email_regex, value))
|
308
|
+
|
309
|
+
@staticmethod
|
310
|
+
def _is_cve(value: str) -> bool:
|
311
|
+
"""Verifica se o valor é um CVE (Common Vulnerabilities and Exposures)."""
|
312
|
+
cve_regex = r'^CVE-\d{4}-\d{4,}$'
|
313
|
+
return bool(re.match(cve_regex, value, re.IGNORECASE))
|
314
|
+
|
315
|
+
@staticmethod
|
316
|
+
def _is_btc(value: str) -> bool:
|
317
|
+
"""Verifica se o valor é um endereço Bitcoin."""
|
318
|
+
# Endereços Bitcoin podem começar com 1, 3 ou bc1
|
319
|
+
btc_regex = r'^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$|^bc1[ac-hj-np-zAC-HJ-NP-Z02-9]{11,71}$'
|
320
|
+
return bool(re.match(btc_regex, value))
|
321
|
+
|
322
|
+
@staticmethod
|
323
|
+
def _is_md5(value: str) -> bool:
|
324
|
+
"""Verifica se o valor é um hash MD5."""
|
325
|
+
return bool(re.match(r'^[a-fA-F0-9]{32}$', value))
|
326
|
+
|
327
|
+
@staticmethod
|
328
|
+
def _is_sha1(value: str) -> bool:
|
329
|
+
"""Verifica se o valor é um hash SHA-1."""
|
330
|
+
return bool(re.match(r'^[a-fA-F0-9]{40}$', value))
|
331
|
+
|
332
|
+
@staticmethod
|
333
|
+
def _is_sha256(value: str) -> bool:
|
334
|
+
"""Verifica se o valor é um hash SHA-256."""
|
335
|
+
return bool(re.match(r'^[a-fA-F0-9]{64}$', value))
|
336
|
+
|
337
|
+
@staticmethod
|
338
|
+
def _is_ssdeep(value: str) -> bool:
|
339
|
+
"""Verifica se o valor é um hash ssdeep."""
|
340
|
+
# Formato: blocksize:hash:hash
|
341
|
+
return ':' in value and all(part for part in value.split(':'))
|
342
|
+
|
343
|
+
@staticmethod
|
344
|
+
def _is_yara(value: str) -> bool:
|
345
|
+
"""Verifica se o valor é uma regra YARA."""
|
346
|
+
return 'rule ' in value and '{' in value and '}' in value
|
347
|
+
|
348
|
+
@staticmethod
|
349
|
+
def _is_snort(value: str) -> bool:
|
350
|
+
"""Verifica se o valor é uma regra Snort."""
|
351
|
+
return value.strip().startswith('alert ') and ('->' in value or '<>' in value)
|
352
|
+
|
353
|
+
@staticmethod
|
354
|
+
def _is_suricata(value: str) -> bool:
|
355
|
+
"""Verifica se o valor é uma regra Suricata."""
|
356
|
+
return value.strip().startswith(('alert ', 'drop ', 'reject ')) and ';' in value
|
@@ -0,0 +1,112 @@
|
|
1
|
+
"""Carregador de assinaturas no formato Wappalyzer."""
|
2
|
+
import json
|
3
|
+
import re
|
4
|
+
from pathlib import Path
|
5
|
+
from typing import Dict, List, Any, Union, Optional, Pattern
|
6
|
+
|
7
|
+
import yaml
|
8
|
+
|
9
|
+
from .base import BaseSignatureLoader
|
10
|
+
|
11
|
+
class WappalyzerLoader(BaseSignatureLoader):
|
12
|
+
"""Carrega assinaturas no formato Wappalyzer (JSON)."""
|
13
|
+
|
14
|
+
def __init__(self, source: Union[str, Path, Dict[str, Any]]):
|
15
|
+
super().__init__(source)
|
16
|
+
self.pattern_cache: Dict[str, Pattern] = {}
|
17
|
+
|
18
|
+
def load(self) -> List[Dict[str, Any]]:
|
19
|
+
"""Carrega assinaturas do Wappalyzer."""
|
20
|
+
if isinstance(self.source, (str, Path)):
|
21
|
+
with open(self.source, 'r', encoding='utf-8') as f:
|
22
|
+
if str(self.source).endswith('.json'):
|
23
|
+
data = json.load(f)
|
24
|
+
else:
|
25
|
+
data = yaml.safe_load(f)
|
26
|
+
else:
|
27
|
+
data = self.source
|
28
|
+
|
29
|
+
signatures = []
|
30
|
+
for tech_name, tech_data in data.get('technologies', {}).items():
|
31
|
+
signatures.extend(self._parse_technology(tech_name, tech_data))
|
32
|
+
|
33
|
+
return signatures
|
34
|
+
|
35
|
+
def _parse_technology(self, name: str, data: Dict[str, Any]) -> List[Dict[str, Any]]:
|
36
|
+
"""Analisa uma tecnologia individual do Wappalyzer."""
|
37
|
+
signatures = []
|
38
|
+
|
39
|
+
# Categorias
|
40
|
+
categories = data.get('cats', [])
|
41
|
+
|
42
|
+
# URL
|
43
|
+
for url_pattern in data.get('url', []):
|
44
|
+
signatures.append({
|
45
|
+
'name': name,
|
46
|
+
'categories': categories,
|
47
|
+
'pattern_type': 'url',
|
48
|
+
'pattern': url_pattern,
|
49
|
+
'confidence': 80,
|
50
|
+
'source': 'wappalyzer'
|
51
|
+
})
|
52
|
+
|
53
|
+
# HTML
|
54
|
+
for html_pattern in data.get('html', []):
|
55
|
+
signatures.append({
|
56
|
+
'name': name,
|
57
|
+
'categories': categories,
|
58
|
+
'pattern_type': 'html',
|
59
|
+
'pattern': html_pattern,
|
60
|
+
'confidence': 80,
|
61
|
+
'source': 'wappalyzer'
|
62
|
+
})
|
63
|
+
|
64
|
+
# Headers
|
65
|
+
for header, patterns in data.get('headers', {}).items():
|
66
|
+
if isinstance(patterns, str):
|
67
|
+
patterns = [patterns]
|
68
|
+
for pattern in patterns:
|
69
|
+
signatures.append({
|
70
|
+
'name': name,
|
71
|
+
'categories': categories,
|
72
|
+
'pattern_type': 'header',
|
73
|
+
'pattern': f"{header}: {pattern}",
|
74
|
+
'confidence': 80,
|
75
|
+
'source': 'wappalyzer'
|
76
|
+
})
|
77
|
+
|
78
|
+
# Cookies
|
79
|
+
for cookie in data.get('cookies', {}).keys():
|
80
|
+
signatures.append({
|
81
|
+
'name': name,
|
82
|
+
'categories': categories,
|
83
|
+
'pattern_type': 'cookie',
|
84
|
+
'pattern': cookie,
|
85
|
+
'confidence': 70,
|
86
|
+
'source': 'wappalyzer'
|
87
|
+
})
|
88
|
+
|
89
|
+
# Scripts
|
90
|
+
for script in data.get('scripts', []):
|
91
|
+
signatures.append({
|
92
|
+
'name': name,
|
93
|
+
'categories': categories,
|
94
|
+
'pattern_type': 'script',
|
95
|
+
'pattern': script,
|
96
|
+
'confidence': 90,
|
97
|
+
'source': 'wappalyzer'
|
98
|
+
})
|
99
|
+
|
100
|
+
# Meta tags
|
101
|
+
for meta in data.get('meta', {}).items():
|
102
|
+
meta_name, meta_content = meta
|
103
|
+
signatures.append({
|
104
|
+
'name': name,
|
105
|
+
'categories': categories,
|
106
|
+
'pattern_type': 'meta',
|
107
|
+
'pattern': f'<meta[^>]*name=["\']{re.escape(meta_name)}["\'][^>]*content=["\']{re.escape(meta_content)}["\']',
|
108
|
+
'confidence': 85,
|
109
|
+
'source': 'wappalyzer'
|
110
|
+
})
|
111
|
+
|
112
|
+
return signatures
|
moriarty/dsl/__init__.py
ADDED
File without changes
|
moriarty/dsl/loader.py
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import importlib.resources
|
4
|
+
from pathlib import Path
|
5
|
+
from typing import List, Optional
|
6
|
+
|
7
|
+
import yaml
|
8
|
+
from pydantic import ValidationError
|
9
|
+
|
10
|
+
from .schema import TemplateSpec
|
11
|
+
|
12
|
+
|
13
|
+
class TemplateLoadError(Exception):
|
14
|
+
"""Erro ao carregar template."""
|
15
|
+
|
16
|
+
|
17
|
+
class TemplateLoader:
|
18
|
+
"""Carrega e valida templates YAML."""
|
19
|
+
|
20
|
+
def __init__(self) -> None:
|
21
|
+
self._templates: dict[str, TemplateSpec] = {}
|
22
|
+
|
23
|
+
def load_from_path(self, path: Path) -> TemplateSpec:
|
24
|
+
"""Carrega um template de um arquivo."""
|
25
|
+
try:
|
26
|
+
with path.open("r", encoding="utf-8") as f:
|
27
|
+
data = yaml.safe_load(f)
|
28
|
+
except Exception as exc:
|
29
|
+
raise TemplateLoadError(f"Failed to read {path}: {exc}") from exc
|
30
|
+
|
31
|
+
try:
|
32
|
+
return TemplateSpec(**data)
|
33
|
+
except ValidationError as exc:
|
34
|
+
raise TemplateLoadError(f"Invalid template in {path}: {exc}") from exc
|
35
|
+
|
36
|
+
def load_from_directory(self, directory: Path) -> List[TemplateSpec]:
|
37
|
+
"""Carrega todos os templates de um diretório."""
|
38
|
+
templates: List[TemplateSpec] = []
|
39
|
+
if not directory.exists():
|
40
|
+
return templates
|
41
|
+
|
42
|
+
for yaml_file in directory.glob("*.yaml"):
|
43
|
+
try:
|
44
|
+
template = self.load_from_path(yaml_file)
|
45
|
+
templates.append(template)
|
46
|
+
self._templates[template.site] = template
|
47
|
+
except TemplateLoadError:
|
48
|
+
continue
|
49
|
+
|
50
|
+
return templates
|
51
|
+
|
52
|
+
def load_builtin(self) -> List[TemplateSpec]:
|
53
|
+
"""Carrega templates embutidos da pasta assets/modules (recursivamente)."""
|
54
|
+
try:
|
55
|
+
root = importlib.resources.files("moriarty.assets.modules")
|
56
|
+
except (AttributeError, ModuleNotFoundError):
|
57
|
+
return []
|
58
|
+
|
59
|
+
templates: List[TemplateSpec] = []
|
60
|
+
|
61
|
+
def _load_entry(entry) -> None:
|
62
|
+
if entry.is_file() and entry.name.endswith(".yaml"):
|
63
|
+
try:
|
64
|
+
content = entry.read_text(encoding="utf-8")
|
65
|
+
data = yaml.safe_load(content)
|
66
|
+
template = TemplateSpec(**data)
|
67
|
+
templates.append(template)
|
68
|
+
self._templates[template.site] = template
|
69
|
+
except (ValidationError, Exception):
|
70
|
+
return
|
71
|
+
elif entry.is_dir():
|
72
|
+
for child in entry.iterdir():
|
73
|
+
_load_entry(child)
|
74
|
+
|
75
|
+
for entry in root.iterdir():
|
76
|
+
_load_entry(entry)
|
77
|
+
|
78
|
+
return templates
|
79
|
+
|
80
|
+
def get_template(self, site: str) -> Optional[TemplateSpec]:
|
81
|
+
"""Retorna um template pelo nome do site."""
|
82
|
+
return self._templates.get(site)
|
83
|
+
|
84
|
+
def list_templates(
|
85
|
+
self, tag: Optional[str] = None, category: Optional[str] = None
|
86
|
+
) -> List[TemplateSpec]:
|
87
|
+
"""Lista templates, opcionalmente filtrados por tag ou categoria."""
|
88
|
+
results = list(self._templates.values())
|
89
|
+
|
90
|
+
if tag:
|
91
|
+
results = [t for t in results if tag in t.tags]
|
92
|
+
|
93
|
+
if category:
|
94
|
+
results = [t for t in results if category in t.category]
|
95
|
+
|
96
|
+
return results
|
97
|
+
|
98
|
+
|
99
|
+
__all__ = ["TemplateLoader", "TemplateLoadError"]
|
moriarty/dsl/schema.py
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import Any, Dict, List, Literal, Optional
|
4
|
+
|
5
|
+
from pydantic import BaseModel, Field
|
6
|
+
|
7
|
+
|
8
|
+
class SelectorSpec(BaseModel):
|
9
|
+
"""Define como extrair dados de uma resposta."""
|
10
|
+
|
11
|
+
type: Literal["css", "xpath", "json", "regex"] = "css"
|
12
|
+
query: str
|
13
|
+
attribute: Optional[str] = None # Para CSS/XPath: qual atributo extrair
|
14
|
+
group: Optional[int] = None # Para regex: qual grupo capturar
|
15
|
+
|
16
|
+
|
17
|
+
class ExtractorSpec(BaseModel):
|
18
|
+
"""Define um campo a ser extraído."""
|
19
|
+
|
20
|
+
name: str
|
21
|
+
selector: SelectorSpec
|
22
|
+
required: bool = False
|
23
|
+
default: Optional[Any] = None
|
24
|
+
|
25
|
+
|
26
|
+
class TemplateSpec(BaseModel):
|
27
|
+
"""Especificação completa de um template de site."""
|
28
|
+
|
29
|
+
site: str
|
30
|
+
name: str
|
31
|
+
category: List[str] = Field(default_factory=list)
|
32
|
+
tags: List[str] = Field(default_factory=list)
|
33
|
+
url_template: str # Ex: "https://github.com/{username}"
|
34
|
+
method: Literal["GET", "POST"] = "GET"
|
35
|
+
headers: Dict[str, str] = Field(default_factory=dict)
|
36
|
+
body: Optional[Dict[str, Any]] = None
|
37
|
+
exists_selectors: List[SelectorSpec] = Field(default_factory=list)
|
38
|
+
not_found_selectors: List[SelectorSpec] = Field(default_factory=list)
|
39
|
+
extractors: List[ExtractorSpec] = Field(default_factory=list)
|
40
|
+
require_headless: bool = False
|
41
|
+
rate_limit_per_second: float = 2.0
|
42
|
+
page_hash_baseline: Optional[str] = None # Para canary/auto-heal
|
43
|
+
enabled: bool = True
|
44
|
+
nsfw: bool = False # NSFW content flag
|
45
|
+
|
46
|
+
|
47
|
+
__all__ = ["TemplateSpec", "ExtractorSpec", "SelectorSpec"]
|
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
"""Módulo de Inteligência Local do Moriarty.
|
2
|
+
|
3
|
+
Este módulo fornece funcionalidades para coleta, armazenamento e análise de dados
|
4
|
+
de inteligência sobre ameaças, incluindo IOCs (Indicadores de Comprometimento)
|
5
|
+
e assinaturas de ameaças.
|
6
|
+
"""
|
7
|
+
|
8
|
+
__version__ = "0.1.0"
|
9
|
+
|
10
|
+
# Importações principais para facilitar o acesso
|
11
|
+
try:
|
12
|
+
from .ioc import IOC, IOCType, ThreatType
|
13
|
+
from .storage import LocalStorage
|
14
|
+
from .signatures import SignatureManager
|
15
|
+
from .collectors import (
|
16
|
+
CTLogCollector,
|
17
|
+
PassiveDNSCollector,
|
18
|
+
WebTechProfiler,
|
19
|
+
ThreatFeedCollector
|
20
|
+
)
|
21
|
+
from .api import app as api_app
|
22
|
+
from .cli import app as cli_app
|
23
|
+
from .config import settings
|
24
|
+
|
25
|
+
except ImportError as e:
|
26
|
+
import warnings
|
27
|
+
warnings.warn(f"Não foi possível importar todos os módulos de inteligência: {e}")
|