active_stix 0.1.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (289) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +32 -0
  5. data/app/assets/config/active_stix_manifest.js +2 -0
  6. data/app/assets/javascripts/active_stix/application.js +15 -0
  7. data/app/assets/javascripts/active_stix/artifacts.js +2 -0
  8. data/app/assets/javascripts/active_stix/attack_patterns.js +2 -0
  9. data/app/assets/javascripts/active_stix/bcc_refs.js +2 -0
  10. data/app/assets/javascripts/active_stix/bundled_objects.js +2 -0
  11. data/app/assets/javascripts/active_stix/bundles.js +2 -0
  12. data/app/assets/javascripts/active_stix/campaigns.js +2 -0
  13. data/app/assets/javascripts/active_stix/course_of_actions.js +2 -0
  14. data/app/assets/javascripts/active_stix/cyber_observables.js +2 -0
  15. data/app/assets/javascripts/active_stix/email_messages.js +2 -0
  16. data/app/assets/javascripts/active_stix/external_references.js +2 -0
  17. data/app/assets/javascripts/active_stix/files.js +2 -0
  18. data/app/assets/javascripts/active_stix/identities.js +2 -0
  19. data/app/assets/javascripts/active_stix/indicator_labels.js +2 -0
  20. data/app/assets/javascripts/active_stix/indicators.js +2 -0
  21. data/app/assets/javascripts/active_stix/intrusion_sets.js +2 -0
  22. data/app/assets/javascripts/active_stix/kill_chain_phases.js +2 -0
  23. data/app/assets/javascripts/active_stix/kill_chains.js +2 -0
  24. data/app/assets/javascripts/active_stix/malwares.js +2 -0
  25. data/app/assets/javascripts/active_stix/marking_definitions.js +2 -0
  26. data/app/assets/javascripts/active_stix/observed_data.js +2 -0
  27. data/app/assets/javascripts/active_stix/open_vocabularies.js +2 -0
  28. data/app/assets/javascripts/active_stix/phases.js +2 -0
  29. data/app/assets/javascripts/active_stix/recipients.js +2 -0
  30. data/app/assets/javascripts/active_stix/relationships.js +2 -0
  31. data/app/assets/javascripts/active_stix/reports.js +2 -0
  32. data/app/assets/javascripts/active_stix/threat_actors.js +2 -0
  33. data/app/assets/javascripts/active_stix/tools.js +2 -0
  34. data/app/assets/javascripts/active_stix/urls.js +2 -0
  35. data/app/assets/javascripts/active_stix/users.js +2 -0
  36. data/app/assets/stylesheets/active_stix/application.css +15 -0
  37. data/app/assets/stylesheets/active_stix/artifacts.css +4 -0
  38. data/app/assets/stylesheets/active_stix/attack_patterns.css +4 -0
  39. data/app/assets/stylesheets/active_stix/bcc_refs.css +4 -0
  40. data/app/assets/stylesheets/active_stix/bundled_objects.css +4 -0
  41. data/app/assets/stylesheets/active_stix/bundles.css +4 -0
  42. data/app/assets/stylesheets/active_stix/campaigns.css +4 -0
  43. data/app/assets/stylesheets/active_stix/course_of_actions.css +4 -0
  44. data/app/assets/stylesheets/active_stix/cyber_observables.css +4 -0
  45. data/app/assets/stylesheets/active_stix/email_messages.css +4 -0
  46. data/app/assets/stylesheets/active_stix/external_references.css +4 -0
  47. data/app/assets/stylesheets/active_stix/files.css +4 -0
  48. data/app/assets/stylesheets/active_stix/identities.css +4 -0
  49. data/app/assets/stylesheets/active_stix/indicator_labels.css +4 -0
  50. data/app/assets/stylesheets/active_stix/indicators.css +4 -0
  51. data/app/assets/stylesheets/active_stix/intrusion_sets.css +4 -0
  52. data/app/assets/stylesheets/active_stix/kill_chain_phases.css +4 -0
  53. data/app/assets/stylesheets/active_stix/kill_chains.css +4 -0
  54. data/app/assets/stylesheets/active_stix/malwares.css +4 -0
  55. data/app/assets/stylesheets/active_stix/marking_definitions.css +4 -0
  56. data/app/assets/stylesheets/active_stix/observed_data.css +4 -0
  57. data/app/assets/stylesheets/active_stix/open_vocabularies.css +4 -0
  58. data/app/assets/stylesheets/active_stix/phases.css +4 -0
  59. data/app/assets/stylesheets/active_stix/recipients.css +4 -0
  60. data/app/assets/stylesheets/active_stix/relationships.css +4 -0
  61. data/app/assets/stylesheets/active_stix/reports.css +4 -0
  62. data/app/assets/stylesheets/active_stix/threat_actors.css +4 -0
  63. data/app/assets/stylesheets/active_stix/tools.css +4 -0
  64. data/app/assets/stylesheets/active_stix/urls.css +4 -0
  65. data/app/assets/stylesheets/active_stix/users.css +4 -0
  66. data/app/assets/stylesheets/scaffold.css +80 -0
  67. data/app/controllers/active_stix/application_controller.rb +5 -0
  68. data/app/controllers/active_stix/artifacts_controller.rb +62 -0
  69. data/app/controllers/active_stix/attack_patterns_controller.rb +27 -0
  70. data/app/controllers/active_stix/bcc_refs_controller.rb +62 -0
  71. data/app/controllers/active_stix/bundled_objects_controller.rb +62 -0
  72. data/app/controllers/active_stix/bundles_controller.rb +11 -0
  73. data/app/controllers/active_stix/campaigns_controller.rb +74 -0
  74. data/app/controllers/active_stix/course_of_actions_controller.rb +62 -0
  75. data/app/controllers/active_stix/cyber_observables_controller.rb +62 -0
  76. data/app/controllers/active_stix/email_addresses_controller.rb +74 -0
  77. data/app/controllers/active_stix/email_messages_controller.rb +26 -0
  78. data/app/controllers/active_stix/external_references_controller.rb +62 -0
  79. data/app/controllers/active_stix/files_controller.rb +74 -0
  80. data/app/controllers/active_stix/identities_controller.rb +128 -0
  81. data/app/controllers/active_stix/indicator_labels_controller.rb +62 -0
  82. data/app/controllers/active_stix/indicators_controller.rb +62 -0
  83. data/app/controllers/active_stix/intrusion_sets_controller.rb +62 -0
  84. data/app/controllers/active_stix/kill_chain_phases_controller.rb +62 -0
  85. data/app/controllers/active_stix/kill_chains_controller.rb +62 -0
  86. data/app/controllers/active_stix/malwares_controller.rb +62 -0
  87. data/app/controllers/active_stix/marking_definitions_controller.rb +62 -0
  88. data/app/controllers/active_stix/observed_data_controller.rb +62 -0
  89. data/app/controllers/active_stix/open_vocabularies_controller.rb +62 -0
  90. data/app/controllers/active_stix/phases_controller.rb +62 -0
  91. data/app/controllers/active_stix/recipients_controller.rb +62 -0
  92. data/app/controllers/active_stix/relationships_controller.rb +62 -0
  93. data/app/controllers/active_stix/reports_controller.rb +62 -0
  94. data/app/controllers/active_stix/threat_actors_controller.rb +75 -0
  95. data/app/controllers/active_stix/tools_controller.rb +62 -0
  96. data/app/controllers/active_stix/urls_controller.rb +62 -0
  97. data/app/controllers/active_stix/user_accounts_controller.rb +74 -0
  98. data/app/controllers/active_stix/users_controller.rb +62 -0
  99. data/app/helpers/active_stix/application_helper.rb +4 -0
  100. data/app/helpers/active_stix/artifacts_helper.rb +4 -0
  101. data/app/helpers/active_stix/attack_patterns_helper.rb +4 -0
  102. data/app/helpers/active_stix/bcc_refs_helper.rb +4 -0
  103. data/app/helpers/active_stix/bundled_objects_helper.rb +4 -0
  104. data/app/helpers/active_stix/bundles_helper.rb +4 -0
  105. data/app/helpers/active_stix/campaigns_helper.rb +4 -0
  106. data/app/helpers/active_stix/course_of_actions_helper.rb +4 -0
  107. data/app/helpers/active_stix/cyber_observables_helper.rb +4 -0
  108. data/app/helpers/active_stix/email_messages_helper.rb +4 -0
  109. data/app/helpers/active_stix/external_references_helper.rb +4 -0
  110. data/app/helpers/active_stix/files_helper.rb +4 -0
  111. data/app/helpers/active_stix/identities_helper.rb +4 -0
  112. data/app/helpers/active_stix/indicator_labels_helper.rb +4 -0
  113. data/app/helpers/active_stix/indicators_helper.rb +4 -0
  114. data/app/helpers/active_stix/intrusion_sets_helper.rb +4 -0
  115. data/app/helpers/active_stix/kill_chain_phases_helper.rb +4 -0
  116. data/app/helpers/active_stix/kill_chains_helper.rb +4 -0
  117. data/app/helpers/active_stix/malwares_helper.rb +4 -0
  118. data/app/helpers/active_stix/marking_definitions_helper.rb +4 -0
  119. data/app/helpers/active_stix/observed_data_helper.rb +4 -0
  120. data/app/helpers/active_stix/open_vocabularies_helper.rb +4 -0
  121. data/app/helpers/active_stix/phases_helper.rb +4 -0
  122. data/app/helpers/active_stix/recipients_helper.rb +4 -0
  123. data/app/helpers/active_stix/relationships_helper.rb +4 -0
  124. data/app/helpers/active_stix/reports_helper.rb +4 -0
  125. data/app/helpers/active_stix/threat_actors_helper.rb +4 -0
  126. data/app/helpers/active_stix/tools_helper.rb +4 -0
  127. data/app/helpers/active_stix/urls_helper.rb +4 -0
  128. data/app/helpers/active_stix/users_helper.rb +4 -0
  129. data/app/jobs/active_stix/application_job.rb +4 -0
  130. data/app/mailers/active_stix/application_mailer.rb +6 -0
  131. data/app/models/active_stix/application_record.rb +5 -0
  132. data/app/models/active_stix/artifact.rb +23 -0
  133. data/app/models/active_stix/attack_pattern.rb +150 -0
  134. data/app/models/active_stix/bcc_ref.rb +6 -0
  135. data/app/models/active_stix/bundle.rb +108 -0
  136. data/app/models/active_stix/bundled_object.rb +4 -0
  137. data/app/models/active_stix/campaign.rb +65 -0
  138. data/app/models/active_stix/cc_ref.rb +6 -0
  139. data/app/models/active_stix/course_of_action.rb +54 -0
  140. data/app/models/active_stix/cyber_observable.rb +4 -0
  141. data/app/models/active_stix/email_address.rb +27 -0
  142. data/app/models/active_stix/email_message.rb +339 -0
  143. data/app/models/active_stix/external_reference.rb +48 -0
  144. data/app/models/active_stix/file.rb +2 -0
  145. data/app/models/active_stix/identity.rb +141 -0
  146. data/app/models/active_stix/indicator.rb +58 -0
  147. data/app/models/active_stix/indicator_label.rb +4 -0
  148. data/app/models/active_stix/intrusion_set.rb +69 -0
  149. data/app/models/active_stix/kill_chain.rb +7 -0
  150. data/app/models/active_stix/kill_chain_phase.rb +6 -0
  151. data/app/models/active_stix/label.rb +17 -0
  152. data/app/models/active_stix/label_malware.rb +4 -0
  153. data/app/models/active_stix/label_report.rb +4 -0
  154. data/app/models/active_stix/label_tool.rb +4 -0
  155. data/app/models/active_stix/malware.rb +98 -0
  156. data/app/models/active_stix/marking_definition.rb +21 -0
  157. data/app/models/active_stix/markup.rb +6 -0
  158. data/app/models/active_stix/object_marking.rb +11 -0
  159. data/app/models/active_stix/observed_datum.rb +67 -0
  160. data/app/models/active_stix/open_vocabulary.rb +8 -0
  161. data/app/models/active_stix/phase.rb +41 -0
  162. data/app/models/active_stix/recipient.rb +4 -0
  163. data/app/models/active_stix/reference_item.rb +4 -0
  164. data/app/models/active_stix/relationship.rb +95 -0
  165. data/app/models/active_stix/report.rb +93 -0
  166. data/app/models/active_stix/report_object.rb +9 -0
  167. data/app/models/active_stix/threat_actor.rb +139 -0
  168. data/app/models/active_stix/to_ref.rb +6 -0
  169. data/app/models/active_stix/tool.rb +112 -0
  170. data/app/models/active_stix/url.rb +15 -0
  171. data/app/models/active_stix/user.rb +4 -0
  172. data/app/models/active_stix/user_account.rb +3 -0
  173. data/app/views/active_stix/artifacts/_form.html.erb +57 -0
  174. data/app/views/active_stix/artifacts/edit.html.erb +6 -0
  175. data/app/views/active_stix/artifacts/index.html.erb +41 -0
  176. data/app/views/active_stix/artifacts/new.html.erb +5 -0
  177. data/app/views/active_stix/artifacts/show.html.erb +44 -0
  178. data/app/views/active_stix/attack_patterns/_form.html.erb +37 -0
  179. data/app/views/active_stix/attack_patterns/edit.html.erb +2 -0
  180. data/app/views/active_stix/attack_patterns/index.html.erb +2 -0
  181. data/app/views/active_stix/attack_patterns/new.html.erb +2 -0
  182. data/app/views/active_stix/attack_patterns/show.html.erb +140 -0
  183. data/app/views/active_stix/bcc_refs/_form.html.erb +27 -0
  184. data/app/views/active_stix/bcc_refs/edit.html.erb +6 -0
  185. data/app/views/active_stix/bcc_refs/index.html.erb +29 -0
  186. data/app/views/active_stix/bcc_refs/new.html.erb +5 -0
  187. data/app/views/active_stix/bcc_refs/show.html.erb +14 -0
  188. data/app/views/active_stix/bundles/index.html.erb +1 -0
  189. data/app/views/active_stix/bundles/show.html.erb +7 -0
  190. data/app/views/active_stix/campaigns/_form.html.erb +42 -0
  191. data/app/views/active_stix/campaigns/_stix_campaign.json.jbuilder +2 -0
  192. data/app/views/active_stix/campaigns/edit.html.erb +6 -0
  193. data/app/views/active_stix/campaigns/index.html.erb +35 -0
  194. data/app/views/active_stix/campaigns/index.json.jbuilder +1 -0
  195. data/app/views/active_stix/campaigns/new.html.erb +5 -0
  196. data/app/views/active_stix/campaigns/show.html.erb +29 -0
  197. data/app/views/active_stix/campaigns/show.json.jbuilder +1 -0
  198. data/app/views/active_stix/email_messages/_form.html.erb +62 -0
  199. data/app/views/active_stix/email_messages/_stix_email_message.json.jbuilder +2 -0
  200. data/app/views/active_stix/email_messages/edit.html.erb +6 -0
  201. data/app/views/active_stix/email_messages/index.html.erb +43 -0
  202. data/app/views/active_stix/email_messages/index.json.jbuilder +1 -0
  203. data/app/views/active_stix/email_messages/new.html.erb +5 -0
  204. data/app/views/active_stix/email_messages/show.html.erb +165 -0
  205. data/app/views/active_stix/email_messages/show.json.jbuilder +1 -0
  206. data/app/views/active_stix/files/_form.html.erb +92 -0
  207. data/app/views/active_stix/files/_stix_file.json.jbuilder +2 -0
  208. data/app/views/active_stix/files/edit.html.erb +6 -0
  209. data/app/views/active_stix/files/index.html.erb +55 -0
  210. data/app/views/active_stix/files/index.json.jbuilder +1 -0
  211. data/app/views/active_stix/files/new.html.erb +5 -0
  212. data/app/views/active_stix/files/show.html.erb +79 -0
  213. data/app/views/active_stix/files/show.json.jbuilder +1 -0
  214. data/app/views/active_stix/identities/_form.html.erb +27 -0
  215. data/app/views/active_stix/identities/_individual.html.erb +100 -0
  216. data/app/views/active_stix/identities/_organization.html.erb +72 -0
  217. data/app/views/active_stix/identities/_received_email_messages.html.erb +27 -0
  218. data/app/views/active_stix/identities/_sent_email_messages.html.erb +27 -0
  219. data/app/views/active_stix/identities/_threat_icons.html.erb +3 -0
  220. data/app/views/active_stix/identities/edit.html.erb +2 -0
  221. data/app/views/active_stix/identities/index.html.erb +37 -0
  222. data/app/views/active_stix/identities/new.html.erb +5 -0
  223. data/app/views/active_stix/identities/show.html.erb +15 -0
  224. data/app/views/active_stix/layouts/active_stix/application.html.erb +16 -0
  225. data/app/views/active_stix/recipients/_form.html.erb +27 -0
  226. data/app/views/active_stix/recipients/edit.html.erb +6 -0
  227. data/app/views/active_stix/recipients/index.html.erb +29 -0
  228. data/app/views/active_stix/recipients/new.html.erb +5 -0
  229. data/app/views/active_stix/recipients/show.html.erb +14 -0
  230. data/app/views/active_stix/threat_actors/_form.html.erb +32 -0
  231. data/app/views/active_stix/threat_actors/_stix_threat_actor.json.jbuilder +2 -0
  232. data/app/views/active_stix/threat_actors/edit.html.erb +6 -0
  233. data/app/views/active_stix/threat_actors/flags.html.erb +184 -0
  234. data/app/views/active_stix/threat_actors/index.html.erb +26 -0
  235. data/app/views/active_stix/threat_actors/index.json.jbuilder +1 -0
  236. data/app/views/active_stix/threat_actors/new.html.erb +5 -0
  237. data/app/views/active_stix/threat_actors/show.html.erb +4 -0
  238. data/app/views/active_stix/threat_actors/show.json.jbuilder +1 -0
  239. data/app/views/layouts/active_stix/application.html.erb +16 -0
  240. data/config/routes.rb +39 -0
  241. data/db/migrate/20191204200025_create_active_stix_bundled_objects.rb +11 -0
  242. data/db/migrate/20191204213707_create_active_stix_bundles.rb +10 -0
  243. data/db/migrate/20191204213802_create_active_stix_campaigns.rb +15 -0
  244. data/db/migrate/20191204213926_create_active_stix_course_of_actions.rb +12 -0
  245. data/db/migrate/20191204214020_create_active_stix_cyber_observables.rb +11 -0
  246. data/db/migrate/20191204214955_create_active_stix_email_messages.rb +20 -0
  247. data/db/migrate/20191204215029_create_active_stix_external_references.rb +12 -0
  248. data/db/migrate/20191204215302_create_active_stix_files.rb +23 -0
  249. data/db/migrate/20191204215419_create_active_stix_identities.rb +13 -0
  250. data/db/migrate/20191204215542_create_active_stix_indicator_labels.rb +10 -0
  251. data/db/migrate/20191204215637_create_active_stix_indicators.rb +16 -0
  252. data/db/migrate/20191204215849_create_active_stix_intrusion_sets.rb +15 -0
  253. data/db/migrate/20191204215929_create_active_stix_kill_chain_phases.rb +10 -0
  254. data/db/migrate/20191204215951_create_active_stix_kill_chains.rb +9 -0
  255. data/db/migrate/20191204220149_create_active_stix_malwares.rb +12 -0
  256. data/db/migrate/20191204220539_create_active_stix_marking_definitions.rb +12 -0
  257. data/db/migrate/20191204220853_create_active_stix_observed_data.rb +12 -0
  258. data/db/migrate/20191204220917_create_active_stix_open_vocabularies.rb +9 -0
  259. data/db/migrate/20191204220952_create_active_stix_phases.rb +11 -0
  260. data/db/migrate/20191204221129_create_active_stix_recipients.rb +10 -0
  261. data/db/migrate/20191204221227_create_active_stix_relationships.rb +16 -0
  262. data/db/migrate/20191204221323_create_active_stix_report_objects.rb +11 -0
  263. data/db/migrate/20191204221359_create_active_stix_reports.rb +14 -0
  264. data/db/migrate/20191204221425_create_active_stix_threat_actors.rb +11 -0
  265. data/db/migrate/20191204221454_create_active_stix_tools.rb +12 -0
  266. data/db/migrate/20191204221639_create_active_stix_urls.rb +9 -0
  267. data/db/migrate/20191204221849_create_active_stix_users.rb +22 -0
  268. data/db/migrate/20191205182234_create_active_stix_bcc_refs.rb +10 -0
  269. data/db/migrate/20191205182255_create_active_stix_cc_refs.rb +10 -0
  270. data/db/migrate/20191205182316_create_active_stix_to_refs.rb +10 -0
  271. data/db/migrate/20191212203611_add_spec_version_to_bundles.rb +5 -0
  272. data/db/migrate/20191212215136_create_active_stix_attack_patterns.rb +12 -0
  273. data/db/migrate/20191212220222_create_active_stix_reference_items.rb +11 -0
  274. data/db/migrate/20191213135204_create_active_stix_labels.rb +10 -0
  275. data/db/migrate/20191213140951_create_active_stix_markups.rb +11 -0
  276. data/db/migrate/20191221210537_fix_observed_data.rb +6 -0
  277. data/db/migrate/20191221223602_create_active_stix_artifacts.rb +16 -0
  278. data/db/migrate/20191223075550_change_artifact_ref_to_string.rb +5 -0
  279. data/db/migrate/20191223154000_add_stix_id_to_email_messages.rb +5 -0
  280. data/db/migrate/20200114162245_add_labels_to_active_stix_identities.rb +5 -0
  281. data/db/migrate/20200404223006_add_aliases_to_tools.rb +5 -0
  282. data/db/migrate/20200404223047_add_aliases_to_attack_patterns.rb +5 -0
  283. data/db/migrate/20200404223158_add_aliases_to_malwares.rb +5 -0
  284. data/db/migrate/20200404223210_add_aliases_to_threat_actors.rb +5 -0
  285. data/lib/active_stix.rb +8 -0
  286. data/lib/active_stix/engine.rb +13 -0
  287. data/lib/active_stix/version.rb +3 -0
  288. data/lib/tasks/active_stix_tasks.rake +4 -0
  289. metadata +358 -0
