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,501 @@
|
|
1
|
+
"""Módulo de armazenamento local para IOCs e assinaturas."""
|
2
|
+
|
3
|
+
import os
|
4
|
+
import json
|
5
|
+
import sqlite3
|
6
|
+
import logging
|
7
|
+
from pathlib import Path
|
8
|
+
from typing import Dict, List, Optional, Any, Union, TypeVar, Type, Tuple, Set
|
9
|
+
from datetime import datetime
|
10
|
+
|
11
|
+
from .ioc import IOC, IOCType, detect_ioc_type
|
12
|
+
|
13
|
+
# Configuração de logging
|
14
|
+
logger = logging.getLogger(__name__)
|
15
|
+
|
16
|
+
# Tipo genérico para documentação
|
17
|
+
T = TypeVar('T')
|
18
|
+
|
19
|
+
class StorageError(Exception):
|
20
|
+
"""Exceção base para erros de armazenamento."""
|
21
|
+
pass
|
22
|
+
|
23
|
+
class IOCStorage:
|
24
|
+
"""Armazenamento de IOCs em banco de dados SQLite."""
|
25
|
+
|
26
|
+
def __init__(self, db_path: Union[str, Path] = None):
|
27
|
+
"""Inicializa o armazenamento de IOCs.
|
28
|
+
|
29
|
+
Args:
|
30
|
+
db_path: Caminho para o arquivo do banco de dados SQLite.
|
31
|
+
Se não for especificado, será usado um banco em memória.
|
32
|
+
"""
|
33
|
+
self.db_path = str(db_path) if db_path else ":memory:"
|
34
|
+
self._conn = None
|
35
|
+
self._initialize_database()
|
36
|
+
|
37
|
+
def _get_connection(self) -> sqlite3.Connection:
|
38
|
+
"""Obtém uma conexão com o banco de dados."""
|
39
|
+
if self._conn is None:
|
40
|
+
self._conn = sqlite3.connect(
|
41
|
+
self.db_path,
|
42
|
+
detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES,
|
43
|
+
check_same_thread=False # Permitir acesso de múltiplas threads
|
44
|
+
)
|
45
|
+
self._conn.row_factory = sqlite3.Row
|
46
|
+
return self._conn
|
47
|
+
|
48
|
+
def _initialize_database(self):
|
49
|
+
"""Inicializa as tabelas do banco de dados."""
|
50
|
+
conn = self._get_connection()
|
51
|
+
cursor = conn.cursor()
|
52
|
+
|
53
|
+
# Tabela de IOCs
|
54
|
+
cursor.execute('''
|
55
|
+
CREATE TABLE IF NOT EXISTS iocs (
|
56
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
57
|
+
value TEXT NOT NULL,
|
58
|
+
ioc_type TEXT NOT NULL,
|
59
|
+
threat_type TEXT NOT NULL,
|
60
|
+
source TEXT NOT NULL,
|
61
|
+
first_seen TIMESTAMP NOT NULL,
|
62
|
+
last_seen TIMESTAMP NOT NULL,
|
63
|
+
confidence INTEGER NOT NULL,
|
64
|
+
tags TEXT, -- JSON array
|
65
|
+
metadata TEXT, -- JSON object
|
66
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
67
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
68
|
+
UNIQUE(value, ioc_type)
|
69
|
+
)
|
70
|
+
''')
|
71
|
+
|
72
|
+
# Índices para buscas rápidas
|
73
|
+
cursor.execute('CREATE INDEX IF NOT EXISTS idx_ioc_value ON iocs(value)')
|
74
|
+
cursor.execute('CREATE INDEX IF NOT EXISTS idx_ioc_type ON iocs(ioc_type)')
|
75
|
+
cursor.execute('CREATE INDEX IF NOT EXISTS idx_ioc_threat_type ON iocs(threat_type)')
|
76
|
+
cursor.execute('CREATE INDEX IF NOT EXISTS idx_ioc_source ON iocs(source)')
|
77
|
+
cursor.execute('CREATE INDEX IF NOT EXISTS idx_ioc_tags ON iocs(tags)')
|
78
|
+
|
79
|
+
# Tabela de assinaturas
|
80
|
+
cursor.execute('''
|
81
|
+
CREATE TABLE IF NOT EXISTS signatures (
|
82
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
83
|
+
name TEXT NOT NULL,
|
84
|
+
signature_type TEXT NOT NULL,
|
85
|
+
pattern TEXT NOT NULL,
|
86
|
+
description TEXT,
|
87
|
+
threat_type TEXT,
|
88
|
+
source TEXT,
|
89
|
+
confidence INTEGER,
|
90
|
+
metadata TEXT, -- JSON object
|
91
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
92
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
93
|
+
UNIQUE(name, signature_type, pattern)
|
94
|
+
)
|
95
|
+
''')
|
96
|
+
|
97
|
+
# Índices para assinaturas
|
98
|
+
cursor.execute('CREATE INDEX IF NOT EXISTS idx_sig_name ON signatures(name)')
|
99
|
+
cursor.execute('CREATE INDEX IF NOT EXISTS idx_sig_type ON signatures(signature_type)')
|
100
|
+
cursor.execute('CREATE INDEX IF NOT EXISTS idx_sig_threat_type ON signatures(threat_type)')
|
101
|
+
|
102
|
+
conn.commit()
|
103
|
+
|
104
|
+
def add_ioc(self, ioc: IOC) -> bool:
|
105
|
+
"""Adiciona um novo IOC ao armazenamento.
|
106
|
+
|
107
|
+
Args:
|
108
|
+
ioc: Instância de IOC a ser adicionada.
|
109
|
+
|
110
|
+
Returns:
|
111
|
+
bool: True se o IOC foi adicionado, False se já existir.
|
112
|
+
"""
|
113
|
+
conn = self._get_connection()
|
114
|
+
cursor = conn.cursor()
|
115
|
+
|
116
|
+
try:
|
117
|
+
cursor.execute('''
|
118
|
+
INSERT OR IGNORE INTO iocs
|
119
|
+
(value, ioc_type, threat_type, source, first_seen, last_seen, confidence, tags, metadata)
|
120
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
121
|
+
''', (
|
122
|
+
ioc.value,
|
123
|
+
ioc.ioc_type.value,
|
124
|
+
ioc.threat_type.value,
|
125
|
+
ioc.source,
|
126
|
+
ioc.first_seen,
|
127
|
+
ioc.last_seen,
|
128
|
+
ioc.confidence,
|
129
|
+
json.dumps(ioc.tags),
|
130
|
+
json.dumps(ioc.metadata)
|
131
|
+
))
|
132
|
+
|
133
|
+
if cursor.rowcount > 0:
|
134
|
+
conn.commit()
|
135
|
+
logger.debug(f"IOC adicionado: {ioc.value} ({ioc.ioc_type.value})")
|
136
|
+
return True
|
137
|
+
else:
|
138
|
+
# Atualiza o IOC existente
|
139
|
+
cursor.execute('''
|
140
|
+
UPDATE iocs
|
141
|
+
SET last_seen = ?,
|
142
|
+
confidence = MAX(confidence, ?),
|
143
|
+
tags = ?,
|
144
|
+
metadata = ?,
|
145
|
+
updated_at = CURRENT_TIMESTAMP
|
146
|
+
WHERE value = ? AND ioc_type = ?
|
147
|
+
''', (
|
148
|
+
ioc.last_seen,
|
149
|
+
ioc.confidence,
|
150
|
+
json.dumps(ioc.tags),
|
151
|
+
json.dumps(ioc.metadata),
|
152
|
+
ioc.value,
|
153
|
+
ioc.ioc_type.value
|
154
|
+
))
|
155
|
+
conn.commit()
|
156
|
+
logger.debug(f"IOC atualizado: {ioc.value} ({ioc.ioc_type.value})")
|
157
|
+
return False
|
158
|
+
|
159
|
+
except sqlite3.Error as e:
|
160
|
+
conn.rollback()
|
161
|
+
logger.error(f"Erro ao adicionar IOC {ioc.value}: {e}")
|
162
|
+
raise StorageError(f"Erro ao adicionar IOC: {e}")
|
163
|
+
|
164
|
+
def get_ioc(self, value: str, ioc_type: Union[str, IOCType] = None) -> Optional[IOC]:
|
165
|
+
"""Obtém um IOC pelo valor e tipo.
|
166
|
+
|
167
|
+
Args:
|
168
|
+
value: Valor do IOC.
|
169
|
+
ioc_type: Tipo do IOC (opcional, tenta detectar automaticamente).
|
170
|
+
|
171
|
+
Returns:
|
172
|
+
IOC ou None se não encontrado.
|
173
|
+
"""
|
174
|
+
if ioc_type is None:
|
175
|
+
detected = detect_ioc_type(value)
|
176
|
+
if detected is None:
|
177
|
+
return None
|
178
|
+
ioc_type = detected.value
|
179
|
+
elif isinstance(ioc_type, IOCType):
|
180
|
+
ioc_type = ioc_type.value
|
181
|
+
|
182
|
+
conn = self._get_connection()
|
183
|
+
cursor = conn.cursor()
|
184
|
+
|
185
|
+
cursor.execute('''
|
186
|
+
SELECT * FROM iocs
|
187
|
+
WHERE value = ? AND ioc_type = ?
|
188
|
+
''', (value, ioc_type))
|
189
|
+
|
190
|
+
row = cursor.fetchone()
|
191
|
+
if not row:
|
192
|
+
return None
|
193
|
+
|
194
|
+
return self._row_to_ioc(row)
|
195
|
+
|
196
|
+
def search_iocs(self, query: str = None, ioc_type: Union[str, IOCType] = None,
|
197
|
+
threat_type: Union[str, ThreatType] = None, source: str = None,
|
198
|
+
min_confidence: int = 0, limit: int = 100, offset: int = 0) -> List[IOC]:
|
199
|
+
"""Busca IOCs com base em critérios de pesquisa.
|
200
|
+
|
201
|
+
Args:
|
202
|
+
query: Termo de busca (pesquisa no valor do IOC).
|
203
|
+
ioc_type: Tipo de IOC para filtrar.
|
204
|
+
threat_type: Tipo de ameaça para filtrar.
|
205
|
+
source: Fonte do IOC para filtrar.
|
206
|
+
min_confidence: Confiança mínima (0-100).
|
207
|
+
limit: Número máximo de resultados.
|
208
|
+
offset: Deslocamento para paginação.
|
209
|
+
|
210
|
+
Returns:
|
211
|
+
Lista de IOCs que correspondem aos critérios.
|
212
|
+
"""
|
213
|
+
conn = self._get_connection()
|
214
|
+
cursor = conn.cursor()
|
215
|
+
|
216
|
+
# Constrói a consulta SQL dinamicamente
|
217
|
+
sql = 'SELECT * FROM iocs WHERE 1=1'
|
218
|
+
params = []
|
219
|
+
|
220
|
+
if query:
|
221
|
+
sql += ' AND value LIKE ?'
|
222
|
+
params.append(f'%{query}%')
|
223
|
+
|
224
|
+
if ioc_type is not None:
|
225
|
+
if isinstance(ioc_type, IOCType):
|
226
|
+
ioc_type = ioc_type.value
|
227
|
+
sql += ' AND ioc_type = ?'
|
228
|
+
params.append(ioc_type)
|
229
|
+
|
230
|
+
if threat_type is not None:
|
231
|
+
if isinstance(threat_type, ThreatType):
|
232
|
+
threat_type = threat_type.value
|
233
|
+
sql += ' AND threat_type = ?'
|
234
|
+
params.append(threat_type)
|
235
|
+
|
236
|
+
if source is not None:
|
237
|
+
sql += ' AND source = ?'
|
238
|
+
params.append(source)
|
239
|
+
|
240
|
+
if min_confidence > 0:
|
241
|
+
sql += ' AND confidence >= ?'
|
242
|
+
params.append(min_confidence)
|
243
|
+
|
244
|
+
# Ordenação e paginação
|
245
|
+
sql += ' ORDER BY last_seen DESC, confidence DESC'
|
246
|
+
sql += ' LIMIT ? OFFSET ?'
|
247
|
+
params.extend([limit, offset])
|
248
|
+
|
249
|
+
cursor.execute(sql, params)
|
250
|
+
return [self._row_to_ioc(row) for row in cursor.fetchall()]
|
251
|
+
|
252
|
+
def delete_ioc(self, value: str, ioc_type: Union[str, IOCType] = None) -> bool:
|
253
|
+
"""Remove um IOC do armazenamento.
|
254
|
+
|
255
|
+
Args:
|
256
|
+
value: Valor do IOC.
|
257
|
+
ioc_type: Tipo do IOC (opcional, tenta detectar automaticamente).
|
258
|
+
|
259
|
+
Returns:
|
260
|
+
bool: True se o IOC foi removido, False se não existir.
|
261
|
+
"""
|
262
|
+
if ioc_type is None:
|
263
|
+
detected = detect_ioc_type(value)
|
264
|
+
if detected is None:
|
265
|
+
return False
|
266
|
+
ioc_type = detected.value
|
267
|
+
elif isinstance(ioc_type, IOCType):
|
268
|
+
ioc_type = ioc_type.value
|
269
|
+
|
270
|
+
conn = self._get_connection()
|
271
|
+
cursor = conn.cursor()
|
272
|
+
|
273
|
+
try:
|
274
|
+
cursor.execute('''
|
275
|
+
DELETE FROM iocs
|
276
|
+
WHERE value = ? AND ioc_type = ?
|
277
|
+
''', (value, ioc_type))
|
278
|
+
|
279
|
+
deleted = cursor.rowcount > 0
|
280
|
+
if deleted:
|
281
|
+
conn.commit()
|
282
|
+
logger.info(f"IOC removido: {value} ({ioc_type})")
|
283
|
+
|
284
|
+
return deleted
|
285
|
+
|
286
|
+
except sqlite3.Error as e:
|
287
|
+
conn.rollback()
|
288
|
+
logger.error(f"Erro ao remover IOC {value}: {e}")
|
289
|
+
raise StorageError(f"Erro ao remover IOC: {e}")
|
290
|
+
|
291
|
+
def add_signature(self, name: str, signature_type: str, pattern: str,
|
292
|
+
description: str = None, threat_type: str = None,
|
293
|
+
source: str = None, confidence: int = 50,
|
294
|
+
metadata: Dict[str, Any] = None) -> bool:
|
295
|
+
"""Adiciona uma nova assinatura ao armazenamento.
|
296
|
+
|
297
|
+
Args:
|
298
|
+
name: Nome da assinatura.
|
299
|
+
signature_type: Tipo da assinatura (ex: 'yara', 'snort').
|
300
|
+
pattern: Padrão da assinatura.
|
301
|
+
description: Descrição da assinatura.
|
302
|
+
threat_type: Tipo de ameaça associada.
|
303
|
+
source: Fonte da assinatura.
|
304
|
+
confidence: Nível de confiança (0-100).
|
305
|
+
metadata: Metadados adicionais.
|
306
|
+
|
307
|
+
Returns:
|
308
|
+
bool: True se a assinatura foi adicionada, False se já existir.
|
309
|
+
"""
|
310
|
+
conn = self._get_connection()
|
311
|
+
cursor = conn.cursor()
|
312
|
+
|
313
|
+
try:
|
314
|
+
cursor.execute('''
|
315
|
+
INSERT OR IGNORE INTO signatures
|
316
|
+
(name, signature_type, pattern, description, threat_type, source, confidence, metadata)
|
317
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
318
|
+
''', (
|
319
|
+
name,
|
320
|
+
signature_type,
|
321
|
+
pattern,
|
322
|
+
description,
|
323
|
+
threat_type,
|
324
|
+
source,
|
325
|
+
min(max(confidence, 0), 100), # Garante que está entre 0 e 100
|
326
|
+
json.dumps(metadata or {})
|
327
|
+
))
|
328
|
+
|
329
|
+
if cursor.rowcount > 0:
|
330
|
+
conn.commit()
|
331
|
+
logger.debug(f"Assinatura adicionada: {name} ({signature_type})")
|
332
|
+
return True
|
333
|
+
else:
|
334
|
+
# Atualiza a assinatura existente
|
335
|
+
cursor.execute('''
|
336
|
+
UPDATE signatures
|
337
|
+
SET description = COALESCE(?, description),
|
338
|
+
threat_type = COALESCE(?, threat_type),
|
339
|
+
source = COALESCE(?, source),
|
340
|
+
confidence = ?,
|
341
|
+
metadata = ?,
|
342
|
+
updated_at = CURRENT_TIMESTAMP
|
343
|
+
WHERE name = ? AND signature_type = ? AND pattern = ?
|
344
|
+
''', (
|
345
|
+
description,
|
346
|
+
threat_type,
|
347
|
+
source,
|
348
|
+
min(max(confidence, 0), 100),
|
349
|
+
json.dumps(metadata or {}),
|
350
|
+
name,
|
351
|
+
signature_type,
|
352
|
+
pattern
|
353
|
+
))
|
354
|
+
conn.commit()
|
355
|
+
logger.debug(f"Assinatura atualizada: {name} ({signature_type})")
|
356
|
+
return False
|
357
|
+
|
358
|
+
except sqlite3.Error as e:
|
359
|
+
conn.rollback()
|
360
|
+
logger.error(f"Erro ao adicionar assinatura {name}: {e}")
|
361
|
+
raise StorageError(f"Erro ao adicionar assinatura: {e}")
|
362
|
+
|
363
|
+
def search_signatures(self, query: str = None, signature_type: str = None,
|
364
|
+
threat_type: str = None, source: str = None,
|
365
|
+
min_confidence: int = 0, limit: int = 100,
|
366
|
+
offset: int = 0) -> List[Dict[str, Any]]:
|
367
|
+
"""Busca assinaturas com base em critérios de pesquisa.
|
368
|
+
|
369
|
+
Args:
|
370
|
+
query: Termo de busca (pesquisa no nome e descrição).
|
371
|
+
signature_type: Tipo de assinatura para filtrar.
|
372
|
+
threat_type: Tipo de ameaça para filtrar.
|
373
|
+
source: Fonte da assinatura para filtrar.
|
374
|
+
min_confidence: Confiança mínima (0-100).
|
375
|
+
limit: Número máximo de resultados.
|
376
|
+
offset: Deslocamento para paginação.
|
377
|
+
|
378
|
+
Returns:
|
379
|
+
Lista de dicionários com as assinaturas encontradas.
|
380
|
+
"""
|
381
|
+
conn = self._get_connection()
|
382
|
+
cursor = conn.cursor()
|
383
|
+
|
384
|
+
# Constrói a consulta SQL dinamicamente
|
385
|
+
sql = 'SELECT * FROM signatures WHERE 1=1'
|
386
|
+
params = []
|
387
|
+
|
388
|
+
if query:
|
389
|
+
sql += ' AND (name LIKE ? OR description LIKE ?)'
|
390
|
+
params.extend([f'%{query}%', f'%{query}%'])
|
391
|
+
|
392
|
+
if signature_type is not None:
|
393
|
+
sql += ' AND signature_type = ?'
|
394
|
+
params.append(signature_type)
|
395
|
+
|
396
|
+
if threat_type is not None:
|
397
|
+
sql += ' AND threat_type = ?'
|
398
|
+
params.append(threat_type)
|
399
|
+
|
400
|
+
if source is not None:
|
401
|
+
sql += ' AND source = ?'
|
402
|
+
params.append(source)
|
403
|
+
|
404
|
+
if min_confidence > 0:
|
405
|
+
sql += ' AND confidence >= ?'
|
406
|
+
params.append(min_confidence)
|
407
|
+
|
408
|
+
# Ordenação e paginação
|
409
|
+
sql += ' ORDER BY name, confidence DESC'
|
410
|
+
sql += ' LIMIT ? OFFSET ?'
|
411
|
+
params.extend([limit, offset])
|
412
|
+
|
413
|
+
cursor.execute(sql, params)
|
414
|
+
return [self._row_to_dict(row) for row in cursor.fetchall()]
|
415
|
+
|
416
|
+
def delete_signature(self, signature_id: int) -> bool:
|
417
|
+
"""Remove uma assinatura do armazenamento.
|
418
|
+
|
419
|
+
Args:
|
420
|
+
signature_id: ID da assinatura a ser removida.
|
421
|
+
|
422
|
+
Returns:
|
423
|
+
bool: True se a assinatura foi removida, False se não existir.
|
424
|
+
"""
|
425
|
+
conn = self._get_connection()
|
426
|
+
cursor = conn.cursor()
|
427
|
+
|
428
|
+
try:
|
429
|
+
cursor.execute('''
|
430
|
+
DELETE FROM signatures
|
431
|
+
WHERE id = ?
|
432
|
+
''', (signature_id,))
|
433
|
+
|
434
|
+
deleted = cursor.rowcount > 0
|
435
|
+
if deleted:
|
436
|
+
conn.commit()
|
437
|
+
logger.info(f"Assinatura removida: ID {signature_id}")
|
438
|
+
|
439
|
+
return deleted
|
440
|
+
|
441
|
+
except sqlite3.Error as e:
|
442
|
+
conn.rollback()
|
443
|
+
logger.error(f"Erro ao remover assinatura ID {signature_id}: {e}")
|
444
|
+
raise StorageError(f"Erro ao remover assinatura: {e}")
|
445
|
+
|
446
|
+
def _row_to_ioc(self, row) -> IOC:
|
447
|
+
"""Converte uma linha do banco de dados em um objeto IOC."""
|
448
|
+
return IOC(
|
449
|
+
value=row['value'],
|
450
|
+
ioc_type=row['ioc_type'],
|
451
|
+
threat_type=row['threat_type'],
|
452
|
+
source=row['source'],
|
453
|
+
first_seen=row['first_seen'],
|
454
|
+
last_seen=row['last_seen'],
|
455
|
+
confidence=row['confidence'],
|
456
|
+
tags=json.loads(row['tags']) if row['tags'] else [],
|
457
|
+
metadata=json.loads(row['metadata']) if row['metadata'] else {}
|
458
|
+
)
|
459
|
+
|
460
|
+
def _row_to_dict(self, row) -> Dict[str, Any]:
|
461
|
+
"""Converte uma linha do banco de dados em um dicionário."""
|
462
|
+
return {
|
463
|
+
'id': row['id'],
|
464
|
+
'name': row['name'],
|
465
|
+
'signature_type': row['signature_type'],
|
466
|
+
'pattern': row['pattern'],
|
467
|
+
'description': row['description'],
|
468
|
+
'threat_type': row['threat_type'],
|
469
|
+
'source': row['source'],
|
470
|
+
'confidence': row['confidence'],
|
471
|
+
'metadata': json.loads(row['metadata']) if row['metadata'] else {},
|
472
|
+
'created_at': row['created_at'],
|
473
|
+
'updated_at': row['updated_at']
|
474
|
+
}
|
475
|
+
|
476
|
+
def close(self):
|
477
|
+
"""Fecha a conexão com o banco de dados."""
|
478
|
+
if self._conn is not None:
|
479
|
+
self._conn.close()
|
480
|
+
self._conn = None
|
481
|
+
|
482
|
+
def __del__(self):
|
483
|
+
"""Garante que a conexão seja fechada quando o objeto for destruído."""
|
484
|
+
self.close()
|
485
|
+
|
486
|
+
# Instância global para uso em todo o módulo
|
487
|
+
local_storage = IOCStorage()
|
488
|
+
|
489
|
+
def get_storage() -> IOCStorage:
|
490
|
+
"""Obtém a instância global do armazenamento local."""
|
491
|
+
return local_storage
|
492
|
+
|
493
|
+
def set_storage_path(path: Union[str, Path]):
|
494
|
+
"""Define o caminho do banco de dados do armazenamento local.
|
495
|
+
|
496
|
+
Args:
|
497
|
+
path: Caminho para o arquivo do banco de dados SQLite.
|
498
|
+
"""
|
499
|
+
global local_storage
|
500
|
+
local_storage.close()
|
501
|
+
local_storage = IOCStorage(path)
|
File without changes
|
File without changes
|
@@ -0,0 +1,47 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import logging
|
4
|
+
import sys
|
5
|
+
from typing import Literal
|
6
|
+
|
7
|
+
import structlog
|
8
|
+
|
9
|
+
LogStyle = Literal["structured", "pretty"]
|
10
|
+
|
11
|
+
|
12
|
+
def configure_logging(style: LogStyle = "structured", verbose: bool = False) -> None:
|
13
|
+
"""Configure structlog for Moriarty CLI."""
|
14
|
+
level = logging.DEBUG if verbose else logging.INFO
|
15
|
+
|
16
|
+
shared_processors = [
|
17
|
+
structlog.contextvars.merge_contextvars,
|
18
|
+
structlog.processors.add_log_level,
|
19
|
+
structlog.processors.TimeStamper(fmt="iso", key="ts"),
|
20
|
+
structlog.stdlib.PositionalArgumentsFormatter(),
|
21
|
+
]
|
22
|
+
|
23
|
+
if style == "structured":
|
24
|
+
renderer = structlog.processors.JSONRenderer()
|
25
|
+
else:
|
26
|
+
renderer = structlog.dev.ConsoleRenderer(colors=True)
|
27
|
+
|
28
|
+
structlog.configure(
|
29
|
+
processors=[
|
30
|
+
structlog.stdlib.filter_by_level,
|
31
|
+
*shared_processors,
|
32
|
+
structlog.processors.StackInfoRenderer(),
|
33
|
+
structlog.processors.format_exc_info,
|
34
|
+
renderer,
|
35
|
+
],
|
36
|
+
logger_factory=structlog.stdlib.LoggerFactory(),
|
37
|
+
wrapper_class=structlog.stdlib.BoundLogger,
|
38
|
+
cache_logger_on_first_use=True,
|
39
|
+
)
|
40
|
+
|
41
|
+
logging.basicConfig(
|
42
|
+
level=level,
|
43
|
+
handlers=[logging.StreamHandler(sys.stderr)],
|
44
|
+
)
|
45
|
+
|
46
|
+
|
47
|
+
__all__ = ["configure_logging", "LogStyle"]
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from .assertion import Assertion
|
2
|
+
from .entity import Entity
|
3
|
+
from .evidence import CustodyEvent, Evidence
|
4
|
+
from .relation import Relation
|
5
|
+
from .types import ConfidenceBand, EntityKind, EvidenceKind
|
6
|
+
|
7
|
+
__all__ = [
|
8
|
+
"Assertion",
|
9
|
+
"Entity",
|
10
|
+
"Evidence",
|
11
|
+
"CustodyEvent",
|
12
|
+
"Relation",
|
13
|
+
"ConfidenceBand",
|
14
|
+
"EntityKind",
|
15
|
+
"EvidenceKind",
|
16
|
+
]
|
@@ -0,0 +1,24 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import List, Optional
|
4
|
+
from uuid import UUID, uuid4
|
5
|
+
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field
|
7
|
+
|
8
|
+
from .types import ConfidenceBand
|
9
|
+
|
10
|
+
|
11
|
+
class Assertion(BaseModel):
|
12
|
+
id: UUID = Field(default_factory=uuid4)
|
13
|
+
subject_id: UUID
|
14
|
+
predicate: str
|
15
|
+
object: str
|
16
|
+
confidence: float = Field(ge=0.0, le=1.0, default=0.5)
|
17
|
+
band: ConfidenceBand = ConfidenceBand.INDICATIVE
|
18
|
+
evidence_ids: List[UUID] = Field(default_factory=list)
|
19
|
+
explanation: Optional[str] = None
|
20
|
+
|
21
|
+
model_config = ConfigDict(populate_by_name=True)
|
22
|
+
|
23
|
+
|
24
|
+
__all__ = ["Assertion"]
|
@@ -0,0 +1,22 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import Any, Dict, Optional, Set
|
4
|
+
from uuid import UUID, uuid4
|
5
|
+
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field
|
7
|
+
|
8
|
+
from .types import EntityKind
|
9
|
+
|
10
|
+
|
11
|
+
class Entity(BaseModel):
|
12
|
+
id: UUID = Field(default_factory=uuid4)
|
13
|
+
kind: EntityKind
|
14
|
+
value: str
|
15
|
+
display_name: Optional[str] = None
|
16
|
+
labels: Set[str] = Field(default_factory=set)
|
17
|
+
attributes: Dict[str, Any] = Field(default_factory=dict)
|
18
|
+
|
19
|
+
model_config = ConfigDict(frozen=True, populate_by_name=True)
|
20
|
+
|
21
|
+
|
22
|
+
__all__ = ["Entity"]
|
@@ -0,0 +1,37 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from datetime import datetime, timezone
|
4
|
+
from typing import Any, Dict, List, Optional
|
5
|
+
from uuid import UUID, uuid4
|
6
|
+
|
7
|
+
from pydantic import BaseModel, ConfigDict, Field
|
8
|
+
|
9
|
+
from .types import EvidenceKind
|
10
|
+
|
11
|
+
|
12
|
+
class CustodyEvent(BaseModel):
|
13
|
+
actor: str
|
14
|
+
action: str
|
15
|
+
at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
16
|
+
notes: Optional[str] = None
|
17
|
+
|
18
|
+
model_config = ConfigDict(frozen=True)
|
19
|
+
|
20
|
+
|
21
|
+
class Evidence(BaseModel):
|
22
|
+
id: UUID = Field(default_factory=uuid4)
|
23
|
+
kind: EvidenceKind
|
24
|
+
sha256: str
|
25
|
+
source: str
|
26
|
+
collected_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
27
|
+
url: Optional[str] = None
|
28
|
+
selector: Optional[str] = None
|
29
|
+
method: Optional[str] = None
|
30
|
+
summary: Optional[str] = None
|
31
|
+
custody: List[CustodyEvent] = Field(default_factory=list)
|
32
|
+
metadata: Dict[str, Any] = Field(default_factory=dict)
|
33
|
+
|
34
|
+
model_config = ConfigDict(populate_by_name=True)
|
35
|
+
|
36
|
+
|
37
|
+
__all__ = ["Evidence", "CustodyEvent"]
|
@@ -0,0 +1,24 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import Dict, Optional
|
4
|
+
from uuid import UUID, uuid4
|
5
|
+
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field
|
7
|
+
|
8
|
+
from .types import ConfidenceBand
|
9
|
+
|
10
|
+
|
11
|
+
class Relation(BaseModel):
|
12
|
+
id: UUID = Field(default_factory=uuid4)
|
13
|
+
source_id: UUID
|
14
|
+
target_id: UUID
|
15
|
+
relation_type: str
|
16
|
+
confidence: float = Field(ge=0.0, le=1.0, default=0.5)
|
17
|
+
band: ConfidenceBand = ConfidenceBand.INDICATIVE
|
18
|
+
attributes: Dict[str, str] = Field(default_factory=dict)
|
19
|
+
description: Optional[str] = None
|
20
|
+
|
21
|
+
model_config = ConfigDict(populate_by_name=True)
|
22
|
+
|
23
|
+
|
24
|
+
__all__ = ["Relation"]
|