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.
Files changed (416) hide show
  1. moriarty/__init__.py +5 -0
  2. moriarty/adapters/__init__.py +0 -0
  3. moriarty/agent/__init__.py +0 -0
  4. moriarty/assets/modules/.gitkeep +0 -0
  5. moriarty/assets/modules/asia/douban.yaml +19 -0
  6. moriarty/assets/modules/asia/kakao.yaml +19 -0
  7. moriarty/assets/modules/asia/line.yaml +19 -0
  8. moriarty/assets/modules/asia/mixi.yaml +19 -0
  9. moriarty/assets/modules/asia/naver.yaml +19 -0
  10. moriarty/assets/modules/asia/qq.yaml +19 -0
  11. moriarty/assets/modules/asia/vk.yaml +19 -0
  12. moriarty/assets/modules/asia/wechat.yaml +19 -0
  13. moriarty/assets/modules/asia/weibo.yaml +19 -0
  14. moriarty/assets/modules/asia/xiaohongshu.yaml +19 -0
  15. moriarty/assets/modules/behance.yaml +47 -0
  16. moriarty/assets/modules/business/crunchbase.yaml +27 -0
  17. moriarty/assets/modules/business/fiverr.yaml +32 -0
  18. moriarty/assets/modules/business/freelancer.yaml +27 -0
  19. moriarty/assets/modules/business/glassdoor.yaml +27 -0
  20. moriarty/assets/modules/business/guru.yaml +26 -0
  21. moriarty/assets/modules/business/indeed.yaml +25 -0
  22. moriarty/assets/modules/business/monster.yaml +25 -0
  23. moriarty/assets/modules/business/peopleperhour.yaml +26 -0
  24. moriarty/assets/modules/business/toptal.yaml +28 -0
  25. moriarty/assets/modules/business/upwork.yaml +27 -0
  26. moriarty/assets/modules/business/ziprecruiter.yaml +25 -0
  27. moriarty/assets/modules/content/buymeacoffee.yaml +27 -0
  28. moriarty/assets/modules/content/gumroad.yaml +27 -0
  29. moriarty/assets/modules/content/ko-fi.yaml +32 -0
  30. moriarty/assets/modules/content/onlyfans.yaml +27 -0
  31. moriarty/assets/modules/content/patreon.yaml +33 -0
  32. moriarty/assets/modules/content/substack.yaml +32 -0
  33. moriarty/assets/modules/creative/500px.yaml +31 -0
  34. moriarty/assets/modules/creative/artstation.yaml +33 -0
  35. moriarty/assets/modules/creative/deviantart.yaml +32 -0
  36. moriarty/assets/modules/creative/flickr.yaml +31 -0
  37. moriarty/assets/modules/creative/pexels.yaml +26 -0
  38. moriarty/assets/modules/creative/unsplash.yaml +26 -0
  39. moriarty/assets/modules/creative/vimeo.yaml +31 -0
  40. moriarty/assets/modules/crypto/binance.yaml +27 -0
  41. moriarty/assets/modules/crypto/bitcointalk.yaml +33 -0
  42. moriarty/assets/modules/crypto/coinbase.yaml +26 -0
  43. moriarty/assets/modules/crypto/etherscan.yaml +32 -0
  44. moriarty/assets/modules/crypto/foundation.yaml +28 -0
  45. moriarty/assets/modules/crypto/kraken.yaml +27 -0
  46. moriarty/assets/modules/crypto/mirror.yaml +27 -0
  47. moriarty/assets/modules/crypto/niftygateway.yaml +26 -0
  48. moriarty/assets/modules/crypto/opensea.yaml +32 -0
  49. moriarty/assets/modules/crypto/rarible.yaml +27 -0
  50. moriarty/assets/modules/crypto/superrare.yaml +29 -0
  51. moriarty/assets/modules/dating/bumble.yaml +25 -0
  52. moriarty/assets/modules/dating/grindr.yaml +27 -0
  53. moriarty/assets/modules/dating/happn.yaml +25 -0
  54. moriarty/assets/modules/dating/her.yaml +27 -0
  55. moriarty/assets/modules/dating/hinge.yaml +25 -0
  56. moriarty/assets/modules/dating/match.yaml +25 -0
  57. moriarty/assets/modules/dating/meetme.yaml +27 -0
  58. moriarty/assets/modules/dating/okcupid.yaml +25 -0
  59. moriarty/assets/modules/dating/pof.yaml +25 -0
  60. moriarty/assets/modules/dating/tinder.yaml +25 -0
  61. moriarty/assets/modules/dating-nsfw/adultfriendfinder.yaml +28 -0
  62. moriarty/assets/modules/dating-nsfw/ashley-madison.yaml +26 -0
  63. moriarty/assets/modules/design/adobe-portfolio.yaml +27 -0
  64. moriarty/assets/modules/design/carbonmade.yaml +27 -0
  65. moriarty/assets/modules/design/cgsociety.yaml +27 -0
  66. moriarty/assets/modules/design/coroflot.yaml +27 -0
  67. moriarty/assets/modules/design/figma.yaml +27 -0
  68. moriarty/assets/modules/design/sketch.yaml +26 -0
  69. moriarty/assets/modules/dev/bitbucket.yaml +35 -0
  70. moriarty/assets/modules/dev/codeforces.yaml +32 -0
  71. moriarty/assets/modules/dev/codepen.yaml +34 -0
  72. moriarty/assets/modules/dev/hackerone.yaml +32 -0
  73. moriarty/assets/modules/dev/hackthebox.yaml +27 -0
  74. moriarty/assets/modules/dev/huggingface.yaml +27 -0
  75. moriarty/assets/modules/dev/kaggle.yaml +32 -0
  76. moriarty/assets/modules/dev/leetcode.yaml +32 -0
  77. moriarty/assets/modules/dev/replit.yaml +31 -0
  78. moriarty/assets/modules/dribbble.yaml +53 -0
  79. moriarty/assets/modules/ecommerce/etsy.yaml +32 -0
  80. moriarty/assets/modules/education/duolingo.yaml +32 -0
  81. moriarty/assets/modules/education/edx.yaml +26 -0
  82. moriarty/assets/modules/education/khanacademy.yaml +26 -0
  83. moriarty/assets/modules/education/lynda.yaml +27 -0
  84. moriarty/assets/modules/education/memrise.yaml +27 -0
  85. moriarty/assets/modules/education/pluralsight.yaml +27 -0
  86. moriarty/assets/modules/education/skillshare.yaml +27 -0
  87. moriarty/assets/modules/education/udacity.yaml +27 -0
  88. moriarty/assets/modules/email/github_email.yaml +40 -0
  89. moriarty/assets/modules/email/gravatar.yaml +23 -0
  90. moriarty/assets/modules/europe/badoo.yaml +19 -0
  91. moriarty/assets/modules/europe/lovoo.yaml +19 -0
  92. moriarty/assets/modules/europe/myspace.yaml +19 -0
  93. moriarty/assets/modules/europe/netlog.yaml +19 -0
  94. moriarty/assets/modules/europe/ok.yaml +19 -0
  95. moriarty/assets/modules/europe/skyrock.yaml +19 -0
  96. moriarty/assets/modules/europe/studivz.yaml +19 -0
  97. moriarty/assets/modules/europe/tuenti.yaml +19 -0
  98. moriarty/assets/modules/europe/viadeo.yaml +19 -0
  99. moriarty/assets/modules/europe/xing.yaml +19 -0
  100. moriarty/assets/modules/fitness/fitbit.yaml +27 -0
  101. moriarty/assets/modules/fitness/garmin.yaml +27 -0
  102. moriarty/assets/modules/fitness/myfitnesspal.yaml +27 -0
  103. moriarty/assets/modules/fitness/strava.yaml +33 -0
  104. moriarty/assets/modules/fitness/zwift.yaml +28 -0
  105. moriarty/assets/modules/food/allrecipes.yaml +27 -0
  106. moriarty/assets/modules/food/tasty.yaml +27 -0
  107. moriarty/assets/modules/food/yelp.yaml +32 -0
  108. moriarty/assets/modules/food/zomato.yaml +28 -0
  109. moriarty/assets/modules/forums/4chan.yaml +26 -0
  110. moriarty/assets/modules/forums/8kun.yaml +26 -0
  111. moriarty/assets/modules/forums/9gag.yaml +26 -0
  112. moriarty/assets/modules/forums/discourse.yaml +26 -0
  113. moriarty/assets/modules/forums/disqus.yaml +31 -0
  114. moriarty/assets/modules/forums/hackernews.yaml +32 -0
  115. moriarty/assets/modules/forums/launchpad.yaml +27 -0
  116. moriarty/assets/modules/forums/phpbb.yaml +25 -0
  117. moriarty/assets/modules/forums/quora.yaml +32 -0
  118. moriarty/assets/modules/forums/serverfault.yaml +27 -0
  119. moriarty/assets/modules/forums/slashdot.yaml +28 -0
  120. moriarty/assets/modules/forums/stackexchange.yaml +32 -0
  121. moriarty/assets/modules/forums/superuser.yaml +27 -0
  122. moriarty/assets/modules/forums/vbulletin.yaml +25 -0
  123. moriarty/assets/modules/forums/xenforo.yaml +25 -0
  124. moriarty/assets/modules/forums-nsfw/kiwifarms.yaml +25 -0
  125. moriarty/assets/modules/forums-nsfw/lolcow.yaml +26 -0
  126. moriarty/assets/modules/gaming/apextracker.yaml +27 -0
  127. moriarty/assets/modules/gaming/battlenet.yaml +26 -0
  128. moriarty/assets/modules/gaming/chess.yaml +30 -0
  129. moriarty/assets/modules/gaming/discord-public.yaml +27 -0
  130. moriarty/assets/modules/gaming/dotabuff.yaml +32 -0
  131. moriarty/assets/modules/gaming/epicgames.yaml +25 -0
  132. moriarty/assets/modules/gaming/faceit.yaml +33 -0
  133. moriarty/assets/modules/gaming/fortnitetracker.yaml +32 -0
  134. moriarty/assets/modules/gaming/gog.yaml +26 -0
  135. moriarty/assets/modules/gaming/itch.yaml +32 -0
  136. moriarty/assets/modules/gaming/kongregate.yaml +25 -0
  137. moriarty/assets/modules/gaming/minecraft.yaml +31 -0
  138. moriarty/assets/modules/gaming/opgg.yaml +32 -0
  139. moriarty/assets/modules/gaming/origin.yaml +26 -0
  140. moriarty/assets/modules/gaming/playstation.yaml +30 -0
  141. moriarty/assets/modules/gaming/roblox.yaml +31 -0
  142. moriarty/assets/modules/gaming/xbox.yaml +25 -0
  143. moriarty/assets/modules/github.yaml +68 -0
  144. moriarty/assets/modules/gitlab.yaml +60 -0
  145. moriarty/assets/modules/instagram.yaml +48 -0
  146. moriarty/assets/modules/latam/fotolog.yaml +27 -0
  147. moriarty/assets/modules/latam/orkut.yaml +26 -0
  148. moriarty/assets/modules/latam/taringa.yaml +27 -0
  149. moriarty/assets/modules/learning/coursera.yaml +26 -0
  150. moriarty/assets/modules/learning/udemy.yaml +26 -0
  151. moriarty/assets/modules/linkedin.yaml +40 -0
  152. moriarty/assets/modules/marketplaces/depop.yaml +28 -0
  153. moriarty/assets/modules/marketplaces/ebay.yaml +32 -0
  154. moriarty/assets/modules/marketplaces/grailed.yaml +27 -0
  155. moriarty/assets/modules/marketplaces/mercari.yaml +26 -0
  156. moriarty/assets/modules/marketplaces/poshmark.yaml +27 -0
  157. moriarty/assets/modules/marketplaces/reverb.yaml +27 -0
  158. moriarty/assets/modules/marketplaces/vinted.yaml +28 -0
  159. moriarty/assets/modules/medium.yaml +44 -0
  160. moriarty/assets/modules/music/audiomack.yaml +26 -0
  161. moriarty/assets/modules/music/bandcamp.yaml +30 -0
  162. moriarty/assets/modules/music/beatport.yaml +28 -0
  163. moriarty/assets/modules/music/deezer.yaml +26 -0
  164. moriarty/assets/modules/music/discogs.yaml +32 -0
  165. moriarty/assets/modules/music/genius.yaml +26 -0
  166. moriarty/assets/modules/music/lastfm.yaml +30 -0
  167. moriarty/assets/modules/music/mixcloud.yaml +26 -0
  168. moriarty/assets/modules/music/reverbnation.yaml +31 -0
  169. moriarty/assets/modules/music/soundcloud.yaml +31 -0
  170. moriarty/assets/modules/music/spotify.yaml +26 -0
  171. moriarty/assets/modules/music/tidal.yaml +26 -0
  172. moriarty/assets/modules/nsfw/adultwork.yaml +27 -0
  173. moriarty/assets/modules/nsfw/bongacams.yaml +28 -0
  174. moriarty/assets/modules/nsfw/cam4.yaml +28 -0
  175. moriarty/assets/modules/nsfw/chaturbate.yaml +28 -0
  176. moriarty/assets/modules/nsfw/clips4sale.yaml +27 -0
  177. moriarty/assets/modules/nsfw/extralunchmoney.yaml +27 -0
  178. moriarty/assets/modules/nsfw/fansly.yaml +28 -0
  179. moriarty/assets/modules/nsfw/fetlife.yaml +28 -0
  180. moriarty/assets/modules/nsfw/iwantclips.yaml +27 -0
  181. moriarty/assets/modules/nsfw/justforfans.yaml +28 -0
  182. moriarty/assets/modules/nsfw/loyalfans.yaml +28 -0
  183. moriarty/assets/modules/nsfw/manyvids.yaml +27 -0
  184. moriarty/assets/modules/nsfw/myfreecams.yaml +28 -0
  185. moriarty/assets/modules/nsfw/niteflirt.yaml +26 -0
  186. moriarty/assets/modules/nsfw/pornhub.yaml +32 -0
  187. moriarty/assets/modules/nsfw/redtube.yaml +27 -0
  188. moriarty/assets/modules/nsfw/stripchat.yaml +28 -0
  189. moriarty/assets/modules/nsfw/xhamster.yaml +27 -0
  190. moriarty/assets/modules/nsfw/xvideos.yaml +27 -0
  191. moriarty/assets/modules/nsfw/youporn.yaml +27 -0
  192. moriarty/assets/modules/photography/eyeem.yaml +25 -0
  193. moriarty/assets/modules/photography/fotki.yaml +25 -0
  194. moriarty/assets/modules/photography/photobucket.yaml +26 -0
  195. moriarty/assets/modules/photography/smugmug.yaml +25 -0
  196. moriarty/assets/modules/photography/vsco.yaml +27 -0
  197. moriarty/assets/modules/pinterest.yaml +40 -0
  198. moriarty/assets/modules/podcasts/anchor.yaml +26 -0
  199. moriarty/assets/modules/podcasts/castbox.yaml +26 -0
  200. moriarty/assets/modules/podcasts/podbean.yaml +26 -0
  201. moriarty/assets/modules/professional/about.yaml +31 -0
  202. moriarty/assets/modules/professional/academia.yaml +27 -0
  203. moriarty/assets/modules/professional/angellist.yaml +27 -0
  204. moriarty/assets/modules/professional/calendly.yaml +26 -0
  205. moriarty/assets/modules/professional/issuu.yaml +27 -0
  206. moriarty/assets/modules/professional/mendeley.yaml +27 -0
  207. moriarty/assets/modules/professional/notion.yaml +27 -0
  208. moriarty/assets/modules/professional/orcid.yaml +27 -0
  209. moriarty/assets/modules/professional/producthunt.yaml +31 -0
  210. moriarty/assets/modules/professional/researchgate.yaml +32 -0
  211. moriarty/assets/modules/professional/scribd.yaml +27 -0
  212. moriarty/assets/modules/professional/slideshare.yaml +31 -0
  213. moriarty/assets/modules/professional/trello.yaml +26 -0
  214. moriarty/assets/modules/professional/typeform.yaml +27 -0
  215. moriarty/assets/modules/reddit.yaml +46 -0
  216. moriarty/assets/modules/regional/amino.yaml +27 -0
  217. moriarty/assets/modules/regional/ask-fm.yaml +32 -0
  218. moriarty/assets/modules/regional/babycenter.yaml +26 -0
  219. moriarty/assets/modules/regional/cafemom.yaml +27 -0
  220. moriarty/assets/modules/regional/care2.yaml +27 -0
  221. moriarty/assets/modules/regional/diaspora.yaml +26 -0
  222. moriarty/assets/modules/regional/ello.yaml +27 -0
  223. moriarty/assets/modules/regional/gaia.yaml +27 -0
  224. moriarty/assets/modules/regional/habbo.yaml +27 -0
  225. moriarty/assets/modules/regional/imvu.yaml +27 -0
  226. moriarty/assets/modules/regional/lemmy.yaml +27 -0
  227. moriarty/assets/modules/regional/peertube.yaml +26 -0
  228. moriarty/assets/modules/regional/pixelfed.yaml +27 -0
  229. moriarty/assets/modules/regional/plurk.yaml +26 -0
  230. moriarty/assets/modules/regional/recroom.yaml +27 -0
  231. moriarty/assets/modules/regional/secondlife.yaml +26 -0
  232. moriarty/assets/modules/regional/vine-archive.yaml +27 -0
  233. moriarty/assets/modules/regional/vrchat.yaml +27 -0
  234. moriarty/assets/modules/regional/weheartit.yaml +27 -0
  235. moriarty/assets/modules/social/anilist.yaml +27 -0
  236. moriarty/assets/modules/social/beacons.yaml +26 -0
  237. moriarty/assets/modules/social/blogger.yaml +27 -0
  238. moriarty/assets/modules/social/crunchyroll.yaml +27 -0
  239. moriarty/assets/modules/social/discord.yaml +27 -0
  240. moriarty/assets/modules/social/dreamwidth.yaml +26 -0
  241. moriarty/assets/modules/social/facebook.yaml +34 -0
  242. moriarty/assets/modules/social/goodreads.yaml +32 -0
  243. moriarty/assets/modules/social/imdb.yaml +27 -0
  244. moriarty/assets/modules/social/kitsu.yaml +27 -0
  245. moriarty/assets/modules/social/letterboxd.yaml +32 -0
  246. moriarty/assets/modules/social/linktree.yaml +26 -0
  247. moriarty/assets/modules/social/livejournal.yaml +27 -0
  248. moriarty/assets/modules/social/mastodon.yaml +30 -0
  249. moriarty/assets/modules/social/minds.yaml +25 -0
  250. moriarty/assets/modules/social/myanimelist.yaml +32 -0
  251. moriarty/assets/modules/social/ravelry.yaml +27 -0
  252. moriarty/assets/modules/social/snapchat.yaml +25 -0
  253. moriarty/assets/modules/social/telegram.yaml +35 -0
  254. moriarty/assets/modules/social/tiktok.yaml +35 -0
  255. moriarty/assets/modules/social/trakt.yaml +28 -0
  256. moriarty/assets/modules/social/wattpad.yaml +32 -0
  257. moriarty/assets/modules/social/wordpress-com.yaml +26 -0
  258. moriarty/assets/modules/sports/espn.yaml +26 -0
  259. moriarty/assets/modules/sports/untappd.yaml +32 -0
  260. moriarty/assets/modules/stackoverflow.yaml +47 -0
  261. moriarty/assets/modules/steam.yaml +47 -0
  262. moriarty/assets/modules/streaming/caffeine.yaml +25 -0
  263. moriarty/assets/modules/streaming/dlive.yaml +27 -0
  264. moriarty/assets/modules/streaming/trovo.yaml +25 -0
  265. moriarty/assets/modules/travel/airbnb.yaml +26 -0
  266. moriarty/assets/modules/travel/booking.yaml +26 -0
  267. moriarty/assets/modules/travel/couchsurfing.yaml +27 -0
  268. moriarty/assets/modules/travel/tripadvisor.yaml +32 -0
  269. moriarty/assets/modules/tumblr.yaml +40 -0
  270. moriarty/assets/modules/twitch.yaml +48 -0
  271. moriarty/assets/modules/twitter.yaml +39 -0
  272. moriarty/assets/modules/youtube.yaml +42 -0
  273. moriarty/assets/templates/cves/CVE-2017-5638.yaml +27 -0
  274. moriarty/assets/templates/cves/CVE-2018-7600.yaml +30 -0
  275. moriarty/assets/templates/cves/CVE-2019-11510.yaml +27 -0
  276. moriarty/assets/templates/cves/CVE-2019-19781.yaml +28 -0
  277. moriarty/assets/templates/cves/CVE-2020-14882.yaml +28 -0
  278. moriarty/assets/templates/cves/CVE-2020-14883.yaml +29 -0
  279. moriarty/assets/templates/cves/CVE-2020-3452.yaml +28 -0
  280. moriarty/assets/templates/cves/CVE-2020-5902.yaml +28 -0
  281. moriarty/assets/templates/cves/CVE-2021-21972.yaml +31 -0
  282. moriarty/assets/templates/cves/CVE-2021-21985.yaml +28 -0
  283. moriarty/assets/templates/cves/CVE-2021-26084.yaml +30 -0
  284. moriarty/assets/templates/cves/CVE-2021-41773.yaml +25 -0
  285. moriarty/assets/templates/cves/CVE-2021-42013.yaml +28 -0
  286. moriarty/assets/templates/cves/CVE-2021-44228.yaml +27 -0
  287. moriarty/assets/templates/cves/CVE-2022-0185.yaml +21 -0
  288. moriarty/assets/templates/cves/CVE-2022-1388.yaml +36 -0
  289. moriarty/assets/templates/cves/CVE-2022-22954.yaml +28 -0
  290. moriarty/assets/templates/cves/CVE-2022-22965.yaml +31 -0
  291. moriarty/assets/templates/cves/CVE-2022-26134.yaml +27 -0
  292. moriarty/assets/templates/cves/CVE-2023-22515.yaml +27 -0
  293. moriarty/assets/templates/cves/CVE-2023-22527.yaml +29 -0
  294. moriarty/assets/templates/cves/CVE-2023-23752.yaml +33 -0
  295. moriarty/assets/templates/cves/CVE-2023-27350.yaml +27 -0
  296. moriarty/assets/templates/cves/CVE-2023-2868.yaml +27 -0
  297. moriarty/assets/templates/cves/CVE-2023-34362.yaml +27 -0
  298. moriarty/assets/templates/cves/CVE-2023-3519.yaml +28 -0
  299. moriarty/assets/templates/cves/CVE-2023-4966.yaml +27 -0
  300. moriarty/assets/templates/default-logins/admin-weak.yaml +40 -0
  301. moriarty/assets/templates/default-logins/wordpress-default.yaml +38 -0
  302. moriarty/assets/templates/exposures/aws-credentials.yaml +35 -0
  303. moriarty/assets/templates/exposures/backup-files.yaml +36 -0
  304. moriarty/assets/templates/exposures/database-files.yaml +34 -0
  305. moriarty/assets/templates/exposures/docker-exposed.yaml +31 -0
  306. moriarty/assets/templates/exposures/env-exposed.yaml +41 -0
  307. moriarty/assets/templates/exposures/git-exposed.yaml +41 -0
  308. moriarty/assets/templates/exposures/phpinfo.yaml +36 -0
  309. moriarty/assets/templates/exposures/svn-exposed.yaml +28 -0
  310. moriarty/assets/templates/fuzzing/api-endpoints.yaml +39 -0
  311. moriarty/assets/templates/fuzzing/common-files.yaml +37 -0
  312. moriarty/assets/templates/fuzzing/open-redirect-fuzz.yaml +35 -0
  313. moriarty/assets/templates/fuzzing/xss-search-fuzz.yaml +29 -0
  314. moriarty/assets/templates/git-config.yaml +18 -0
  315. moriarty/assets/templates/misconfigurations/cors-misconfiguration.yaml +30 -0
  316. moriarty/assets/templates/misconfigurations/debug-enabled.yaml +29 -0
  317. moriarty/assets/templates/misconfigurations/directory-listing.yaml +33 -0
  318. moriarty/assets/templates/misconfigurations/jwt-none-algo.yaml +30 -0
  319. moriarty/assets/templates/misconfigurations/ssl-tls-weak.yaml +23 -0
  320. moriarty/assets/templates/vulnerabilities/lfi-basic.yaml +31 -0
  321. moriarty/assets/templates/vulnerabilities/open-redirect.yaml +31 -0
  322. moriarty/assets/templates/vulnerabilities/rce-basic.yaml +34 -0
  323. moriarty/assets/templates/vulnerabilities/sqli-error.yaml +39 -0
  324. moriarty/assets/templates/vulnerabilities/ssrf-basic.yaml +31 -0
  325. moriarty/assets/templates/vulnerabilities/xss-reflected.yaml +38 -0
  326. moriarty/assets/templates/vulnerabilities/xxe-basic.yaml +30 -0
  327. moriarty/assets/wordlists/subdomains-1000.txt +1063 -0
  328. moriarty/cli/__init__.py +3 -0
  329. moriarty/cli/app.py +120 -0
  330. moriarty/cli/async_utils.py +19 -0
  331. moriarty/cli/dns.py +83 -0
  332. moriarty/cli/domain_cmd.py +572 -0
  333. moriarty/cli/email.py +383 -0
  334. moriarty/cli/email_investigate.py +224 -0
  335. moriarty/cli/intelligence.py +329 -0
  336. moriarty/cli/output.py +62 -0
  337. moriarty/cli/rdap.py +94 -0
  338. moriarty/cli/state.py +38 -0
  339. moriarty/cli/tls.py +91 -0
  340. moriarty/cli/user.py +227 -0
  341. moriarty/core/cache_backend.py +223 -0
  342. moriarty/core/config_manager.py +303 -0
  343. moriarty/correlator/__init__.py +0 -0
  344. moriarty/data/__init__.py +81 -0
  345. moriarty/data/ioc/__init__.py +142 -0
  346. moriarty/data/ioc/matcher.py +254 -0
  347. moriarty/data/ioc/types.py +267 -0
  348. moriarty/data/local_intelligence.py +507 -0
  349. moriarty/data/signature_loaders/__init__.py +103 -0
  350. moriarty/data/signature_loaders/base.py +54 -0
  351. moriarty/data/signature_loaders/ioc_feed.py +356 -0
  352. moriarty/data/signature_loaders/wappalyzer.py +112 -0
  353. moriarty/dsl/__init__.py +0 -0
  354. moriarty/dsl/loader.py +99 -0
  355. moriarty/dsl/schema.py +47 -0
  356. moriarty/export/__init__.py +0 -0
  357. moriarty/intelligence/__init__.py +27 -0
  358. moriarty/intelligence/__main__.py +150 -0
  359. moriarty/intelligence/config.py +395 -0
  360. moriarty/intelligence/ioc.py +267 -0
  361. moriarty/intelligence/signatures.py +550 -0
  362. moriarty/intelligence/storage.py +501 -0
  363. moriarty/interop/__init__.py +0 -0
  364. moriarty/logging/__init__.py +0 -0
  365. moriarty/logging/config.py +47 -0
  366. moriarty/models/__init__.py +16 -0
  367. moriarty/models/assertion.py +24 -0
  368. moriarty/models/entity.py +22 -0
  369. moriarty/models/evidence.py +37 -0
  370. moriarty/models/relation.py +24 -0
  371. moriarty/models/types.py +28 -0
  372. moriarty/modules/__init__.py +0 -0
  373. moriarty/modules/avatar_hash.py +184 -0
  374. moriarty/modules/directory_fuzzer.py +322 -0
  375. moriarty/modules/dns_scan.py +40 -0
  376. moriarty/modules/domain_scanner.py +620 -0
  377. moriarty/modules/email_check.py +98 -0
  378. moriarty/modules/email_investigate.py +267 -0
  379. moriarty/modules/email_security.py +274 -0
  380. moriarty/modules/googlemaps_lookup.py +106 -0
  381. moriarty/modules/headless_executor.py +201 -0
  382. moriarty/modules/orchestrator.py +60 -0
  383. moriarty/modules/passive_recon.py +444 -0
  384. moriarty/modules/phone_extractor.py +151 -0
  385. moriarty/modules/pipeline_orchestrator.py +726 -0
  386. moriarty/modules/port_scanner.py +129 -0
  387. moriarty/modules/rdap.py +61 -0
  388. moriarty/modules/rdap_extended.py +188 -0
  389. moriarty/modules/stealth_mode.py +610 -0
  390. moriarty/modules/subdomain_discovery.py +595 -0
  391. moriarty/modules/technology_profiler.py +361 -0
  392. moriarty/modules/template_executor.py +239 -0
  393. moriarty/modules/template_scanner.py +1048 -0
  394. moriarty/modules/tls_scan.py +46 -0
  395. moriarty/modules/tls_validator.py +188 -0
  396. moriarty/modules/vuln_scanner.py +483 -0
  397. moriarty/modules/waf_detector.py +585 -0
  398. moriarty/modules/wayback_discovery.py +234 -0
  399. moriarty/modules/web_crawler.py +163 -0
  400. moriarty/net/__init__.py +0 -0
  401. moriarty/net/dns_cache.py +175 -0
  402. moriarty/net/dns_client.py +188 -0
  403. moriarty/net/rdap_client.py +52 -0
  404. moriarty/net/smtp_client.py +114 -0
  405. moriarty/net/tls_client.py +111 -0
  406. moriarty/parsers/__init__.py +0 -0
  407. moriarty/parsers/html_parser.py +136 -0
  408. moriarty/tests/__init__.py +0 -0
  409. moriarty/tests/test_email_service.py +17 -0
  410. moriarty/tests/test_models.py +46 -0
  411. moriarty/tests/test_orchestrator.py +30 -0
  412. moriarty/tests/test_tls_client.py +18 -0
  413. moriarty_project-0.1.6.dist-info/METADATA +388 -0
  414. moriarty_project-0.1.6.dist-info/RECORD +418 -0
  415. moriarty_project-0.1.6.dist-info/WHEEL +4 -0
  416. moriarty_project-0.1.6.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,726 @@