@@ -0,0 +1,4 @@
1
+ class ActiveStix::BundledObject < ApplicationRecord
2
+ belongs_to :bundle, foreign_key: "bundle_ref", primary_key: "stix_id"
3
+ belongs_to :stix_object, polymorphic: true, foreign_key: "object_ref", primary_key: "stix_id", foreign_type: :object_type
4
+ end
@@ -0,0 +1,65 @@
1
+ class ActiveStix::Campaign < ApplicationRecord
2
+ has_many :source_relationships, class_name: 'ActiveStix::Relationship', primary_key: 'stix_id', foreign_key: 'source_ref' #relationships where this class is the source
3
+ has_many :target_relationships, class_name: 'ActiveStix::Relationship', primary_key: 'stix_id', foreign_key: 'target_ref' #relationships where this class is the target
4
+
5
+ def self.ingest_json(obj)
6
+ camp = find_or_create_by(stix_id: obj['id'], name: obj['name'], description: obj['description'], first_seen: obj['first_seen'], last_seen: obj['last_seen'])
7
+ camp
8
+ end
9
+
10
+ before_create do
11
+ self.stix_id = "#{type}--#{SecureRandom.uuid}" if stix_id.blank?
12
+ end
13
+
14
+
15
+ def type
16
+ 'campaign'
17
+ end
18
+
19
+
20
+ def attack_patterns
21
+ attack_pattern_relationships.map(&:target)
22
+ end
23
+
24
+ def attack_pattern_relationships
25
+ relationships = []
26
+ ActiveStix::Relationship.where(source: self, relationship_type: "uses", target_type: "ActiveStix::AttackPattern").each do |rel|
27
+ relationships << rel
28
+ end
29
+ relationships
30
+ end
31
+
32
+ def indicator_relationships
33
+ relationships = []
34
+ ActiveStix::Relationship.where(source_type: "ActiveStix::Indicator", relationship_type: "indicates", target: self).each do |rel|
35
+ relationships << rel
36
+ end
37
+ relationships
38
+ end
39
+
40
+ def as_stix
41
+ as_json(only: []).tap do |hash|
42
+ hash["id"] = stix_id
43
+ hash["type"] = type
44
+ hash["created"] = created_at.rfc3339(3)
45
+ hash["modified"] = updated_at.rfc3339(3)
46
+ hash["first_seen"] = created_at.rfc3339(3)
47
+ hash["last_seen"] = updated_at.rfc3339(3)
48
+ hash["name"] = name
49
+ hash["description"] = description
50
+ end
51
+ end
52
+
53
+ def convert_to_json
54
+ {
55
+ :type => "campaign",
56
+ :id => stix_id,
57
+ :created => created_at.to_s,
58
+ :modified => updated_at.to_s,
59
+ :name => name,
60
+ :description => description,
61
+ :first_seen => first_seen,
62
+ :last_seen => last_seen
63
+ }
64
+ end
65
+ end
@@ -0,0 +1,6 @@
1
+ module ActiveStix
2
+ class CcRef < ActiveStix::Recipient
3
+ belongs_to :email_message
4
+ belongs_to :email_address
5
+ end
6
+ end
@@ -0,0 +1,54 @@
1
+ module ActiveStix
2
+ class CourseOfAction < ApplicationRecord
3
+ has_many :reference_items, as: 'referrer'
4
+ has_many :external_references, class_name: 'ActiveStix::ExternalReference', through: :reference_items
5
+
6
+ has_many :reference_object_marking_courses, class_name: 'ActiveStix::ReferenceObjectMarkingCourse', foreign_key: 'stix_course_of_action_id'
7
+ has_many :marking_definitions, class_name: 'ActiveStix::MarkingDefinition', through: :reference_object_marking_courses, primary_key: 'id'
8
+
9
+ has_many :source_relationships, class_name: 'ActiveStix::Relationship', primary_key: 'stix_id', foreign_key: 'source_ref' #relationships where this class is the source
10
+ has_many :target_relationships, class_name: 'ActiveStix::Relationship', primary_key: 'stix_id', foreign_key: 'target_ref' #relationships where this class is the target
11
+
12
+ def self.ingest_json(obj)
13
+ course_of_action = find_or_create_by(stix_id: obj['id'], name: obj['name'], description: obj['description'])
14
+ if obj.has_key?('external_references')
15
+ obj['external_references'].each do |er|
16
+ external_reference = ExternalReference.ingest_json(er, obj['id'])
17
+ course_of_action.external_references << external_reference unless ActiveStix::ReferenceItem.find_by(external_reference:external_reference, referrer: course_of_action)
18
+ end
19
+ end
20
+ if obj.has_key?('object_marking_refs')
21
+ # TODO
22
+ # obj['object_marking_refs'].each do |mr|
23
+ # marking_definition = MarkingDefinition.create_by_id(mr)
24
+ # course_of_action.marking_definitions << marking_definition unless ActiveStix::ReferenceObjectMarkingCourse.find_by(stix_marking_definition_id:marking_definition.id, stix_course_of_action_id:course_of_action.id)
25
+ # end
26
+ end
27
+ course_of_action.save
28
+ course_of_action
29
+ end
30
+
31
+ def convert_to_json
32
+ external_refs_arr = []
33
+ external_references.each do | x |
34
+ external_refs_arr << x.convert_to_json
35
+ end
36
+
37
+ marking_def_arr = []
38
+ marking_definitions.each do | x |
39
+ marking_def_arr << x.convert_to_json
40
+ end
41
+
42
+ {
43
+ :external_references => external_refs_arr,
44
+ :object_marking_refs => marking_def_arr,
45
+ :id => stix_id,
46
+ :name => name,
47
+ :type => "course-of-action",
48
+ :modified => updated_at.to_s,
49
+ :created => created_at.to_s,
50
+ :description => description
51
+ }
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,4 @@
1
+ class ActiveStix::CyberObservable < ApplicationRecord
2
+ belongs_to :observed_datum, :class_name => 'ActiveStix::ObservedDatum', foreign_key: :observed_datum_ref, primary_key: :stix_id
3
+ belongs_to :cyber_observable_object, polymorphic: true, foreign_key: :observable_object_id
4
+ end
@@ -0,0 +1,27 @@
1
+ module ActiveStix
2
+ class EmailAddress < ApplicationRecord
3
+
4
+ has_many :to_refs, foreign_key: 'stix_email_address_id'
5
+ has_many :email_messages, foreign_key: :from_ref
6
+ belongs_to :identity, class_name: 'ActiveStix::Identity'
7
+
8
+ # after_create_commit do
9
+ # assign_iddentity_to_group
10
+ # end
11
+
12
+ def self.from_eml(eml)
13
+ eml.correspondences.all.collect do |c|
14
+ {
15
+ "type": "email-address",
16
+ "value": c.email.address,
17
+ "display_name": c.email.alias,
18
+ "from_ref": c.agent.id
19
+ }
20
+ end
21
+ end
22
+
23
+ def assign_identity_to_group
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,339 @@
1
+ module ActiveStix
2
+ class EmailMessage < ApplicationRecord
3
+ has_many :to_refs, foreign_key: 'email_message_id'
4
+ has_many :cc_refs, foreign_key: 'email_message_id'
5
+ has_many :bcc_refs, foreign_key: 'email_message_id'
6
+ has_many :recipients, foreign_key: 'email_message_id'
7
+ has_many :cyber_observables, :class_name => 'ActiveStix::CyberObservable', foreign_key: :observable_object_id, as: :cyber_observable_object
8
+ has_many :observed_data, through: :cyber_observables
9
+ belongs_to :from, class_name: 'ActiveStix::EmailAddress', foreign_key: 'from_ref'
10
+ belongs_to :raw_email_artifact, foreign_key: :raw_email_ref, class_name: 'ActiveStix::Artifact', primary_key: :stix_id
11
+
12
+
13
+ before_create do
14
+ self.stix_id = "#{type}--#{SecureRandom.uuid}" if stix_id.blank?
15
+ end
16
+
17
+ after_create do
18
+ ActiveStix::ObservedDatum.wrap_object(self)
19
+ end
20
+
21
+ def primary_observed_datum
22
+ observed_data.first
23
+ end
24
+
25
+ def from_identity
26
+ from.identity
27
+ end
28
+
29
+ def identities
30
+ ids = [from.identity]
31
+ to_refs.each do |tr|
32
+ ids << tr.email_address.identity
33
+ end
34
+
35
+ cc_refs.each do |ccr|
36
+ ids << ccr.email_address.identity
37
+ end
38
+
39
+ bcc_refs.each do |bccr|
40
+ ids << bccr.email_address.identity
41
+ end
42
+ ids.uniq
43
+ end
44
+
45
+ def mail_server
46
+ Mail.new(raw_email_artifact.payload_bin).message_id.split(/[@\.]/)[-3..-1]
47
+ end
48
+
49
+ def readable
50
+ eml.readable
51
+ end
52
+
53
+ def self.from_eml(eml)
54
+ eml = eml.encode(Encoding.find('UTF-8'), {invalid: :replace, undef: :replace, replace: ''}).sub("\xEF\xBB\xBF".force_encoding('UTF-8'), "").gsub("\r", "").unicode_normalize(:nfkc)
55
+ mail = Mail.new(eml)
56
+
57
+ #TODO Add details for cc_refs, bcc_refs etc. from the email message object
58
+
59
+ is_multipart = mail.multipart?
60
+ date = mail.date
61
+ content_type = mail.content_type
62
+ from = create_from(mail, eml)
63
+ sender_ref = create_sender(mail, eml)
64
+ subject = mail.header["Subject"] ? mail.header["Subject"].value : ""
65
+ received_lines = mail.header["Received"]
66
+
67
+ #TODO add the appropriate details here later
68
+ #TODO late make additional header fields more specific, check stix spec
69
+ email_message = EmailMessage.create(
70
+ "is_multipart": is_multipart,
71
+ "date": date,
72
+ "content_type": content_type,
73
+ "from": from,
74
+ "sender_ref": sender_ref,
75
+ "subject": subject,
76
+ "received_lines": received_lines,
77
+ "additional_header_fields": mail.header,
78
+ "body": mail.body,
79
+ "body_multipart": body_multipart(mail),
80
+ "raw_email_ref": raw_email_artifact(mail).stix_id
81
+ )
82
+ create_recipients(mail, eml, email_message)
83
+
84
+ email_message
85
+ end
86
+
87
+ def self.raw_email_artifact(eml)
88
+ artifact = Artifact.create_from_eml(eml)
89
+ end
90
+
91
+ def self.body_multipart(mail)
92
+ if mail.multipart?
93
+ mail.parts.collect {|part| part.mime_type}
94
+ else
95
+ nil
96
+ end
97
+ end
98
+
99
+ def type
100
+ return "email-message"
101
+ end
102
+
103
+ def self.extract_info_from_address_header(descriptive_name)
104
+ descriptive_name = descriptive_name.to_s
105
+ descriptive_name.gsub!('\"', '')
106
+ temp = descriptive_name.split(' via ')
107
+ fullname = temp[0].to_s
108
+ if temp.size > 1
109
+ medium = temp[1]
110
+ end
111
+ if not fullname.lstrip().start_with?('<')
112
+ name_parts = fullname.split(',')
113
+ if name_parts.size > 1
114
+ last_name = name_parts[0]
115
+ first_name = name_parts[1].lstrip()
116
+ else
117
+ name_parts = fullname.split(' ')
118
+ if name_parts.size > 1
119
+ first_name = name_parts[0]
120
+ last_name = name_parts[1]
121
+ end
122
+ end
123
+ end
124
+ return first_name, last_name, medium
125
+ end
126
+
127
+ def self.create_recipients(mail, eml, email_message)
128
+ if mail.header["To"]
129
+ get_recipients_by_type("To", mail, eml, email_message)
130
+ end
131
+
132
+ if mail.header["CC"]
133
+ get_recipients_by_type("CC", mail, eml, email_message)
134
+ end
135
+
136
+ if mail.header["BCC"]
137
+ get_recipients_by_type("BCC", mail, eml, email_message)
138
+ end
139
+ end
140
+
141
+ #TODO The two methods below can definitely be consolidated to one. Make sure to do so.
142
+ def self.create_from(mail, eml)
143
+ if mail.header["From"]
144
+ mail.header["From"].address_list.addresses.each do |address|
145
+ user_account = UserAccount.where("lower(user_id) = ?", address.address.downcase).first
146
+ fname, lname, medium = extract_info_from_address_header(address.display_name)
147
+ #TODO Create an identity here so it can be linked to the user account and email address
148
+ if user_account.nil?
149
+ identity = create_identity(address.address.downcase, address.name)
150
+ user_account = UserAccount.create(user_id: address.address.downcase, account_login: get_name_from_address(address.address), display_name: address.name, is_service_account: false, is_privileged: false, can_escalate_privs: false, is_disabled: false, identity_id: identity.id)
151
+ identity.user_accounts << user_account
152
+ else
153
+ identity = user_account.identity
154
+ end
155
+ email_address = EmailAddress.where("lower(value) = ?", address.address.downcase).first
156
+ if email_address.nil?
157
+ email_address = EmailAddress.create(value: address.address.downcase, display_name: address.name, belongs_to_ref: user_account.id, identity_id: identity.id)
158
+ end
159
+
160
+ return email_address
161
+ end
162
+ end
163
+
164
+ end
165
+
166
+ def self.create_sender(mail, eml)
167
+ if mail.from.any?
168
+ address = mail.from.first
169
+ user_account = UserAccount.where("lower(user_id) = ?", address.downcase).first
170
+ #TODO Create an identity here so it can be linked to the user account and email address
171
+ if user_account.nil?
172
+ identity = create_identity(address, address)
173
+ user_account = UserAccount.create(user_id: address, account_login: get_name_from_address(address), display_name: address, is_service_account: false, is_privileged: false, can_escalate_privs: false, is_disabled: false, identity_id: identity.id)
174
+ identity.users_accounts << user_account
175
+ else
176
+ identity = user_account.identity
177
+ end
178
+ email_address = EmailAddress.where("lower(value) = ?", address.downcase).first
179
+ if email_address.nil?
180
+ email_address = EmailAddress.create(value: address, display_name: address, belongs_to_ref: user_account.id, identity_id: identity.id)
181
+ end
182
+ return email_address
183
+ end
184
+ end
185
+
186
+ def self.get_recipients_by_type(recipient_type, mail, eml, email_message)
187
+ return if mail.header[recipient_type].errors.any? # todo we should throw and catch an exception here
188
+ mail.header[recipient_type].each do |address|
189
+ # TODO this will be the user account
190
+ user_account = UserAccount.where("lower(user_id) = ?", address.address.downcase).first
191
+
192
+ fname, lname, medium = extract_info_from_address_header(address.display_name)
193
+
194
+ #TODO Create an identity here so it can be linked to the user account and email address
195
+ if user_account.nil?
196
+ identity = create_identity(address.address.downcase, address.name)
197
+ user_account = identity.user_accounts.create(user_id: address.address, account_login: get_name_from_address(address.address), display_name: address.name, is_service_account: false, is_privileged: false, can_escalate_privs: false, is_disabled: false)
198
+ else
199
+ identity = user_account.identity
200
+ end
201
+
202
+ # TODO this will be the email address
203
+ email_address = EmailAddress.where("lower(value) = ?", address.address.downcase).first
204
+ if email_address.nil?
205
+ email_address = EmailAddress.create(value: address.address.downcase, display_name: address.name, belongs_to_ref: user_account.id, identity_id: identity.id)
206
+ end
207
+
208
+ # Create header specific refs
209
+ create_recipient_type_ref(recipient_type, email_message, email_address)
210
+ end
211
+ end
212
+
213
+ def self.create_recipient_type_ref(recipient_type, email_message, email_address)
214
+
215
+ case recipient_type
216
+ when "To"
217
+ ToRef.create(email_message: email_message, email_address: email_address)
218
+ when "CC"
219
+ CcRef.create(email_message: email_message, email_address: email_address)
220
+ when "BCC"
221
+ BccRef.create(email_message: email_message, email_address: email_address)
222
+ end
223
+ end
224
+
225
+ def self.create_identity(address, display_name)
226
+ #TODO figure out where to get the details for whether for identity_class, description etc.
227
+ identity = Identity.create(name: display_name || Mail::Address.new(address).local, contact_information: {email_addresses: [address]}, identity_class: 'individual')
228
+
229
+ organization = from_domain_identity(address)
230
+ ActiveStix::Identity.employ(identity, organization)
231
+
232
+ return identity
233
+ end
234
+
235
+ #NOTE Instance method created for the class to use
236
+ def self.from_domain_identity(address)
237
+ org_name = Organization.company_from_email_address(address)
238
+ public_suffix = Organization.public_suffix_from_email_address(address)
239
+
240
+ organization = ActiveStix::Identity.find_or_create_by(name: org_name + public_suffix, identity_class: "organization")
241
+
242
+ if organization.contact_information.nil?
243
+ organization.update_attribute("contact_information", {domain: org_name, public_suffix: public_suffix})
244
+ else
245
+ contact_information = organization.contact_information
246
+ contact_information["public_suffix"] = public_suffix
247
+ organization.contact_information = contact_information
248
+ organization.save
249
+ end
250
+
251
+ freemail = ActiveStix::AttackPattern.find_by(name: "Free email")
252
+ if freemail and freemail.targets?(organization)
253
+ personal_organization = ActiveStix::Identity.find_or_create_by(name: address, identity_class: "organization")
254
+ ActiveStix::Identity.employ(identity, personal_organization)
255
+ end
256
+ organization
257
+ end
258
+
259
+ def from_domain_identity
260
+ ActiveStix::EmailMessage.from_domain_identity(from.value)
261
+ end
262
+
263
+ def self.get_name_from_address(address)
264
+ return address.split('@')[0]
265
+ end
266
+
267
+ def self.find_or_create_user_account(email, aliasname)
268
+ if email.agent.nil?
269
+ agent = Agent.create
270
+ agent.emails << email
271
+ else
272
+ agent = email.agent
273
+ unless agent.emails.where(alias: aliasname).any?
274
+ agent.emails << email
275
+ end
276
+ end
277
+ return agent
278
+ end
279
+
280
+ def stix_references
281
+ object_refs = {}
282
+ object_index = 1
283
+ [to_refs, cc_refs, bcc_refs].each do |field|
284
+ field.each do |ref|
285
+ object_refs[{
286
+
287
+ "type": "email-addr",
288
+ "value": ref.email_address.value.to_s,
289
+ "display_name": ref.email_address.display_name.to_s
290
+ }] = object_index.to_s
291
+ object_index += 1
292
+ end
293
+ end
294
+ object_refs[{
295
+
296
+ "type": "email-addr",
297
+ "value": from.value.to_s,
298
+ "display_name": from.display_name.to_s
299
+ }] = object_index.to_s
300
+ object_refs
301
+ end
302
+
303
+
304
+ def mail
305
+ Mail.new(eml.raw_source)
306
+ end
307
+
308
+ def as_stix
309
+
310
+ as_json(only: []).tap do |hash|
311
+ # hash["x_panacea_id"] = "<#{id}>".force_encoding("utf-8")
312
+ hash["type"] = "email-message"
313
+
314
+ mail = Mail.new(raw_email_artifact.payload_bin)
315
+ hash["date"] = mail.date.utc.iso8601(3)
316
+
317
+ # todo fix this when jpl turns on stix
318
+ hash["is_multipart"] = false
319
+
320
+ # if mail.multipart?
321
+ # stix_parts = mail.parts.collect do |part|
322
+ # {
323
+ # "content_type" => part.content_type.to_s,
324
+ # "content_disposition" => part.content_transfer_encoding.to_s,
325
+ # "body" => Digest::SHA1.hexdigest(part.to_s)
326
+ # }
327
+ # end.to_a
328
+ # hash["body_multipart"] = stix_parts
329
+ # else
330
+ # hash["body"] = eml.readable
331
+ # end
332
+
333
+ hash
334
+ end
335
+ end
336
+
337
+
338
+ end
339
+ end