1
+ """Pipeline Orchestrator - Execução declarativa de ataques via YAML."""
2
+ import asyncio
3
+ import json
4
+ import time
5
+ from dataclasses import dataclass
6
+ from pathlib import Path
7
+ from typing import Any, Dict, List, Optional
8
+
9
+ import httpx
10
+ import structlog
11
+ import yaml
12
+ from rich.console import Console
13
+ from rich.tree import Tree
14
+
15
+ from moriarty.core.config_manager import config_manager
16
+ from moriarty.modules.passive_recon import PassiveRecon
17
+ from moriarty.modules.port_scanner import PortScanner
18
+ from moriarty.modules.web_crawler import WebCrawler
19
+
20
+ logger = structlog.get_logger(__name__)
21
+ console = Console()
22
+
23
+
24
+ @dataclass
25
+ class PipelineStage:
26
+ """Stage do pipeline."""
27
+ name: str
28
+ module: str
29
+ config: Dict[str, Any]
30
+ depends_on: List[str] = None
31
+ condition: Optional[str] = None
32
+
33
+
34
+ @dataclass
35
+ class PipelineResult:
36
+ """Resultado de execução do pipeline."""
37
+ stage: str
38
+ success: bool
39
+ output: Any
40
+ duration: float
41
+
42
+
43
+ class PipelineOrchestrator:
44
+ """
45
+ Orquestrador de pipelines declarativos.
46
+
47
+ Exemplo de pipeline.yaml:
48
+
49
+ ```yaml
50
+ name: "Full Recon Pipeline"
51
+ target: "example.com"
52
+
53
+ variables:
54
+ wordlist: "/path/to/wordlist.txt"
55
+ threads: 20
56
+
57
+ stages:
58
+ - name: "DNS Discovery"
59
+ module: "dns"
60
+ config:
61
+ records: ["A", "AAAA", "MX", "TXT"]
62
+
63
+ - name: "Subdomain Enum"
64
+ module: "subdiscover"
65
+ depends_on: ["DNS Discovery"]
66
+ config:
67
+ sources: ["crtsh", "wayback"]
68
+ validate: true
69
+
70
+ - name: "Port Scan"
71
+ module: "ports"
72
+ depends_on: ["Subdomain Enum"]
73
+ config:
74
+ ports: "common"
75
+ stealth: 2
76
+
77
+ - name: "Template Scan"
78
+ module: "template-scan"
79
+ depends_on: ["Port Scan"]
80
+ condition: "len(previous.open_ports) > 0"
81
+ config:
82
+ severity: ["critical", "high"]
83
+ ```
84
+ """
85
+
86
+ def __init__(
87
+ self,
88
+ pipeline_file: str,
89
+ target_override: Optional[str] = None,
90
+ vars_file: Optional[str] = None,
91
+ dry_run: bool = False,
92
+ log_file: Optional[str] = None,
93
+ checkpoint_file: Optional[str] = None,
94
+ resume: bool = True,
95
+ ):
96
+ self.pipeline_file = pipeline_file
97
+ self.target_override = target_override
98
+ self.vars_file = vars_file
99
+ self.dry_run = dry_run
100
+ self.resume_enabled = resume
101
+
102
+ self.pipeline_data: Dict[str, Any] = {}
103
+ self.stages: List[PipelineStage] = []
104
+ self.results: List[PipelineResult] = []
105
+ self.variables: Dict[str, Any] = {}
106
+ self.stage_results: Dict[str, PipelineResult] = {}
107
+ self.default_retries: int = 1
108
+ self.config = config_manager
109
+ self.notification_config = getattr(self.config, "notifications", None) if self.config else None
110
+
111
+ base_dir = Path(self.config.config_dir) if self.config else Path.home() / ".moriarty"
112
+
113
+ logs_dir = base_dir / "logs"
114
+ checkpoints_dir = base_dir / "checkpoints"
115
+ logs_dir.mkdir(parents=True, exist_ok=True)
116
+ checkpoints_dir.mkdir(parents=True, exist_ok=True)
117
+
118
+ self.log_file_path = Path(log_file) if log_file else logs_dir / "pipeline.log"
119
+ self.checkpoint_path = (
120
+ Path(checkpoint_file)
121
+ if checkpoint_file
122
+ else checkpoints_dir / f"{Path(self.pipeline_file).stem}.json"
123
+ )
124
+
125
+ async def run(self):
126
+ """Executa pipeline."""
127
+ logger.info("pipeline.start", file=self.pipeline_file)
128
+ self._log_event("pipeline_start", file=self.pipeline_file)
129
+
130
+ # Carrega pipeline
131
+ self._load_pipeline()
132
+
133
+ # Carrega variáveis
134
+ self._load_variables()
135
+
136
+ if self.resume_enabled:
137
+ self._load_checkpoint()
138
+
139
+ # Mostra resumo
140
+ self._show_summary()
141
+
142
+ if self.dry_run:
143
+ console.print("[yellow]🔍 Dry run - não executando stages[/yellow]")
144
+ return
145
+
146
+ # Executa stages em ordem
147
+ await self._execute_stages()
148
+
149
+ # Mostra resultados
150
+ self._show_results()
151
+ await self._notify_pipeline_summary()
152
+ self._finalize_checkpoint()
153
+ self._log_event(
154
+ "pipeline_complete",
155
+ success=all(result.success for result in self.results) if self.results else True,
156
+ total=len(self.results),
157
+ )
158
+
159
+ def _load_pipeline(self):
160
+ """Carrega arquivo de pipeline."""
161
+ try:
162
+ with open(self.pipeline_file, 'r') as f:
163
+ self.pipeline_data = yaml.safe_load(f)
164
+
165
+ # Override target se fornecido
166
+ if self.target_override:
167
+ self.pipeline_data["target"] = self.target_override
168
+
169
+ # Parse stages
170
+ for stage_data in self.pipeline_data.get("stages", []):
171
+ stage = PipelineStage(
172
+ name=stage_data["name"],
173
+ module=stage_data["module"],
174
+ config=stage_data.get("config", {}),
175
+ depends_on=stage_data.get("depends_on", []),
176
+ condition=stage_data.get("condition"),
177
+ )
178
+ self.stages.append(stage)
179
+
180
+ logger.info("pipeline.loaded", stages=len(self.stages))
181
+
182
+ except Exception as e:
183
+ logger.error("pipeline.load.error", error=str(e))
184
+ raise
185
+
186
+ def _load_variables(self):
187
+ """Carrega variáveis do pipeline e arquivo externo."""
188
+ # Variáveis do pipeline
189
+ self.variables = self.pipeline_data.get("variables", {})
190
+
191
+ # Variáveis de arquivo externo
192
+ if self.vars_file:
193
+ try:
194
+ with open(self.vars_file, 'r') as f:
195
+ external_vars = yaml.safe_load(f)
196
+ self.variables.update(external_vars)
197
+ except Exception as e:
198
+ logger.warning("pipeline.vars.load.error", file=self.vars_file, error=str(e))
199
+
200
+ def _show_summary(self):
201
+ """Mostra resumo do pipeline."""
202
+ tree = Tree(f"[bold cyan]🔄 Pipeline: {self.pipeline_data.get('name', 'Unnamed')}[/bold cyan]")
203
+
204
+ tree.add(f"[dim]Target:[/dim] {self.pipeline_data.get('target', 'N/A')}")
205
+ tree.add(f"[dim]Stages:[/dim] {len(self.stages)}")
206
+
207
+ if self.variables:
208
+ vars_node = tree.add("[dim]Variables:[/dim]")
209
+ for key, value in self.variables.items():
210
+ vars_node.add(f"{key}: {value}")
211
+
212
+ stages_node = tree.add("[bold]Stages:[/bold]")
213
+ for stage in self.stages:
214
+ stage_label = f"{stage.name} [dim]({stage.module})[/dim]"
215
+ stage_node = stages_node.add(stage_label)
216
+
217
+ if stage.depends_on:
218
+ stage_node.add(f"[dim]Depends on: {', '.join(stage.depends_on)}[/dim]")
219
+
220
+ if stage.condition:
221
+ stage_node.add(f"[dim]Condition: {stage.condition}[/dim]")
222
+
223
+ console.print(tree)
224
+ console.print()
225
+
226
+ async def _execute_stages(self):
227
+ """Executa stages do pipeline com paralelismo e retries."""
228
+ pending = {
229
+ stage.name: stage
230
+ for stage in self.stages
231
+ if stage.name not in self.stage_results
232
+ or not self.stage_results[stage.name].success
233
+ }
234
+ running: Dict[asyncio.Task, PipelineStage] = {}
235
+
236
+ while pending or running:
237
+ ready: List[PipelineStage] = []
238
+
239
+ for stage_name, stage in list(pending.items()):
240
+ if not self._dependencies_met(stage):
241
+ continue
242
+
243
+ if stage.condition and not self._evaluate_condition(stage):
244
+ logger.info("pipeline.stage.skip.condition", stage=stage.name)
245
+ result = PipelineResult(
246
+ stage=stage.name,
247
+ success=True,
248
+ output="skipped (condition)",
249
+ duration=0.0,
250
+ )
251
+ self.results.append(result)
252
+ self.stage_results[stage.name] = result
253
+ pending.pop(stage_name)
254
+ continue
255
+
256
+ ready.append(stage)
257
+ pending.pop(stage_name)
258
+
259
+ for stage in ready:
260
+ task = asyncio.create_task(self._execute_stage_with_retry(stage))
261
+ running[task] = stage
262
+
263
+ if not running:
264
+ # Nenhuma stage pronta (dependências não satisfeitas)
265
+ break
266
+
267
+ done, _ = await asyncio.wait(running.keys(), return_when=asyncio.FIRST_COMPLETED)
268
+
269
+ for task in done:
270
+ stage = running.pop(task)
271
+ try:
272
+ result = await task
273
+ except Exception as exc: # pragma: no cover - fallback seguro
274
+ logger.error("pipeline.stage.unhandled", stage=stage.name, error=str(exc))
275
+ result = PipelineResult(
276
+ stage=stage.name,
277
+ success=False,
278
+ output=str(exc),
279
+ duration=0.0,
280
+ )
281
+
282
+ self.results.append(result)
283
+ self.stage_results[stage.name] = result
284
+ self._persist_checkpoint(result)
285
+
286
+ if result.success:
287
+ console.print(f"[green]✓ Completo:[/green] {stage.name} [{result.duration:.2f}s]")
288
+ else:
289
+ console.print(f"[red]✗ Falhou:[/red] {stage.name}")
290
+
291
+ for stage_name, stage in pending.items():
292
+ logger.warning("pipeline.stage.unexecuted", stage=stage.name)
293
+
294
+ def _dependencies_met(self, stage: PipelineStage) -> bool:
295
+ """Verifica se dependências do stage já foram executadas."""
296
+ if not stage.depends_on:
297
+ return True
298
+ return all(dep in self.stage_results for dep in stage.depends_on)
299
+
300
+ async def _execute_stage_with_retry(self, stage: PipelineStage) -> PipelineResult:
301
+ """Executa stage com política de retry."""
302
+ retries = int(stage.config.get("retries", self.default_retries))
303
+ delay = float(stage.config.get("retry_delay", 2.0))
304
+ attempt = 0
305
+ last_result: Optional[PipelineResult] = None
306
+
307
+ while attempt <= retries:
308
+ await self._notify_stage_start(stage, attempt)
309
+ self._log_event("stage_start", stage=stage.name, attempt=attempt)
310
+ result = await self._execute_stage(stage, attempt=attempt)
311
+
312
+ if result.success:
313
+ await self._notify_stage_end(stage, result)
314
+ self._log_event(
315
+ "stage_complete",
316
+ stage=stage.name,
317
+ success=True,
318
+ duration=result.duration,
319
+ )
320
+ return result
321
+
322
+ last_result = result
323
+ attempt += 1
324
+
325
+ if attempt <= retries:
326
+ logger.warning("pipeline.stage.retry", stage=stage.name, attempt=attempt)
327
+ await asyncio.sleep(delay)
328
+
329
+ await self._notify_stage_end(stage, last_result or result)
330
+ self._log_event(
331
+ "stage_complete",
332
+ stage=stage.name,
333
+ success=False,
334
+ duration=(last_result or result).duration if (last_result or result) else 0.0,
335
+ )
336
+ return last_result or result
337
+
338
+ async def _execute_stage(self, stage: PipelineStage, attempt: int = 0) -> PipelineResult:
339
+ """Executa uma stage."""
340
+ import time
341
+ start = time.time()
342
+
343
+ try:
344
+ label = stage.name if attempt == 0 else f"{stage.name} (retry {attempt})"
345
+ console.print(f"[cyan]▶ Executando:[/cyan] {label}")
346
+
347
+ # Substitui variáveis no config
348
+ config = self._substitute_variables(stage.config)
349
+
350
+ # Mapeamento de módulos
351
+ if stage.module == "dns":
352
+ output = await self._run_dns(config)
353
+ elif stage.module == "subdiscover":
354
+ output = await self._run_subdiscover(config)
355
+ elif stage.module == "ports":
356
+ output = await self._run_ports(config)
357
+ elif stage.module == "template-scan":
358
+ output = await self._run_template_scan(config)
359
+ elif stage.module == "wayback":
360
+ output = await self._run_wayback(config)
361
+ elif stage.module == "passive":
362
+ output = await self._run_passive(config)
363
+ elif stage.module == "crawl":
364
+ output = await self._run_crawl(config)
365
+ else:
366
+ logger.warning("pipeline.stage.unknown", module=stage.module)
367
+ output = None
368
+
369
+ duration = time.time() - start
370
+
371
+ return PipelineResult(
372
+ stage=stage.name,
373
+ success=True,
374
+ output=output,
375
+ duration=duration,
376
+ )
377
+
378
+ except Exception as e:
379
+ logger.error("pipeline.stage.error", stage=stage.name, error=str(e))
380
+ duration = time.time() - start
381
+
382
+ return PipelineResult(
383
+ stage=stage.name,
384
+ success=False,
385
+ output=str(e),
386
+ duration=duration,
387
+ )
388
+
389
+ def _substitute_variables(self, config: Dict[str, Any]) -> Dict[str, Any]:
390
+ """Substitui variáveis no config."""
391
+ import re
392
+
393
+ def replace_var(match):
394
+ var_name = match.group(1)
395
+ return str(self.variables.get(var_name, match.group(0)))
396
+
397
+ # Converte para string, substitui, converte de volta
398
+ config_str = str(config)
399
+ config_str = re.sub(r'\$\{(\w+)\}', replace_var, config_str)
400
+
401
+ # Eval seguro (simplificado)
402
+ try:
403
+ return eval(config_str)
404
+ except:
405
+ return config
406
+
407
+ def _evaluate_condition(self, stage: PipelineStage) -> bool:
408
+ """Avalia condição booleana do stage."""
409
+ if not stage.condition:
410
+ return True
411
+
412
+ try:
413
+ previous = None
414
+ if self.stage_results:
415
+ previous = self.stage_results[next(reversed(self.stage_results))]
416
+
417
+ context = {
418
+ "len": len,
419
+ "any": any,
420
+ "all": all,
421
+ "previous": previous,
422
+ "results": self.stage_results,
423
+ "stage_result": lambda name: self.stage_results.get(name),
424
+ }
425
+
426
+ return bool(eval(stage.condition, {"__builtins__": {}}, context))
427
+ except Exception as e:
428
+ logger.warning("pipeline.stage.condition_error", stage=stage.name, error=str(e))
429
+ return False
430
+
431
+ def _notifications_enabled(self) -> bool:
432
+ """Retorna se notificações estão habilitadas."""
433
+ return bool(
434
+ self.notification_config
435
+ and getattr(self.notification_config, "enabled", False)
436
+ and (
437
+ getattr(self.notification_config, "slack_enabled", False)
438
+ or getattr(self.notification_config, "discord_enabled", False)
439
+ or getattr(self.notification_config, "telegram_enabled", False)
440
+ )
441
+ )
442
+
443
+ async def _notify_stage_start(self, stage: PipelineStage, attempt: int) -> None:
444
+ """Envia notificação de início de stage."""
445
+ if not self._notifications_enabled():
446
+ return
447
+
448
+ message = f"Stage '{stage.name}' iniciado"
449
+ if attempt:
450
+ message += f" (tentativa {attempt + 1})"
451
+
452
+ await self._send_notification(message, level="info")
453
+
454
+ async def _notify_stage_end(self, stage: PipelineStage, result: PipelineResult) -> None:
455
+ """Envia notificação de conclusão de stage."""
456
+ if not self._notifications_enabled():
457
+ return
458
+
459
+ status = "sucesso" if result and result.success else "falha"
460
+ duration = f"{result.duration:.2f}s" if result else "0s"
461
+ snippet = ""
462
+ if result and isinstance(result.output, str) and result.output:
463
+ snippet = f" - {result.output[:120]}"
464
+
465
+ message = f"Stage '{stage.name}' finalizada com {status} em {duration}{snippet}"
466
+ level = "success" if result and result.success else "error"
467
+ await self._send_notification(message, level=level)
468
+
469
+ async def _notify_pipeline_summary(self) -> None:
470
+ """Envia resumo final do pipeline."""
471
+ if not self._notifications_enabled():
472
+ return
473
+
474
+ total = len(self.results)
475
+ success = sum(1 for item in self.results if item.success)
476
+ message = (
477
+ f"Pipeline '{self.pipeline_data.get('name', 'Unnamed')}' finalizado: "
478
+ f"{success}/{total} stages com sucesso."
479
+ )
480
+ await self._send_notification(message, level="info")
481
+
482
+ async def _send_notification(self, message: str, level: str = "info") -> None:
483
+ """Envio de notificações para canais configurados."""
484
+ if not self._notifications_enabled():
485
+ return
486
+
487
+ notif = self.notification_config
488
+ title = self.pipeline_data.get('name', 'Moriarty Pipeline')
489
+ tasks = []
490
+
491
+ async with httpx.AsyncClient(timeout=5.0) as client:
492
+ if getattr(notif, "slack_enabled", False) and notif.slack_webhook:
493
+ tasks.append(
494
+ client.post(
495
+ notif.slack_webhook,
496
+ json={"text": f"[{level.upper()}] {title}: {message}"},
497
+ )
498
+ )
499
+
500
+ if getattr(notif, "discord_enabled", False) and notif.discord_webhook:
501
+ tasks.append(
502
+ client.post(
503
+ notif.discord_webhook,
504
+ json={"content": f"[{level.upper()}] {title}: {message}"},
505
+ )
506
+ )
507
+
508
+ if (
509
+ getattr(notif, "telegram_enabled", False)
510
+ and notif.telegram_token
511
+ and notif.telegram_chat_id
512
+ ):
513
+ telegram_url = f"https://api.telegram.org/bot{notif.telegram_token}/sendMessage"
514
+ tasks.append(
515
+ client.post(
516
+ telegram_url,
517
+ data={
518
+ "chat_id": notif.telegram_chat_id,
519
+ "text": f"[{level.upper()}] {title}: {message}",
520
+ },
521
+ )
522
+ )
523
+
524
+ if not tasks:
525
+ return
526
+
527
+ responses = await asyncio.gather(*tasks, return_exceptions=True)
528
+
529
+ for response in responses:
530
+ if isinstance(response, Exception):
531
+ logger.debug("pipeline.notify.error", error=str(response))
532
+ elif getattr(response, "status_code", 200) >= 400:
533
+ body = getattr(response, "text", "")
534
+ logger.debug(
535
+ "pipeline.notify.http_error",
536
+ status=response.status_code,
537
+ body=body[:200],
538
+ )
539
+
540
+ def _load_checkpoint(self) -> None:
541
+ if not self.resume_enabled or not self.checkpoint_path.exists():
542
+ return
543
+
544
+ try:
545
+ with self.checkpoint_path.open("r", encoding="utf-8") as handle:
546
+ data = json.load(handle)
547
+
548
+ for entry in data.get("stages", []):
549
+ stage_name = entry.get("stage")
550
+ if not stage_name:
551
+ continue
552
+ result = PipelineResult(
553
+ stage=stage_name,
554
+ success=bool(entry.get("success")),
555
+ output=entry.get("output"),
556
+ duration=float(entry.get("duration", 0.0)),
557
+ )
558
+ self.stage_results[stage_name] = result
559
+ if result.success:
560
+ self.results.append(result)
561
+
562
+ if self.stage_results:
563
+ self._log_event(
564
+ "checkpoint_loaded",
565
+ stages=len(self.stage_results),
566
+ path=str(self.checkpoint_path),
567
+ )
568
+
569
+ except Exception as exc:
570
+ logger.warning("pipeline.checkpoint.load_error", error=str(exc))
571
+
572
+ def _persist_checkpoint(self, result: PipelineResult) -> None:
573
+ if not self.resume_enabled:
574
+ return
575
+
576
+ payload = {
577
+ "pipeline": self.pipeline_data.get("name", "Unnamed"),
578
+ "stages": [
579
+ {
580
+ "stage": r.stage,
581
+ "success": r.success,
582
+ "duration": r.duration,
583
+ "output": self._summarize_output(r.output),
584
+ }
585
+ for r in self.stage_results.values()
586
+ ],
587
+ }
588
+
589
+ try:
590
+ with self.checkpoint_path.open("w", encoding="utf-8") as handle:
591
+ json.dump(payload, handle, ensure_ascii=False, indent=2)
592
+ except Exception as exc:
593
+ logger.warning("pipeline.checkpoint.save_error", error=str(exc))
594
+
595
+ def _finalize_checkpoint(self) -> None:
596
+ if not self.resume_enabled:
597
+ return
598
+
599
+ all_success = all(result.success for result in self.results) if self.results else False
600
+ if all_success and self.checkpoint_path.exists():
601
+ try:
602
+ self.checkpoint_path.unlink()
603
+ self._log_event("checkpoint_cleared", path=str(self.checkpoint_path))
604
+ except Exception as exc:
605
+ logger.debug("pipeline.checkpoint.cleanup_error", error=str(exc))
606
+
607
+ def _summarize_output(self, output: Any) -> Any:
608
+ if output is None:
609
+ return None
610
+ if isinstance(output, (str, int, float, bool)):
611
+ text = str(output)
612
+ else:
613
+ text = str(output)
614
+ return text[:2000]
615
+
616
+ def _log_event(self, event: str, **payload: Any) -> None:
617
+ if not self.log_file_path:
618
+ return
619
+ entry = {
620
+ "event": event,
621
+ "timestamp": time.time(),
622
+ **payload,
623
+ }
624
+ try:
625
+ with self.log_file_path.open("a", encoding="utf-8") as handle:
626
+ handle.write(json.dumps(entry, ensure_ascii=False) + "\n")
627
+ except Exception as exc:
628
+ logger.debug("pipeline.log.error", error=str(exc))
629
+
630
+ async def _run_dns(self, config: Dict[str, Any]) -> Any:
631
+ """Executa módulo DNS."""
632
+ from moriarty.net.dns_client import DNSClient
633
+
634
+ client = DNSClient()
635
+ result = await client.lookup_domain(self.pipeline_data["target"])
636
+ return result
637
+
638
+ async def _run_subdiscover(self, config: Dict[str, Any]) -> Any:
639
+ """Executa subdomain discovery."""
640
+ from moriarty.modules.subdomain_discovery import SubdomainDiscovery
641
+
642
+ discovery = SubdomainDiscovery(
643
+ domain=self.pipeline_data["target"],
644
+ sources=config.get("sources"),
645
+ validate=config.get("validate", True),
646
+ )
647
+ return await discovery.discover()
648
+
649
+ async def _run_ports(self, config: Dict[str, Any]) -> Any:
650
+ """Executa port scan."""
651
+ profile = config.get("profile", "quick")
652
+ concurrency = int(config.get("concurrency", 200))
653
+ timeout = float(config.get("timeout", 1.5))
654
+
655
+ scanner = PortScanner(
656
+ target=self.pipeline_data["target"],
657
+ profile=profile,
658
+ concurrency=concurrency,
659
+ timeout=timeout,
660
+ )
661
+ results = await scanner.scan()
662
+ return {
663
+ "profile": profile,
664
+ "results": [r.__dict__ for r in results],
665
+ }
666
+
667
+ async def _run_template_scan(self, config: Dict[str, Any]) -> Any:
668
+ """Executa template scan."""
669
+ from moriarty.modules.template_scanner import TemplateScanner
670
+
671
+ scanner = TemplateScanner(
672
+ target=self.pipeline_data["target"],
673
+ severity_filter=config.get("severity"),
674
+ )
675
+ return await scanner.scan()
676
+
677
+ async def _run_wayback(self, config: Dict[str, Any]) -> Any:
678
+ """Executa wayback discovery."""
679
+ from moriarty.modules.wayback_discovery import WaybackDiscovery
680
+
681
+ wayback = WaybackDiscovery(
682
+ domain=self.pipeline_data["target"],
683
+ filter_extensions=config.get("filter_extensions"),
684
+ filter_status_codes=config.get("filter_status_codes"),
685
+ )
686
+ return await wayback.discover()
687
+
688
+ async def _run_passive(self, config: Dict[str, Any]) -> Any:
689
+ """Executa coleta passiva utilizando PassiveRecon."""
690
+ recon = PassiveRecon(self.pipeline_data["target"], timeout=float(config.get("timeout", 15.0)))
691
+ try:
692
+ result = await recon.collect()
693
+ return result.to_dict()
694
+ finally:
695
+ await recon.close()
696
+
697
+ async def _run_crawl(self, config: Dict[str, Any]) -> Any:
698
+ """Executa crawler leve."""
699
+ base_url = config.get("base_url") or f"https://{self.pipeline_data['target']}"
700
+ crawler = WebCrawler(
701
+ base_url=base_url,
702
+ max_pages=int(config.get("max_pages", 100)),
703
+ max_depth=int(config.get("max_depth", 2)),
704
+ concurrency=int(config.get("concurrency", 10)),
705
+ follow_subdomains=bool(config.get("follow_subdomains", False)),
706
+ )
707
+ try:
708
+ pages = await crawler.crawl()
709
+ return {url: page.__dict__ for url, page in pages.items()}
710
+ finally:
711
+ await crawler.close()
712
+
713
+ def _show_results(self):
714
+ """Mostra resultados do pipeline."""
715
+ console.print("\n[bold]📊 Resultados:[/bold]\n")
716
+
717
+ for result in self.results:
718
+ status = "✓" if result.success else "✗"
719
+ color = "green" if result.success else "red"
720
+ console.print(f"[{color}]{status} {result.stage}[/{color}] - {result.duration:.2f}s")
721
+
722
+ successful = sum(1 for r in self.results if r.success)
723
+ console.print(f"\n[cyan]Total:[/cyan] {successful}/{len(self.results)} stages bem-sucedidos")
724
+
725
+
726
+ __all__ = ["PipelineOrchestrator", "PipelineStage", "PipelineResult"]