├── .coveragerc ├── .deepsource.toml ├── .dockerignore ├── .flake8 ├── .github ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── issue_template.md │ ├── new_analyzer.md │ ├── new_connector.md │ ├── new_ingestor.md │ ├── new_playbook.md │ └── new_visualizer.md ├── SECURITY.md ├── dependabot.yml ├── legal_notice.md ├── pull_request_template.md ├── release_template.md └── workflows │ ├── codeql-analysis.yml │ ├── dependency_review.yml │ ├── pull_request_automation.yml │ ├── scorecard.yml │ └── stale.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .watchmanconfig ├── LICENSE ├── README.md ├── api_app ├── __init__.py ├── admin.py ├── analyzables_manager │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_migrate_data.py │ │ ├── 0003_analyzable_analyzables_classif_adf7ca_idx_and_more.py │ │ ├── 0004_analyzable_name_field_index.py │ │ └── __init__.py │ ├── models.py │ ├── queryset.py │ ├── serializers.py │ ├── signals.py │ ├── urls.py │ └── views.py ├── analyzers_manager │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── classes.py │ ├── constants.py │ ├── exceptions.py │ ├── file_analyzers │ │ ├── __init__.py │ │ ├── androguard.py │ │ ├── apkid.py │ │ ├── artifacts.py │ │ ├── blint_scan.py │ │ ├── boxjs_scan.py │ │ ├── capa_info.py │ │ ├── cape_sandbox.py │ │ ├── clamav.py │ │ ├── cuckoo_scan.py │ │ ├── debloat.py │ │ ├── detectiteasy.py │ │ ├── doc_info.py │ │ ├── docguard.py │ │ ├── droidlysis.py │ │ ├── elf_info.py │ │ ├── file_info.py │ │ ├── filescan.py │ │ ├── floss.py │ │ ├── goresym.py │ │ ├── hfinger.py │ │ ├── intezer_scan.py │ │ ├── iocextract.py │ │ ├── iocfinder.py │ │ ├── lnk_info.py │ │ ├── malpedia_scan.py │ │ ├── malprob.py │ │ ├── mobsf.py │ │ ├── mobsf_service.py │ │ ├── mwdb_scan.py │ │ ├── onenote.py │ │ ├── pdf_info.py │ │ ├── pe_info.py │ │ ├── peframe.py │ │ ├── perm_hash.py │ │ ├── phishing │ │ │ ├── __init__.py │ │ │ └── phishing_form_compiler.py │ │ ├── polyswarm.py │ │ ├── qiling.py │ │ ├── quark_engine.py │ │ ├── rtf_info.py │ │ ├── signature_info.py │ │ ├── speakeasy_emulation.py │ │ ├── strings_info.py │ │ ├── sublime.py │ │ ├── suricata.py │ │ ├── thug_file.py │ │ ├── triage_scan.py │ │ ├── unpac_me.py │ │ ├── virushee.py │ │ ├── xlm_macro_deobfuscator.py │ │ ├── yara_scan.py │ │ ├── yaraify_file_scan.py │ │ └── zippy_scan.py │ ├── filters.py │ ├── migrations │ │ ├── 0001_initial_squashed.py │ │ ├── 0002_0000_analyzer_config_apkid.py │ │ ├── 0002_0001_analyzer_config_abuseipdb.py │ │ ├── 0002_0002_analyzer_config_anomali_threatstream.py │ │ ├── 0002_0003_analyzer_config_auth0.py │ │ ├── 0002_0004_analyzer_config_binaryedge.py │ │ ├── 0002_0005_analyzer_config_bitcoinabuse.py │ │ ├── 0002_0006_analyzer_config_boxjs.py │ │ ├── 0002_0007_analyzer_config_circlpassivedns.py │ │ ├── 0002_0008_analyzer_config_circlpassivessl.py │ │ ├── 0002_0009_analyzer_config_crxcavator.py │ │ ├── 0002_0010_analyzer_config_capa_info.py │ │ ├── 0002_0011_analyzer_config_capa_info_shellcode.py │ │ ├── 0002_0012_analyzer_config_capesandbox.py │ │ ├── 0002_0013_analyzer_config_censys_search.py │ │ ├── 0002_0014_analyzer_config_checkdmarc.py │ │ ├── 0002_0015_analyzer_config_checkphish.py │ │ ├── 0002_0016_analyzer_config_clamav.py │ │ ├── 0002_0017_analyzer_config_classic_dns.py │ │ ├── 0002_0018_analyzer_config_cloudflare_dns.py │ │ ├── 0002_0019_analyzer_config_cloudflare_malicious_detector.py │ │ ├── 0002_0020_analyzer_config_crowdsec.py │ │ ├── 0002_0021_analyzer_config_cuckoo_scan.py │ │ ├── 0002_0022_analyzer_config_cyberchef.py │ │ ├── 0002_0023_analyzer_config_cymru_hash_registry_get_file.py │ │ ├── 0002_0024_analyzer_config_cymru_hash_registry_get_observable.py │ │ ├── 0002_0025_analyzer_config_dns0_eu.py │ │ ├── 0002_0026_analyzer_config_dns0_eu_malicious_detector.py │ │ ├── 0002_0027_analyzer_config_dns0_names.py │ │ ├── 0002_0028_analyzer_config_dns0_rrsets_data.py │ │ ├── 0002_0029_analyzer_config_dns0_rrsets_name.py │ │ ├── 0002_0030_analyzer_config_dnsdb.py │ │ ├── 0002_0031_analyzer_config_dnstwist.py │ │ ├── 0002_0032_analyzer_config_dehashed_search.py │ │ ├── 0002_0033_analyzer_config_docguard_get.py │ │ ├── 0002_0034_analyzer_config_docguard_upload_file.py │ │ ├── 0002_0035_analyzer_config_doc_info.py │ │ ├── 0002_0036_analyzer_config_dragonfly_emulation.py │ │ ├── 0002_0037_analyzer_config_elf_info.py │ │ ├── 0002_0038_analyzer_config_emailrep.py │ │ ├── 0002_0039_analyzer_config_filescan_search.py │ │ ├── 0002_0040_analyzer_config_filescan_upload_file.py │ │ ├── 0002_0041_analyzer_config_file_info.py │ │ ├── 0002_0042_analyzer_config_firehol_iplist.py │ │ ├── 0002_0043_analyzer_config_floss.py │ │ ├── 0002_0044_analyzer_config_googlesafebrowsing.py │ │ ├── 0002_0045_analyzer_config_googlewebrisk.py │ │ ├── 0002_0046_analyzer_config_google_dns.py │ │ ├── 0002_0047_analyzer_config_greedybear.py │ │ ├── 0002_0048_analyzer_config_greynoise.py │ │ ├── 0002_0049_analyzer_config_greynoisecommunity.py │ │ ├── 0002_0050_analyzer_config_hashlookupserver_get_file.py │ │ ├── 0002_0051_analyzer_config_hashlookupserver_get_observable.py │ │ ├── 0002_0052_analyzer_config_haveibeenpwned.py │ │ ├── 0002_0053_analyzer_config_honeydb.py │ │ ├── 0002_0054_analyzer_config_hunter_how.py │ │ ├── 0002_0055_analyzer_config_hunter_io.py │ │ ├── 0002_0056_analyzer_config_hybridanalysis_get_file.py │ │ ├── 0002_0057_analyzer_config_hybridanalysis_get_observable.py │ │ ├── 0002_0058_analyzer_config_ipapi.py │ │ ├── 0002_0059_analyzer_config_ipinfo.py │ │ ├── 0002_0060_analyzer_config_inquest_dfi.py │ │ ├── 0002_0061_analyzer_config_inquest_iocdb.py │ │ ├── 0002_0062_analyzer_config_inquest_repdb.py │ │ ├── 0002_0063_analyzer_config_intelx_intelligent_search.py │ │ ├── 0002_0064_analyzer_config_intelx_phonebook.py │ │ ├── 0002_0065_analyzer_config_intezer_get.py │ │ ├── 0002_0066_analyzer_config_intezer_scan.py │ │ ├── 0002_0067_analyzer_config_koodous.py │ │ ├── 0002_0068_analyzer_config_misp.py │ │ ├── 0002_0069_analyzer_config_mispfirst.py │ │ ├── 0002_0070_analyzer_config_mispfirst_check_hash.py │ │ ├── 0002_0071_analyzer_config_misp_check_hash.py │ │ ├── 0002_0072_analyzer_config_mwdb_get.py │ │ ├── 0002_0073_analyzer_config_mwdb_scan.py │ │ ├── 0002_0074_analyzer_config_malpedia_scan.py │ │ ├── 0002_0075_analyzer_config_malwarebazaar_get_file.py │ │ ├── 0002_0076_analyzer_config_malwarebazaar_get_observable.py │ │ ├── 0002_0077_analyzer_config_malwarebazaar_google_observable.py │ │ ├── 0002_0078_analyzer_config_maxmindgeoip.py │ │ ├── 0002_0079_analyzer_config_mnemonic_passivedns.py │ │ ├── 0002_0080_analyzer_config_netlas.py │ │ ├── 0002_0081_analyzer_config_onyphe.py │ │ ├── 0002_0082_analyzer_config_otxquery.py │ │ ├── 0002_0083_analyzer_config_otx_check_hash.py │ │ ├── 0002_0084_analyzer_config_onenote_info.py │ │ ├── 0002_0085_analyzer_config_onionscan.py │ │ ├── 0002_0086_analyzer_config_opencti.py │ │ ├── 0002_0087_analyzer_config_pdf_info.py │ │ ├── 0002_0088_analyzer_config_pe_info.py │ │ ├── 0002_0089_analyzer_config_peframe_scan.py │ │ ├── 0002_0090_analyzer_config_phishingarmy.py │ │ ├── 0002_0091_analyzer_config_phishstats.py │ │ ├── 0002_0092_analyzer_config_phishtank.py │ │ ├── 0002_0093_analyzer_config_pulsedive.py │ │ ├── 0002_0094_analyzer_config_qiling_linux.py │ │ ├── 0002_0095_analyzer_config_qiling_linux_shellcode.py │ │ ├── 0002_0096_analyzer_config_qiling_windows.py │ │ ├── 0002_0097_analyzer_config_qiling_windows_shellcode.py │ │ ├── 0002_0098_analyzer_config_quad9_dns.py │ │ ├── 0002_0099_analyzer_config_quad9_malicious_detector.py │ │ ├── 0002_0100_analyzer_config_quark_engine.py │ │ ├── 0002_0101_analyzer_config_robtex.py │ │ ├── 0002_0102_analyzer_config_rtf_info.py │ │ ├── 0002_0103_analyzer_config_ssapinet.py │ │ ├── 0002_0104_analyzer_config_securitytrails.py │ │ ├── 0002_0105_analyzer_config_shodan_honeyscore.py │ │ ├── 0002_0106_analyzer_config_shodan_search.py │ │ ├── 0002_0107_analyzer_config_signature_info.py │ │ ├── 0002_0108_analyzer_config_speakeasy.py │ │ ├── 0002_0109_analyzer_config_speakeasy_shellcode.py │ │ ├── 0002_0110_analyzer_config_spyse.py │ │ ├── 0002_0111_analyzer_config_stalkphish.py │ │ ├── 0002_0112_analyzer_config_stratosphere_blacklist.py │ │ ├── 0002_0113_analyzer_config_strings_info.py │ │ ├── 0002_0114_analyzer_config_sublimesecurity.py │ │ ├── 0002_0115_analyzer_config_suricata.py │ │ ├── 0002_0116_analyzer_config_talosreputation.py │ │ ├── 0002_0117_analyzer_config_threatfox.py │ │ ├── 0002_0118_analyzer_config_threatminer.py │ │ ├── 0002_0119_analyzer_config_thug_html_info.py │ │ ├── 0002_0120_analyzer_config_thug_url_info.py │ │ ├── 0002_0121_analyzer_config_torproject.py │ │ ├── 0002_0122_analyzer_config_tranco.py │ │ ├── 0002_0123_analyzer_config_triage_scan.py │ │ ├── 0002_0124_analyzer_config_triage_scan_url.py │ │ ├── 0002_0125_analyzer_config_triage_search.py │ │ ├── 0002_0126_analyzer_config_urlhaus.py │ │ ├── 0002_0127_analyzer_config_unpacme.py │ │ ├── 0002_0128_analyzer_config_urlscan_search.py │ │ ├── 0002_0129_analyzer_config_urlscan_submit_result.py │ │ ├── 0002_0130_analyzer_config_virustotal_v3_get_file.py │ │ ├── 0002_0131_analyzer_config_virustotal_v3_get_observable.py │ │ ├── 0002_0132_analyzer_config_virustotal_v3_intelligence_search.py │ │ ├── 0002_0133_analyzer_config_virushee_checkhash.py │ │ ├── 0002_0134_analyzer_config_virushee_scan.py │ │ ├── 0002_0135_analyzer_config_whois_ripedb_search.py │ │ ├── 0002_0136_analyzer_config_whoisxmlapi.py │ │ ├── 0002_0137_analyzer_config_wigle.py │ │ ├── 0002_0138_analyzer_config_xforceexchange.py │ │ ├── 0002_0139_analyzer_config_xlm_macro_deobfuscator.py │ │ ├── 0002_0140_analyzer_config_yaraify_file_scan.py │ │ ├── 0002_0141_analyzer_config_yaraify_file_search.py │ │ ├── 0002_0142_analyzer_config_yaraify_generics.py │ │ ├── 0002_0143_analyzer_config_yaraify_search.py │ │ ├── 0002_0144_analyzer_config_yeti.py │ │ ├── 0002_0145_analyzer_config_yara.py │ │ ├── 0002_0146_analyzer_config_zoomeye.py │ │ ├── 0058_1_change_primary_key.py │ │ ├── 0058_2_change_primary_key.py │ │ ├── 0058_3_change_primary_key.py │ │ ├── 0058_4_change_primary_key.py │ │ ├── 0059_alter_analyzer_config_dns0_rrsets_data.py │ │ ├── 0060_analyzer_config_ip2location.py │ │ ├── 0061_analyzer_config_ipqs_fraud_and_risk_scoring.py │ │ ├── 0062_analyzer_config_mmdb_server.py │ │ ├── 0063_alter_analyzerconfig_not_supported_filetypes_and_more.py │ │ ├── 0064_analyzer_config_zippy_scan.py │ │ ├── 0065_analyzer_config_validin.py │ │ ├── 0066_analyzer_config_phoneinfoga.py │ │ ├── 0067_update_misp.py │ │ ├── 0068_analyzer_config_feodo_tracker.py │ │ ├── 0069_analyzer_config_bgp_ranking.py │ │ ├── 0070_urlhaus_threatfox_disable_param.py │ │ ├── 0071_analyzer_config_tor_nodes_danmeuk.py │ │ ├── 0072_analyzer_config_tweetfeed.py │ │ ├── 0073_remove_dragonfly_analyzer.py │ │ ├── 0074_adjust_maximum_tlp.py │ │ ├── 0075_adjust_greynoise.py │ │ ├── 0076_analyzer_config_greynoise_labs.py │ │ ├── 0077_analyzer_config_abusix.py │ │ ├── 0078_analyzer_config_hfinger.py │ │ ├── 0079_remove_dns0_rrsets_analyzer.py │ │ ├── 0080_remove_dns0_names_analyzer.py │ │ ├── 0081_adjust_abusix.py │ │ ├── 0082_analyzer_config_ip2whois.py │ │ ├── 0083_adjust_docinfo.py │ │ ├── 0084_alter_analyzerconfig_not_supported_filetypes_and_more.py │ │ ├── 0085_analyzer_config_permhash.py │ │ ├── 0086_analyzer_config_blint.py │ │ ├── 0087_alter_mmdbserver_param.py │ │ ├── 0088_phoneinfoga_parameters.py │ │ ├── 0089_analyzer_config_hudsonrock.py │ │ ├── 0090_analyzer_config_cycat.py │ │ ├── 0091_analyzer_config_vulners.py │ │ ├── 0092_alter_validin_desc.py │ │ ├── 0093_analyzer_config_ailtyposquatting.py │ │ ├── 0094_analyzer_config_detectiteasy.py │ │ ├── 0095_analyzer_config_malprobsearch.py │ │ ├── 0096_analyzer_config_malprobscan.py │ │ ├── 0097_analyzer_config_orklsearch.py │ │ ├── 0098_analyzer_config_crt_sh.py │ │ ├── 0099_analyzer_config_spamhaus_wqs.py │ │ ├── 0100_analyzer_config_downloadfilefromuri.py │ │ ├── 0101_analyzer_config_adguard.py │ │ ├── 0102_analyzer_config_ja4_db.py │ │ ├── 0103_add_x_executable.py │ │ ├── 0104_analyzer_config_goresym.py │ │ ├── 0105_alter_analyzerconfig_not_supported_filetypes_and_more.py │ │ ├── 0106_analyzer_config_leakix.py │ │ ├── 0107_analyzer_config_apivoid.py │ │ ├── 0108_analyzer_config_iocextract.py │ │ ├── 0109_analyzer_config_iocfinder.py │ │ ├── 0110_analyzer_config_spamhaus_drop.py │ │ ├── 0111_analyzer_config_criminalip.py │ │ ├── 0112_analyzer_config_criminalip_scan.py │ │ ├── 0113_analyzer_config_polyswarm.py │ │ ├── 0114_analyzer_config_polyswarmobs.py │ │ ├── 0115_analyzer_config_knock.py │ │ ├── 0116_add_new_files.py │ │ ├── 0117_analyzer_config_mobsf.py │ │ ├── 0118_analyzer_config_droidlysis.py │ │ ├── 0119_analyzer_config_apk_artifacts.py │ │ ├── 0120_alter_analyzerconfig_not_supported_filetypes_and_more.py │ │ ├── 0121_analyzer_config_lnk_info.py │ │ ├── 0122_alter_soft_time_limit.py │ │ ├── 0123_basic_observable_analyzer.py │ │ ├── 0124_analyzer_config_androguard.py │ │ ├── 0125_update_yara_repo.py │ │ ├── 0126_analyzer_config_nerd_analyzer.py │ │ ├── 0127_analyzer_config_dshield.py │ │ ├── 0128_analyzer_config_phishing_form_compiler.py │ │ ├── 0129_analyzer_config_phishing_extractor.py │ │ ├── 0130_analyzer_config_nvd_cve.py │ │ ├── 0131_analyzer_config_vt_sample_download.py │ │ ├── 0132_analyzer_config_urldna_new_scan.py │ │ ├── 0133_analyzer_config_urldna_search.py │ │ ├── 0134_analyzerconfig_mapping_data_model.py │ │ ├── 0135_data_mapping.py │ │ ├── 0136_alter_analyzerconfig_mapping_data_model_and_more.py │ │ ├── 0137_analyzerreport_data_model_content_type_and_more.py │ │ ├── 0138_alter_analyzerreport_data_model_content_type.py │ │ ├── 0139_alter_analyzerconfig_mapping_data_model.py │ │ ├── 0140_analyzerreport_analyzers_m_data_mo_a1952b_idx.py │ │ ├── 0141_analyzer_config_mobsf_service.py │ │ ├── 0142_alter_analyzerreport_data_model_content_type_and_more.py │ │ ├── 0143_alter_analyzer_config_phishing_extractor_and_form_compiler.py │ │ ├── 0144_analyzer_config_ultradns_dns.py │ │ ├── 0145_analyzer_config_ultradns_malicious_detector.py │ │ ├── 0146_analyzer_config_wad.py │ │ ├── 0147_alter_analyzer_config_feodo_yaraify_urlhaus_yaraify_scan.py │ │ ├── 0148_analyzer_config_nuclei.py │ │ ├── 0149_alter_die_analyzer.py │ │ ├── 0150_alter_dns_malicious_detectors.py │ │ ├── 0151_analyzer_config_ipquery.py │ │ ├── 0152_analyzer_config_mullvad_dns.py │ │ ├── 0153_alter_spamhaus_drop_supported_observable.py │ │ ├── 0154_analyzer_config_bbot.py │ │ ├── 0155_analyzer_config_debloat.py │ │ ├── 0156_alter_analyzer_config_required_api_key_abuse_ch.py │ │ └── __init__.py │ ├── models.py │ ├── observable_analyzers │ │ ├── __init__.py │ │ ├── abuseipdb.py │ │ ├── abusix.py │ │ ├── ailtyposquatting.py │ │ ├── apivoid.py │ │ ├── auth0.py │ │ ├── basic_observable_analyzer.py │ │ ├── bbot.py │ │ ├── bgp_ranking.py │ │ ├── binaryedge.py │ │ ├── bitcoinabuse.py │ │ ├── censys.py │ │ ├── checkdmarc.py │ │ ├── checkphish.py │ │ ├── circl_pdns.py │ │ ├── circl_pssl.py │ │ ├── criminalip │ │ │ ├── __init__.py │ │ │ ├── criminalip.py │ │ │ ├── criminalip_base.py │ │ │ └── criminalip_scan.py │ │ ├── crowdsec.py │ │ ├── crt_sh.py │ │ ├── crxcavator.py │ │ ├── cyberchef.py │ │ ├── cycat.py │ │ ├── cymru.py │ │ ├── dehashed.py │ │ ├── dns │ │ │ ├── __init__.py │ │ │ ├── dns_malicious_detectors │ │ │ │ ├── __init__.py │ │ │ │ ├── adguard.py │ │ │ │ ├── cloudflare_malicious_detector.py │ │ │ │ ├── dns0_eu_malicious_detector.py │ │ │ │ ├── google_webrisk.py │ │ │ │ ├── googlesf.py │ │ │ │ ├── mullvad_dns.py │ │ │ │ ├── quad9_malicious_detector.py │ │ │ │ ├── spamhaus_wqs.py │ │ │ │ └── ultradns_malicious_detector.py │ │ │ ├── dns_resolvers │ │ │ │ ├── __init__.py │ │ │ │ ├── classic_dns_resolver.py │ │ │ │ ├── cloudflare_dns_resolver.py │ │ │ │ ├── dns0_eu_resolver.py │ │ │ │ ├── google_dns_resolver.py │ │ │ │ ├── quad9_dns_resolver.py │ │ │ │ └── ultradns_dns_resolver.py │ │ │ └── dns_responses.py │ │ ├── dnsdb.py │ │ ├── dnstwist.py │ │ ├── docguard_get.py │ │ ├── download_file_from_uri.py │ │ ├── dshield.py │ │ ├── emailrep.py │ │ ├── feodo_tracker.py │ │ ├── filescan_search.py │ │ ├── firehol_iplist.py │ │ ├── greedybear.py │ │ ├── greynoise_labs.py │ │ ├── greynoiseintel.py │ │ ├── ha_get.py │ │ ├── hashlookup.py │ │ ├── haveibeenpwned.py │ │ ├── honeydb.py │ │ ├── hudsonrock.py │ │ ├── hunter_how.py │ │ ├── hunter_io.py │ │ ├── inquest.py │ │ ├── intelx.py │ │ ├── intezer_get.py │ │ ├── ip2location.py │ │ ├── ip2whois.py │ │ ├── ipapi.py │ │ ├── ipinfo.py │ │ ├── ipqs.py │ │ ├── ipquery.py │ │ ├── ja4_db.py │ │ ├── knockanalyzer.py │ │ ├── koodous.py │ │ ├── leakix.py │ │ ├── malprob.py │ │ ├── maxmind.py │ │ ├── mb_get.py │ │ ├── mb_google.py │ │ ├── misp.py │ │ ├── mmdb_server.py │ │ ├── mnemonic_pdns.py │ │ ├── mwdb_get.py │ │ ├── nerd.py │ │ ├── netlas.py │ │ ├── nuclei.py │ │ ├── nvd_cve.py │ │ ├── onionscan.py │ │ ├── onyphe.py │ │ ├── opencti.py │ │ ├── orkl_search.py │ │ ├── otx.py │ │ ├── phishing │ │ │ ├── __init__.py │ │ │ └── phishing_extractor.py │ │ ├── phishing_army.py │ │ ├── phishstats.py │ │ ├── phishtank.py │ │ ├── phoneinfoga_scan.py │ │ ├── polyswarm_obs.py │ │ ├── pulsedive.py │ │ ├── robtex.py │ │ ├── securitytrails.py │ │ ├── shodan.py │ │ ├── spamhaus_drop.py │ │ ├── spyse.py │ │ ├── ss_api_net.py │ │ ├── stalkphish.py │ │ ├── stratosphere.py │ │ ├── talos.py │ │ ├── threatfox.py │ │ ├── threatminer.py │ │ ├── threatstream.py │ │ ├── thug_url.py │ │ ├── tor.py │ │ ├── tor_nodes_danmeuk.py │ │ ├── tranco.py │ │ ├── triage │ │ │ ├── __init__.py │ │ │ ├── triage_base.py │ │ │ └── triage_search.py │ │ ├── tweetfeeds.py │ │ ├── urldna.py │ │ ├── urlhaus.py │ │ ├── urlscan.py │ │ ├── validin.py │ │ ├── virushee.py │ │ ├── vt │ │ │ ├── __init__.py │ │ │ ├── vt3_get.py │ │ │ ├── vt3_intelligence_search.py │ │ │ └── vt3_sample_download.py │ │ ├── vulners.py │ │ ├── wad.py │ │ ├── whoisripe.py │ │ ├── whoisxmlapi.py │ │ ├── wigle.py │ │ ├── xforce.py │ │ ├── yaraify.py │ │ ├── yeti.py │ │ └── zoomeye.py │ ├── queryset.py │ ├── repo_downloader.sh │ ├── serializers.py │ ├── signals.py │ ├── ssh_gitpython.sh │ ├── urls.py │ └── views.py ├── apps.py ├── choices.py ├── classes.py ├── connectors_manager │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── classes.py │ ├── connectors │ │ ├── __init__.py │ │ ├── abuse_submitter.py │ │ ├── email_sender.py │ │ ├── misp.py │ │ ├── opencti.py │ │ ├── slack.py │ │ └── yeti.py │ ├── exceptions.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial_squashed.py │ │ ├── 0002_0000_connector_config_misp.py │ │ ├── 0002_0001_connector_config_opencti.py │ │ ├── 0002_0002_connector_config_slack.py │ │ ├── 0002_0003_connector_config_yeti.py │ │ ├── 0029_1_change_primary_key.py │ │ ├── 0029_2_change_primary_key.py │ │ ├── 0029_3_change_primary_key.py │ │ ├── 0029_4_change_primary_key.py │ │ ├── 0030_connector_config_emailsender.py │ │ ├── 0031_connector_config_abusesubmitter.py │ │ ├── 0032_more_params_emails.py │ │ └── __init__.py │ ├── models.py │ ├── queryset.py │ ├── serializers.py │ ├── signals.py │ ├── urls.py │ └── views.py ├── data_model_manager │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── enums.py │ ├── fields.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_domaindatamodel_resolutions_and_more.py │ │ ├── 0003_remove_ipdatamodel_ietf_report_and_more.py │ │ ├── 0004_alter_domaindatamodel_evaluation_and_more.py │ │ ├── 0005_alter_domaindatamodel_external_references_and_more.py │ │ ├── 0006_alter_ipdatamodel_asn_rank.py │ │ ├── 0007_alter_signature_url.py │ │ ├── 0008_domaindatamodel_reliability_and_more.py │ │ ├── 0009_alter_domaindatamodel_evaluation_and_more.py │ │ ├── 0010_domaindatamodel_killchain_phase_and_more.py │ │ └── __init__.py │ ├── models.py │ ├── queryset.py │ ├── serializers.py │ ├── signals.py │ ├── urls.py │ └── views.py ├── decorators.py ├── defaults.py ├── engines_manager │ ├── __init__.py │ ├── apps.py │ ├── classes.py │ ├── engines │ │ ├── __init__.py │ │ ├── evaluation.py │ │ └── malware_family.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_alter_engineconfig_modules.py │ │ ├── 0003_engine.py │ │ └── __init__.py │ ├── models.py │ ├── queryset.py │ ├── signals.py │ ├── tasks.py │ ├── urls.py │ ├── validators.py │ └── views.py ├── enums.py ├── exceptions.py ├── fields.py ├── filters.py ├── fixtures │ ├── 0001_user.json │ └── __init__.py ├── forms.py ├── helpers.py ├── ingestors_manager │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── classes.py │ ├── exceptions.py │ ├── ingestors │ │ ├── __init__.py │ │ ├── greedybear.py │ │ ├── malshare.py │ │ ├── malware_bazaar.py │ │ ├── threatfox.py │ │ └── virus_total.py │ ├── migrations │ │ ├── 0001_initial_squashed.py │ │ ├── 0002_0000_ingestor_config_threatfox.py │ │ ├── 0016_1_change_primary_key.py │ │ ├── 0016_2_change_primary_key.py │ │ ├── 0016_3_change_primary_key.py │ │ ├── 0016_4_change_primary_key.py │ │ ├── 0017_2_change_primary_key.py │ │ ├── 0017_4_change_primary_key.py │ │ ├── 0018_ingestorconfig_delay.py │ │ ├── 0019_ingestor_config_malwarebazaar.py │ │ ├── 0020_ingestor_config_threatfox.py │ │ ├── 0021_ingestor_fix_malwarebazaar_threatfox.py │ │ ├── 0022_ingestor_fix_duplicated_users.py │ │ ├── 0023_remove_ingestorconfig_playbook_to_execute_and_more.py │ │ ├── 0024_remove_ingestorconfig_playbook_to_execute.py │ │ ├── 0025_ingestor_config_virustotal_example_query.py │ │ ├── 0026_alter_ingestor_config_malware_bazaar_threatfox.py │ │ ├── 0027_added_limit_parameter_malware_bazaar_threatfox.py │ │ ├── 0028_ingestor_config_greedybear.py │ │ ├── 0029_ingestor_config_malshare.py │ │ ├── 0030_alter_ingestor_config_required_api_key_abuse_ch.py │ │ └── __init__.py │ ├── models.py │ ├── queryset.py │ ├── serializers.py │ ├── signals.py │ ├── urls.py │ └── views.py ├── interfaces.py ├── investigations_manager │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── choices.py │ ├── filters.py │ ├── migrations │ │ ├── 0001_initial.py │ │ └── __init__.py │ ├── models.py │ ├── queryset.py │ ├── serializers.py │ ├── signals.py │ ├── urls.py │ └── views.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ ├── celery_reload.py │ │ ├── dump_all_plugins.py │ │ ├── dumpplugin.py │ │ ├── elastic_templates.py │ │ ├── migrate.py │ │ └── update_analyzer.py ├── migrations │ ├── 0001_1_initial_squashed.py │ ├── 0001_2_initial_squashed.py │ ├── 0055_organizationpluginconfiguration_and_more.py │ ├── 0056_alter_organizationpluginconfiguration_content_type.py │ ├── 0057_2_change_primary_key.py │ ├── 0057_4_change_primary_key.py │ ├── 0058_2_change_primary_key.py │ ├── 0058_4_change_primary_key.py │ ├── 0059_alter_organizationpluginconfiguration_unique_together.py │ ├── 0060_job_depth_job_numchild_job_path.py │ ├── 0061_job_depth_analysis.py │ ├── 0062_alter_parameter_python_module.py │ ├── 0063_singleton_and_elastic_report.py │ ├── 0064_vt_sample_download.py │ ├── 0065_job_mpnodesearch.py │ ├── 0066_remove_lastelasticreportupdate_singleton_and_more.py │ ├── 0067_add_analyzable.py │ ├── 0068_remove_job_api_app_job_md5_4d2c5e_idx_and_more.py │ ├── 0069_remove_comment_job_comment_analyzable.py │ ├── 0070_remove_comment_job_comment_analyzable.py │ ├── 0071_delete_last_elastic_report.py │ └── __init__.py ├── mixins.py ├── models.py ├── permissions.py ├── pivots_manager │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── classes.py │ ├── exceptions.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_1_initial_squashed.py │ │ ├── 0001_2_initial_squashed.py │ │ ├── 0002_000_self_analyzable.py │ │ ├── 0002_001_compare.py │ │ ├── 0023_2_change_primary_key.py │ │ ├── 0023_4_change_primary_key.py │ │ ├── 0024_2_change_primary_key.py │ │ ├── 0024_4_change_primary_key.py │ │ ├── 0025_alter_pivotmap_ending_job.py │ │ ├── 0026_pivot_config_abuseiptosubmission.py │ │ ├── 0027_pivot_config_takedownrequesttoabuseip.py │ │ ├── 0028_pivot_config_resubmitdownloadedfile.py │ │ ├── 0029_pivot_config_downloadfilefromuri.py │ │ ├── 0030_pivot_config_delay.py │ │ ├── 0031_remove_pivotconfig_playbook_to_execute_and_more.py │ │ ├── 0032_remove_pivotconfig_playbook_to_execute.py │ │ ├── 0033_pivot_config_extractedonenotefiles.py │ │ ├── 0034_changed_resubmitdownloadedfile_playbook_to_execute.py │ │ ├── 0035_pivot_config_phishingextractortoanalysis.py │ │ ├── 0036_alter_extractedonenotefiles_resubmitdownloadedfile_loadfilesameplaybook.py │ │ └── __init__.py │ ├── models.py │ ├── permissions.py │ ├── pivots │ │ ├── __init__.py │ │ ├── any_compare.py │ │ ├── compare.py │ │ ├── load_file.py │ │ ├── load_file_same_playbook.py │ │ └── self_analyzable.py │ ├── queryset.py │ ├── serializers.py │ ├── signals.py │ ├── urls.py │ ├── validators.py │ └── views.py ├── playbooks_manager │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── fields.py │ ├── migrations │ │ ├── 0001_initial_squashed.py │ │ ├── 0002_0000_playbook_config_dns.py │ │ ├── 0002_0001_playbook_config_free_to_use_analyzers.py │ │ ├── 0002_0002_playbook_config_popular_ip_reputation_services.py │ │ ├── 0002_0003_playbook_config_popular_url_reputation_services.py │ │ ├── 0002_0004_playbook_config_sample_static_analysis.py │ │ ├── 0023_2_change_primary_key.py │ │ ├── 0023_4_change_primary_key.py │ │ ├── 0024_1_change_primary_key.py │ │ ├── 0024_3_change_primary_key.py │ │ ├── 0024_4_change_primary_key.py │ │ ├── 0025_add_mmdb_analyzer_free_to_use.py │ │ ├── 0026_add_zippy_scan_to_free_to_use.py │ │ ├── 0027_add_feodo_tracker_to_free_to_use.py │ │ ├── 0028_add_bgp_ranking_to_free_to_use.py │ │ ├── 0029_add_tor_nodes_danmeuk_analyzer_free_to_use.py │ │ ├── 0030_add_tweetfeeds_to_free_analyzers.py │ │ ├── 0031_add_hfinger_analyzer_free_to_use.py │ │ ├── 0032_delete_dns0_playbook_free_to_use_analyzers.py │ │ ├── 0033_playbook_config_send_abuse_email.py │ │ ├── 0034_playbook_config_abuse_ip.py │ │ ├── 0035_playbook_config_takedown_request.py │ │ ├── 0036_static_analyzer_remove_visualizer.py │ │ ├── 0037_playbookconfig_starting.py │ │ ├── 0038_playbooks_not_starting.py │ │ ├── 0039_alter_playbookconfig_scan_check_time_and_more.py │ │ ├── 0040_alter_domain_reputation_playbook.py │ │ ├── 0041_add_permhash_to_free_analyzers_and_static_analyzers.py │ │ ├── 0042_add_blint_to_free_analyzers_and_static_analyzers.py │ │ ├── 0043_playbook_config_pcap_analysis.py │ │ ├── 0044_add_cycat_to_free_to_use.py │ │ ├── 0045_playbook_config_passive_dns.py │ │ ├── 0046_add_orkl_to_free_to_use.py │ │ ├── 0047_add_crt_sh_to_free_to_use.py │ │ ├── 0048_playbook_config_download_file.py │ │ ├── 0049_add_adguard_to_free_to_use_and_dns.py │ │ ├── 0050_add_goresym_to_sample_static_abalysis.py │ │ ├── 0051_add_lnk_info_analyzer_free_to_use.py │ │ ├── 0052_playbook_config_uris.py │ │ ├── 0053_add_androguard_to_free_to_use_analyzers.py │ │ ├── 0054_playbook_config_phishinganalysis.py │ │ ├── 0055_playbook_config_phishingextractor.py │ │ ├── 0056_download_sample_vt.py │ │ ├── 0057_alter_phishing_extractor_add_domain.py │ │ ├── 0058_add_ultradns_to_free_to_use_and_dns.py │ │ ├── 0059_add_ipquery_analyzer_free_to_use.py │ │ └── __init__.py │ ├── models.py │ ├── queryset.py │ ├── serializers.py │ ├── signals.py │ ├── urls.py │ └── views.py ├── queryset.py ├── serializers │ ├── __init__.py │ ├── celery.py │ ├── elastic.py │ ├── job.py │ ├── plugin.py │ ├── report.py │ └── test.py ├── signals.py ├── tabulars.py ├── urls.py ├── user_events_manager │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── choices.py │ ├── filters.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_alter_userdomainwildcardevent_query.py │ │ └── __init__.py │ ├── models.py │ ├── queryset.py │ ├── serializers.py │ ├── signals.py │ ├── tasks.py │ ├── urls.py │ ├── validators.py │ └── views.py ├── validators.py ├── views.py ├── visualizers_manager │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── choices.py │ ├── classes.py │ ├── decorators.py │ ├── enums.py │ ├── exceptions.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial_squashed.py │ │ ├── 0002_0000_visualizer_config_dns.py │ │ ├── 0002_0001_visualizer_config_domain_reputation.py │ │ ├── 0002_0002_visualizer_config_ip_reputation.py │ │ ├── 0002_0003_visualizer_config_pivot.py │ │ ├── 0002_0004_visualizer_config_yara.py │ │ ├── 0036_1_change_primary_key.py │ │ ├── 0036_2_change_primary_key.py │ │ ├── 0036_3_change_primary_key.py │ │ ├── 0036_4_change_primary_key.py │ │ ├── 0037_2_change_primary_key.py │ │ ├── 0037_4_change_primary_key.py │ │ ├── 0038_visualizer_config_passive_dns.py │ │ ├── 0039_sample_download.py │ │ ├── 0040_visualizer_config_data_model.py │ │ └── __init__.py │ ├── models.py │ ├── queryset.py │ ├── serializers.py │ ├── signals.py │ ├── urls.py │ ├── validators.py │ ├── views.py │ └── visualizers │ │ ├── __init__.py │ │ ├── data_model.py │ │ ├── dns.py │ │ ├── domain_reputation_services.py │ │ ├── ip_reputation_services.py │ │ ├── passive_dns │ │ ├── analyzer_extractor.py │ │ ├── pdns_table.py │ │ └── visualizer.py │ │ ├── pivot.py │ │ ├── sample_download.py │ │ └── yara.py └── websocket.py ├── authentication ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_migrate_from_durin.py │ ├── 0003_userprofile_is_robot_userprofile_task_priority_and_more.py │ ├── 0004_alter_userprofile_company_name_and_more.py │ ├── 0005_create_profiles.py │ ├── 0006_alter_userprofile_company_name_and_more.py │ └── __init__.py ├── models.py ├── oauth.py ├── serializers.py ├── signals.py ├── templates │ └── authentication │ │ └── emails │ │ ├── account-activated.html │ │ ├── account-declined.html │ │ ├── base.html │ │ ├── duplicate-email.html │ │ ├── reset-password.html │ │ └── verify-email.html ├── urls.py └── views.py ├── configuration ├── Kibana-Saved-Conf.ndjson ├── cyberchef_recipes.json ├── elastic_search_mappings │ ├── intel_owl_bi.json │ └── plugin_report.json ├── intel_owl.ini ├── ldap_config.py ├── nginx │ ├── django_server.conf │ ├── errors.conf │ ├── flower_http.conf │ ├── flower_https.conf │ ├── http.conf │ ├── https.conf │ ├── locations.conf │ └── websocket.conf ├── rabbitmq.conf └── radius_config.py ├── create_elastic_certs ├── docker ├── .env ├── .env.start.test.template ├── Dockerfile ├── Dockerfile_nginx ├── bin │ ├── README.md │ └── osslsigncode ├── ci.override.yml ├── default.yml ├── elasticsearch.override.yml ├── entrypoints │ ├── celery_beat.sh │ ├── celery_default.sh │ ├── celery_ingestor.sh │ ├── celery_local.sh │ ├── celery_long.sh │ ├── daphne.sh │ ├── flower.sh │ └── uwsgi.sh ├── env_file_app_ci ├── env_file_app_template ├── env_file_elasticsearch_template ├── env_file_integrations_template ├── env_file_postgres_template ├── flower.override.yml ├── hooks │ └── build ├── https.override.yml ├── multi-queue.override.yml ├── nfs.override.yml ├── nginx.override.yml ├── postgres.override.yml ├── rabbitmq.override.yml ├── redis.override.yml ├── scripts │ ├── add_license.py │ ├── cron │ │ ├── application_restart │ │ └── update_repositories │ ├── initdb.sh │ ├── install_crontab.sh │ ├── install_logrotate.sh │ ├── logrotate │ │ ├── application │ │ ├── docker │ │ └── nginx │ ├── manage.sh │ ├── tail-logs.sh │ └── watchman_install.sh ├── sqs.override.yml ├── test.flower.override.yml ├── test.multi-queue.override.yml ├── test.override.yml ├── traefik.yml ├── traefik_local.yml └── traefik_prod.yml ├── elasticsearch_instances.yml ├── frontend ├── .eslintrc.json ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .stylelintrc ├── FixJSDOMEnvironment.js ├── README.md ├── babel.config.js ├── jest.config.js ├── package-lock.json ├── package.json ├── public │ ├── google-logo.svg │ ├── icons │ │ ├── 192x192.png │ │ ├── 512x512.png │ │ ├── apple-touch-icon.png │ │ ├── browserconfig.xml │ │ ├── cloudflare-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-notification.ico │ │ ├── favicon.ico │ │ ├── google-icon.png │ │ ├── honeynet.ico │ │ ├── hybrid-analysis-icon.png │ │ ├── mstile-150x150.png │ │ ├── quad9-icon.png │ │ ├── quokka-icon.png │ │ └── urlhaus-icon.png │ ├── index.html │ ├── logo-blue.png │ ├── logo-dark.png │ ├── logo-negative-reduced.png │ ├── logo-negative.png │ ├── logo-positive.png │ ├── logo-white.png │ ├── manifest.json │ ├── notification.mp3 │ └── robots.txt ├── src │ ├── App.jsx │ ├── components │ │ ├── GuideWrapper.jsx │ │ ├── History.jsx │ │ ├── Routes.jsx │ │ ├── auth │ │ │ ├── ChangePassword.jsx │ │ │ ├── EmailVerification.jsx │ │ │ ├── Login.jsx │ │ │ ├── Logout.jsx │ │ │ ├── Register.jsx │ │ │ ├── ResetPassword.jsx │ │ │ ├── authApi.js │ │ │ └── utils │ │ │ │ ├── EmailForm.jsx │ │ │ │ ├── registration-alert.jsx │ │ │ │ ├── registration-buttons.jsx │ │ │ │ └── validator.jsx │ │ ├── common │ │ │ ├── JobTag.jsx │ │ │ ├── JsonEditor.jsx │ │ │ ├── PlaybookTag.jsx │ │ │ ├── StatusTag.jsx │ │ │ ├── TLPTag.jsx │ │ │ ├── TableCell.jsx │ │ │ ├── TableCellCollapse.jsx │ │ │ ├── TimePicker.jsx │ │ │ ├── areYouSureConfirmDialog.jsx │ │ │ ├── engineBadges.jsx │ │ │ ├── flows │ │ │ │ └── getLayoutedElements.js │ │ │ ├── form │ │ │ │ ├── ScanConfigSelectInput.jsx │ │ │ │ ├── TLPSelectInput.jsx │ │ │ │ ├── TagSelectInput.jsx │ │ │ │ ├── pluginsMultiSelectDropdownInput.jsx │ │ │ │ └── runtimeConfigurationInput.jsx │ │ │ ├── icon │ │ │ │ ├── StatusIcon.jsx │ │ │ │ ├── actionIcons.jsx │ │ │ │ └── icons.jsx │ │ │ └── markdownToHtml.jsx │ │ ├── dashboard │ │ │ ├── Dashboard.jsx │ │ │ └── charts.jsx │ │ ├── home │ │ │ ├── Home.jsx │ │ │ └── Home.scss │ │ ├── investigations │ │ │ ├── flow │ │ │ │ ├── CustomInvestigationNode.jsx │ │ │ │ ├── CustomJobNode.jsx │ │ │ │ ├── InvestigationFlow.jsx │ │ │ │ ├── investigationActions.jsx │ │ │ │ └── utils.js │ │ │ ├── result │ │ │ │ ├── InvestigationActionBar.jsx │ │ │ │ ├── InvestigationInfoCard.jsx │ │ │ │ ├── InvestigationOverview.jsx │ │ │ │ ├── InvestigationResult.jsx │ │ │ │ └── investigationApi.jsx │ │ │ └── table │ │ │ │ ├── InvestigationsTable.jsx │ │ │ │ └── investigationTableColumns.jsx │ │ ├── jobs │ │ │ ├── notification │ │ │ │ ├── NotificationPopoverButton.jsx │ │ │ │ ├── NotificationsList.jsx │ │ │ │ └── notificationApi.js │ │ │ ├── notifications.jsx │ │ │ ├── result │ │ │ │ ├── JobInfoCard.jsx │ │ │ │ ├── JobInfoIcon.jsx │ │ │ │ ├── JobIsRunningAlert.jsx │ │ │ │ ├── JobOverview.jsx │ │ │ │ ├── JobResult.jsx │ │ │ │ ├── bar │ │ │ │ │ ├── JobActionBar.jsx │ │ │ │ │ ├── SaveAsPlaybooksForm.jsx │ │ │ │ │ └── comment │ │ │ │ │ │ ├── CommentOverview.jsx │ │ │ │ │ │ ├── CommentResult.jsx │ │ │ │ │ │ └── commentApi.js │ │ │ │ ├── flow │ │ │ │ │ ├── CustomJobPipelineNode.jsx │ │ │ │ │ ├── JobIsRunningFlow.jsx │ │ │ │ │ └── utils.js │ │ │ │ ├── jobApi.jsx │ │ │ │ ├── pluginReportTables.jsx │ │ │ │ ├── utils │ │ │ │ │ ├── extractCountry.js │ │ │ │ │ └── reportedPlugins.jsx │ │ │ │ └── visualizer │ │ │ │ │ ├── VisualizerTooltip.jsx │ │ │ │ │ ├── elements │ │ │ │ │ ├── base.jsx │ │ │ │ │ ├── bool.jsx │ │ │ │ │ ├── const.js │ │ │ │ │ ├── download.jsx │ │ │ │ │ ├── horizontalList.jsx │ │ │ │ │ ├── table.jsx │ │ │ │ │ ├── title.jsx │ │ │ │ │ └── verticalList.jsx │ │ │ │ │ ├── validators.js │ │ │ │ │ └── visualizer.jsx │ │ │ └── table │ │ │ │ ├── JobsTable.jsx │ │ │ │ ├── jobTableColumns.jsx │ │ │ │ └── playbookJobInfo.jsx │ │ ├── organization │ │ │ ├── InvitationsList.jsx │ │ │ ├── MyOrgPage.jsx │ │ │ ├── Organization.jsx │ │ │ ├── orgApi.js │ │ │ └── utils │ │ │ │ ├── InvitationStatusBadge.jsx │ │ │ │ ├── InviteButton.jsx │ │ │ │ ├── MembersList.jsx │ │ │ │ ├── OrgCreateButton.jsx │ │ │ │ ├── OrgInfoCard.jsx │ │ │ │ └── PendingInvitationsList.jsx │ │ ├── plugins │ │ │ ├── PluginConfigContainer.jsx │ │ │ ├── PluginConfigModal.jsx │ │ │ ├── PluginsContainer.jsx │ │ │ ├── flows │ │ │ │ ├── CustomPivotNode.jsx │ │ │ │ ├── CustomPlaybookNode.jsx │ │ │ │ ├── PlaybookFlows.jsx │ │ │ │ └── utils.js │ │ │ ├── forms │ │ │ │ ├── AnalyzerConfigForm.jsx │ │ │ │ ├── PivotConfigForm.jsx │ │ │ │ ├── PlaybookConfigForm.jsx │ │ │ │ └── PluginConfigForm.jsx │ │ │ ├── pluginsApi.jsx │ │ │ └── tables │ │ │ │ ├── Analyzers.jsx │ │ │ │ ├── Connectors.jsx │ │ │ │ ├── Ingestors.jsx │ │ │ │ ├── Pivots.jsx │ │ │ │ ├── Playbooks.jsx │ │ │ │ ├── PluginWrapper.jsx │ │ │ │ ├── Visualizers.jsx │ │ │ │ ├── pluginActionsButtons.jsx │ │ │ │ └── pluginTableColumns.jsx │ │ ├── scan │ │ │ ├── ScanForm.jsx │ │ │ ├── scanApi.jsx │ │ │ └── utils │ │ │ │ ├── MultipleObservablesModal.jsx │ │ │ │ ├── RecentScans.jsx │ │ │ │ └── RuntimeConfigurationModal.jsx │ │ ├── search │ │ │ ├── Search.jsx │ │ │ ├── searchApi.jsx │ │ │ ├── searchTableColumns.jsx │ │ │ └── utils.jsx │ │ └── user │ │ │ └── token │ │ │ ├── TokenAccess.jsx │ │ │ ├── TokenPage.jsx │ │ │ └── tokenApi.js │ ├── constants │ │ ├── advancedSettingsConst.js │ │ ├── apiURLs.js │ │ ├── colorConst.js │ │ ├── engineConst.js │ │ ├── environment.js │ │ ├── investigationConst.js │ │ ├── jobConst.js │ │ ├── miscConst.js │ │ ├── pluginConst.js │ │ └── regexConst.js │ ├── contexts │ │ └── GuideContext.jsx │ ├── hooks │ │ ├── index.js │ │ └── useQuotaBadge.jsx │ ├── index.jsx │ ├── layouts │ │ ├── AppHeader.jsx │ │ ├── AppMain.jsx │ │ ├── NoMatch.jsx │ │ ├── Toast.jsx │ │ └── widgets │ │ │ └── UserMenu.jsx │ ├── serviceWorker.js │ ├── stores │ │ ├── useAuthStore.jsx │ │ ├── useJsonEditorStore.jsx │ │ ├── useOrganizationStore.jsx │ │ ├── usePluginConfigurationStore.jsx │ │ ├── useRecentScansStore.jsx │ │ └── useTagsStore.jsx │ ├── styles │ │ └── App.scss │ ├── utils │ │ ├── api.jsx │ │ ├── files.js │ │ ├── initAxios.js │ │ ├── observables.js │ │ └── time.js │ └── wrappers │ │ ├── AuthGuard.jsx │ │ ├── IfAuthRedirectGuard.jsx │ │ └── withAuth.jsx └── tests │ ├── components │ ├── History.test.jsx │ ├── auth │ │ ├── EmailVerification.test.jsx │ │ ├── Login.test.jsx │ │ ├── Logout.test.jsx │ │ ├── Register.test.jsx │ │ ├── ResetPassword.test.jsx │ │ └── utils │ │ │ ├── EmailForm.test.jsx │ │ │ ├── registration-alert.test.jsx │ │ │ ├── registration-buttons.test.jsx │ │ │ └── validator.test.jsx │ ├── common │ │ ├── JsonEditor.test.jsx │ │ └── TimePicker.test.jsx │ ├── dashboard │ │ ├── Dashboard.test.jsx │ │ └── charts.test.jsx │ ├── investigations │ │ ├── flow │ │ │ ├── InvestigationFlow.test.jsx │ │ │ └── investigationActions.test.jsx │ │ └── result │ │ │ ├── InvestigationActionBar.test.jsx │ │ │ ├── InvestigationInfoCard.test.jsx │ │ │ └── InvestigationOverview.test.jsx │ ├── jobs │ │ ├── result │ │ │ ├── JobInfoCard.test.jsx │ │ │ ├── JobIsRunningAlert.test.jsx │ │ │ ├── JobOverview.test.jsx │ │ │ ├── pluginReportTable.test.jsx │ │ │ ├── utils │ │ │ │ ├── JobActionBar.test.jsx │ │ │ │ ├── extractCountry.test.js │ │ │ │ └── reportedPlugins.test.jsx │ │ │ └── visualizer │ │ │ │ ├── elements │ │ │ │ ├── base.test.jsx │ │ │ │ ├── bool.test.jsx │ │ │ │ ├── download.test.jsx │ │ │ │ ├── horizontalList.test.jsx │ │ │ │ ├── table.test.jsx │ │ │ │ ├── title.test.jsx │ │ │ │ └── verticalList.test.jsx │ │ │ │ ├── icons.test.jsx │ │ │ │ ├── validators.test.js │ │ │ │ ├── visualizer.test.jsx │ │ │ │ └── visualizerTooltip.test.jsx │ │ └── table │ │ │ └── playbookJobInfo.test.jsx │ ├── organization │ │ ├── MyOrgPage.test.jsx │ │ └── utils │ │ │ └── MembersList.test.jsx │ ├── plugins │ │ ├── PluginConfigContainer.test.jsx │ │ ├── PluginConfigModal.test.jsx │ │ ├── PluginsContainers.test.jsx │ │ ├── flows │ │ │ └── PlaybookFlows.test.jsx │ │ ├── forms │ │ │ ├── AnalyzerConfigForm.test.jsx │ │ │ ├── PivotConfigForm.test.jsx │ │ │ ├── PlaybookConfigForm.test.jsx │ │ │ └── PluginConfigForm.test.jsx │ │ └── tables │ │ │ ├── Analyzers.test.jsx │ │ │ ├── Connectors.test.jsx │ │ │ ├── Ingestors.test.jsx │ │ │ ├── Pivots.test.jsx │ │ │ ├── Playbooks.test.jsx │ │ │ ├── Visualizers.test.jsx │ │ │ └── pluginActionsButtons.test.jsx │ ├── scan │ │ ├── ScanForm │ │ │ ├── ScanForm.advanced.test.jsx │ │ │ ├── ScanForm.toastRedirect.test.jsx │ │ │ ├── ScanForm.validation.test.jsx │ │ │ └── requests │ │ │ │ ├── ScanForm.file.test.jsx │ │ │ │ └── ScanForm.observable.test.jsx │ │ └── utils │ │ │ ├── MultipleObservablesModal.test.jsx │ │ │ ├── RecentScans.test.jsx │ │ │ └── RuntimeConfigurationModal.test.jsx │ ├── search │ │ └── Search.test.jsx │ ├── user │ │ └── token │ │ │ ├── TokenAccess.test.jsx │ │ │ └── TokenPage.test.jsx │ └── utils │ │ └── time.test.js │ ├── constants │ └── regexConst.test.js │ ├── layouts │ └── AppHeader.test.jsx │ ├── mock.js │ ├── test-setup.js │ └── utils │ ├── api.test.jsx │ ├── files.test.js │ └── observables.test.js ├── initialize.sh ├── integrations ├── __init__.py ├── bbot │ ├── Dockerfile │ ├── app.py │ ├── compose-tests.yml │ ├── compose.yml │ └── requirements.txt ├── cyberchef │ ├── Dockerfile │ ├── compose-tests.yml │ ├── compose.yml │ └── hooks │ │ └── build ├── malware_tools_analyzers │ ├── Dockerfile │ ├── app.py │ ├── clamav │ │ ├── etc │ │ │ ├── clamd.conf │ │ │ ├── fangfrisch.conf │ │ │ └── freshclam.conf │ │ └── sigs │ │ │ └── LOLDrivers.hdb │ ├── compose-tests.yml │ ├── compose.yml │ ├── crontab │ ├── droidlysis │ │ └── general.conf │ ├── entrypoint.sh │ ├── hooks │ │ └── build │ ├── qiling │ │ ├── analyze.py │ │ ├── profiles │ │ │ └── README.md │ │ └── rootfs │ │ │ └── README.md │ ├── requirements │ │ ├── apkid-requirements.txt │ │ ├── droidlysis-requirements.txt │ │ ├── flask-requirements.txt │ │ ├── mobsf-requirements.txt │ │ ├── peframe-requirements.txt │ │ ├── qiling-requirements.txt │ │ └── stringsifter-requirements.txt │ └── stringsifter │ │ └── wrapper.py ├── nuclei_analyzer │ ├── Dockerfile │ ├── app.py │ ├── compose-tests.yml │ ├── compose.yml │ ├── entrypoint.sh │ ├── hooks │ │ └── build │ └── requirements.txt ├── pcap_analyzers │ ├── Dockerfile │ ├── app.py │ ├── check_pcap.py │ ├── compose-tests.yml │ ├── compose.yml │ ├── config │ │ └── suricata │ │ │ ├── etc │ │ │ ├── classification.config │ │ │ ├── disable.conf │ │ │ ├── enable.conf │ │ │ ├── reference.config │ │ │ ├── suricata.yaml │ │ │ ├── threshold.config │ │ │ └── update.yaml │ │ │ └── rules │ │ │ └── custom.rules │ ├── crontab │ ├── entrypoint.sh │ ├── hooks │ │ └── build │ ├── requirements.txt │ └── update_signatures.sh ├── phishing_analyzers │ ├── Dockerfile │ ├── __init__.py │ ├── analyzers │ │ ├── __init__.py │ │ ├── driver_wrapper.py │ │ ├── extract_phishing_site.py │ │ └── seleniumwire_request_serializer.py │ ├── app.py │ ├── compose-tests.yml │ ├── compose.yml │ ├── entrypoint.sh │ ├── hooks │ │ └── build │ └── requirements.txt ├── phoneinfoga │ ├── compose-tests.yml │ └── compose.yml ├── thug │ ├── Dockerfile │ ├── app.py │ ├── compose-tests.yml │ ├── compose.yml │ ├── entrypoint.sh │ └── requirements.txt └── tor_analyzers │ ├── Dockerfile │ ├── app.py │ ├── bundled │ └── onionscan │ ├── compose-tests.yml │ ├── compose.yml │ ├── entrypoint.sh │ ├── hooks │ └── build │ └── requirements.txt ├── intel_owl ├── __init__.py ├── asgi.py ├── backends.py ├── celery.py ├── consts.py ├── middleware.py ├── secrets.py ├── settings │ ├── __init__.py │ ├── _util.py │ ├── a_secrets.py │ ├── auth.py │ ├── aws.py │ ├── cache.py │ ├── celery.py │ ├── certego.py │ ├── commons.py │ ├── db.py │ ├── django.py │ ├── elasticsearch.py │ ├── logging.py │ ├── mail.py │ ├── rest.py │ ├── security.py │ ├── storage.py │ └── websocket.py ├── tasks.py ├── test_runner.py ├── urls.py └── wsgi.py ├── jsconfig.json ├── manage.py ├── pyproject.toml ├── requirements ├── certego-requirements.txt ├── django-server-requirements.txt ├── hardcoded-requirements.txt ├── project-requirements.txt └── test-requirements.txt ├── start ├── static ├── Certego.png ├── greedybear.png ├── gsoc_logo.png ├── honeynet_logo.png ├── intel_owl_negative.png ├── intel_owl_positive.png └── threathunter_logo.png └── tests ├── __init__.py ├── api_app ├── __init__.py ├── analyzable_manager │ ├── __init__.py │ └── test_models.py ├── analyzers_manager │ ├── __init__.py │ ├── file_analyzers │ │ ├── __init__.py │ │ ├── phishing │ │ │ └── test_phishing_form_compiler.py │ │ ├── test_boxjs.py │ │ ├── test_doc_info.py │ │ ├── test_iocextract.py │ │ ├── test_lnk_info.py │ │ ├── test_onenote_info.py │ │ ├── test_pdf_info.py │ │ └── test_strings_info.py │ ├── observable_analyzers │ │ ├── __init__.py │ │ └── test_nvd_cve.py │ ├── test_classes.py │ ├── test_models.py │ ├── test_signals.py │ └── test_views.py ├── connectors_manager │ ├── __init__.py │ ├── test_classes.py │ └── test_views.py ├── data_model_manager │ ├── __init__.py │ ├── test_models.py │ ├── test_queryset.py │ ├── test_serializers.py │ └── test_views.py ├── engines_manager │ ├── __init__.py │ ├── test_models.py │ └── test_modules.py ├── ingestors_manager │ ├── __init__.py │ ├── test_classes.py │ └── test_signals.py ├── investigations_manager │ ├── __init__.py │ ├── test_models.py │ ├── test_serializers.py │ └── test_views.py ├── pivots_manager │ ├── __init__.py │ ├── test_classes.py │ ├── test_models.py │ ├── test_serializers.py │ ├── test_validators.py │ └── test_views.py ├── playbooks_manager │ ├── __init__.py │ ├── test_queryset.py │ ├── test_serializers.py │ ├── test_validators.py │ └── test_views.py ├── test_api.py ├── test_classes.py ├── test_helpers.py ├── test_interfaces.py ├── test_mixins.py ├── test_models.py ├── test_queryset.py ├── test_serializers.py ├── test_signals.py ├── test_validators.py ├── test_views.py ├── test_websocket.py ├── user_events_manager │ ├── __init__.py │ ├── test_models.py │ ├── test_queryset.py │ ├── test_serializers.py │ └── test_views.py └── visualizers_manager │ ├── __init__.py │ ├── passive_dns │ └── test_analyzer_extractor.py │ ├── test_classes.py │ ├── test_validators.py │ └── test_views.py ├── auth ├── __init__.py ├── test_api.py ├── test_auth.py └── test_oauth.py ├── intel_owl ├── __init__.py └── test_tasks.py ├── mock_utils.py ├── test_crons.py ├── test_files.zip └── test_interfaces.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | source = 4 | api_app 5 | intel_owl 6 | concurrency = multiprocessing 7 | parallel = True 8 | 9 | [report] 10 | exclude_lines = 11 | if self.debug: 12 | pragma: no cover 13 | raise NotImplementedError 14 | if __name__ == .__main__.: 15 | ignore_errors = True 16 | omit = 17 | tests/* 18 | .venv/* 19 | venv/ -------------------------------------------------------------------------------- /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | test_patterns = [ 4 | "tests/**", 5 | "test_*.py" 6 | ] 7 | 8 | [[analyzers]] 9 | name = "python" 10 | enabled = true 11 | 12 | [analyzers.meta] 13 | runtime_version = "3.x.x" 14 | 15 | [[analyzers]] 16 | name = "docker" 17 | enabled = true 18 | 19 | [analyzers.meta] 20 | dockerfile_paths = [ 21 | "docker/Dockerfile", 22 | "docker/Dockerfile_nginx" 23 | ] 24 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .git 3 | .vscode 4 | .lgtm.yml 5 | __pycache__ 6 | venv/ 7 | **/build 8 | .env 9 | docker/env_file_* 10 | docker/custom.override.yml 11 | **/docker-compose.* 12 | docs/ 13 | frontend/node_modules 14 | frontend/dist 15 | frontend/build 16 | integrations/ 17 | docker-compose* 18 | *.quark.log 19 | .pre-commit-config.yaml 20 | .ipython/ 21 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 140 3 | ignore = 4 | W503, 5 | E231, 6 | W605, 7 | exclude = 8 | Dockerfile, 9 | docker-compose*, 10 | venv, 11 | docs, 12 | migrations, 13 | virtualenv, 14 | ldap_config.py 15 | api_app/analyzers_manager/migrations/* 16 | api_app/ingestors_manager/migrations/* -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please refer to https://intelowlproject.github.io/docs/IntelOwl/contribute/ 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | open_collective: intelowl-project 2 | github: intelowlproject -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue_template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Issue Template 3 | about: used to report bugs 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## What happened 11 | 12 | ## Environment 13 | 1. OS: 14 | 2. IntelOwl version: 15 | 16 | ## What did you expect to happen 17 | 18 | ## How to reproduce your issue 19 | 20 | ## Error messages and logs 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new_analyzer.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: New Analyzer 3 | about: A new analyzer to integrate with IntelOwl 4 | title: "[Analyzer]" 5 | labels: new_analyzer 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Name 11 | 12 | ## Link 13 | 14 | ## Type of analyzer 15 | **this can be observable, file, and docker** 16 | 17 | 18 | ## Why should we use it 19 | 20 | 21 | ## Possible implementation 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new_connector.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: New Connector 3 | about: A new connector to integrate with IntelOwl 4 | title: "[Connector]" 5 | labels: new_connector 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Name 11 | 12 | ## Link 13 | 14 | ## Type of connector 15 | ** what kind of data this connector would push to the integrated service ** 16 | 17 | 18 | ## Why should we use it 19 | 20 | 21 | ## Possible implementation 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new_ingestor.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: New Ingestor 3 | about: A new ingestor to integrate with IntelOwl 4 | title: "[Ingestor]" 5 | labels: new_ingestor 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Name 11 | 12 | ## Link 13 | 14 | 15 | ## Why should we use it 16 | 17 | 18 | ## Possible implementation 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new_playbook.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: New Playbook 3 | about: A new playbook configured inside IntelOwl 4 | title: "[Playbook]" 5 | labels: new_playbook 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Name 11 | 12 | 13 | ## Analyzers 14 | 15 | 16 | ## Connectors 17 | 18 | 19 | ## Runtime configuration 20 | 21 | 22 | ## Use case 23 | 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new_visualizer.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: New Visualizer 3 | about: A new visualizer to integrate with IntelOwl 4 | title: "[Visualizer]" 5 | labels: new_visualizer 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Name 11 | 12 | 13 | ## Playbooks 14 | 15 | 16 | ## Why should we create it 17 | 18 | 19 | ## Possible implementation 20 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | |---------| ------------------ | 7 | | >4.x.x | :white_check_mark: | 8 | | <4.x.x | :x: | 9 | 10 | ## Reporting a Vulnerability 11 | 12 | Please contact privately via Twitter one of the current maintainers. 13 | Current list of maintainers is available here: https://github.com/intelowlproject/IntelOwl#about-the-author-and-maintainers 14 | 15 | Then we would: 16 | * verify the vulnerability 17 | * once verified, open a Security Advisory in Github 18 | * update you with progress -------------------------------------------------------------------------------- /.github/workflows/dependency_review.yml: -------------------------------------------------------------------------------- 1 | name: 'Dependency Review' 2 | on: 3 | pull_request: 4 | branches: [ master, develop ] 5 | 6 | permissions: 7 | contents: read 8 | 9 | jobs: 10 | dependency-review: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: 'Checkout Repository' 14 | uses: actions/checkout@v4.2.2 15 | - name: 'Dependency Review' 16 | uses: actions/dependency-review-action@v4 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ide 2 | .idea 3 | .vscode 4 | 5 | 6 | __pycache__ 7 | test_files 8 | docker/env_file_app 9 | docker/env_file_postgres 10 | docker/env_file_integrations 11 | docker/env_file_elasticsearch 12 | docker/custom.override.yml 13 | venv/ 14 | intel_owl_test_env/ 15 | compose-elk.yml 16 | 17 | .python_history 18 | .viminfo 19 | 20 | # certs 21 | certs/ 22 | 23 | # docs 24 | docs_env/ 25 | docs/build/ 26 | 27 | 28 | configuration/service_account_keyfile.json 29 | configuration/custom_yara/* 30 | coverage_reports/ 31 | docker/.env.start.test 32 | docker/.env.start 33 | .ipython 34 | .subversion 35 | .bash_history 36 | .cache 37 | .google-cookie 38 | .quark-engine 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | .hypothesis/ 50 | /.env 51 | 52 | # post run dev 53 | integrations/malware_tools_analyzers/clamav/sigs -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_dirs": ["node_modules", "venv"] 3 | } -------------------------------------------------------------------------------- /api_app/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/__init__.py -------------------------------------------------------------------------------- /api_app/analyzables_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzables_manager/__init__.py -------------------------------------------------------------------------------- /api_app/analyzables_manager/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from api_app.analyzables_manager.models import Analyzable 4 | 5 | 6 | @admin.register(Analyzable) 7 | class AnalyzableAdmin(admin.ModelAdmin): 8 | list_display = ["pk", "name", "sha1", "sha256", "md5"] 9 | search_fields = ["name", "sha1", "sha256", "md5"] 10 | ordering = ["name"] 11 | list_filter = ["discovery_date"] 12 | -------------------------------------------------------------------------------- /api_app/analyzables_manager/apps.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class AnalyzablesManagerConfig(AppConfig): 8 | name = "api_app.analyzables_manager" 9 | 10 | @staticmethod 11 | def ready() -> None: 12 | from . import signals # noqa 13 | -------------------------------------------------------------------------------- /api_app/analyzables_manager/migrations/0003_analyzable_analyzables_classif_adf7ca_idx_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.17 on 2025-01-23 14:38 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("analyzables_manager", "0002_migrate_data"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddIndex( 14 | model_name="analyzable", 15 | index=models.Index( 16 | fields=["classification"], name="analyzables_classif_adf7ca_idx" 17 | ), 18 | ), 19 | migrations.AddIndex( 20 | model_name="analyzable", 21 | index=models.Index( 22 | fields=["mimetype"], name="analyzables_mimetyp_321d7d_idx" 23 | ), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /api_app/analyzables_manager/migrations/0004_analyzable_name_field_index.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.17 on 2025-03-07 11:17 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ( 10 | "analyzables_manager", 11 | "0003_analyzable_analyzables_classif_adf7ca_idx_and_more", 12 | ), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddIndex( 17 | model_name="analyzable", 18 | index=models.Index(fields=["name"], name="analyzables_name_aa34aa_idx"), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /api_app/analyzables_manager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzables_manager/migrations/__init__.py -------------------------------------------------------------------------------- /api_app/analyzables_manager/queryset.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from django.db.models import QuerySet 4 | 5 | logger = logging.getLogger(__name__) 6 | 7 | 8 | class AnalyzableQuerySet(QuerySet): 9 | 10 | def visible_for_user(self, user): 11 | 12 | from api_app.models import Job 13 | 14 | analyzables = ( 15 | Job.objects.visible_for_user(user) 16 | .values("analyzable") 17 | .distinct() 18 | .values_list("analyzable__pk", flat=True) 19 | ) 20 | return self.filter(pk__in=analyzables) 21 | 22 | def create(self, *args, **kwargs): 23 | obj = self.model(**kwargs) 24 | self._for_write = True 25 | try: 26 | obj.full_clean() 27 | except Exception as e: 28 | logger.error(f"Already exists obj {obj.md5}") 29 | raise e 30 | obj.save(force_insert=True, using=self.db) 31 | return obj 32 | -------------------------------------------------------------------------------- /api_app/analyzables_manager/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework.serializers import ModelSerializer 2 | 3 | from api_app.analyzables_manager.models import Analyzable 4 | from api_app.serializers.job import JobRelatedField 5 | 6 | 7 | class AnalyzableSerializer(ModelSerializer): 8 | jobs = JobRelatedField(many=True, read_only=True) 9 | 10 | class Meta: 11 | model = Analyzable 12 | fields = "__all__" 13 | -------------------------------------------------------------------------------- /api_app/analyzables_manager/urls.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.urls import include, path 5 | from rest_framework import routers 6 | 7 | from api_app.analyzables_manager.views import AnalyzableViewSet 8 | 9 | # Routers provide an easy way of automatically determining the URL conf. 10 | 11 | 12 | router = routers.DefaultRouter(trailing_slash=False) 13 | router.register(r"analyzable", AnalyzableViewSet, basename="analyzable") 14 | 15 | urlpatterns = [ 16 | # Viewsets 17 | path(r"", include(router.urls)), 18 | ] 19 | -------------------------------------------------------------------------------- /api_app/analyzables_manager/views.py: -------------------------------------------------------------------------------- 1 | from rest_framework import viewsets 2 | from rest_framework.permissions import IsAuthenticated 3 | 4 | from api_app.analyzables_manager.serializers import AnalyzableSerializer 5 | 6 | 7 | class AnalyzableViewSet(viewsets.ReadOnlyModelViewSet): 8 | 9 | serializer_class = AnalyzableSerializer 10 | permission_classes = [IsAuthenticated] 11 | 12 | def get_queryset(self): 13 | user = self.request.user 14 | return super().get_queryset().visible_for_user(user) 15 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzers_manager/__init__.py -------------------------------------------------------------------------------- /api_app/analyzers_manager/admin.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | from django.contrib import admin 4 | 5 | from api_app.admin import AbstractReportAdminView, PythonConfigAdminView 6 | from api_app.analyzers_manager.models import AnalyzerConfig, AnalyzerReport 7 | 8 | 9 | # flake8: noqa 10 | @admin.register(AnalyzerReport) 11 | class AnalyzerReportAdminView(AbstractReportAdminView): ... 12 | 13 | 14 | @admin.register(AnalyzerConfig) 15 | class AnalyzerConfigAdminView(PythonConfigAdminView): 16 | list_display = PythonConfigAdminView.list_display + ( 17 | "type", 18 | "docker_based", 19 | "maximum_tlp", 20 | ) 21 | list_filter = ["type", "maximum_tlp"] + PythonConfigAdminView.list_filter 22 | exclude = ["update_task"] 23 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/apps.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class AnalyzersManagerConfig(AppConfig): 8 | name = "api_app.analyzers_manager" 9 | 10 | @staticmethod 11 | def ready() -> None: 12 | from . import signals # noqa 13 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/constants.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | from logging import getLogger 4 | 5 | from django.db import models 6 | 7 | logger = getLogger(__name__) 8 | 9 | 10 | class TypeChoices(models.TextChoices): 11 | FILE = "file" 12 | OBSERVABLE = "observable" 13 | 14 | 15 | class HashChoices(models.TextChoices): 16 | MD5 = "md5" 17 | SHA256 = "sha256" 18 | 19 | 20 | class HTTPMethods(models.TextChoices): 21 | GET = "get" 22 | POST = "post" 23 | PUT = "put" 24 | PATCH = "patch" 25 | DELETE = "delete" 26 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/exceptions.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | 5 | class NotRunnableAnalyzer(Exception): 6 | pass 7 | 8 | 9 | class AnalyzerRunException(Exception): 10 | pass 11 | 12 | 13 | class AnalyzerConfigurationException(Exception): 14 | pass 15 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/file_analyzers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzers_manager/file_analyzers/__init__.py -------------------------------------------------------------------------------- /api_app/analyzers_manager/file_analyzers/phishing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzers_manager/file_analyzers/phishing/__init__.py -------------------------------------------------------------------------------- /api_app/analyzers_manager/filters.py: -------------------------------------------------------------------------------- 1 | import rest_framework_filters as filters 2 | 3 | from api_app.analyzers_manager.models import AnalyzerConfig 4 | from api_app.fields import ChoiceArrayField 5 | 6 | 7 | class AnalyzerConfigFilter(filters.FilterSet): 8 | class Meta: 9 | model = AnalyzerConfig 10 | filter_overrides = { 11 | ChoiceArrayField: { 12 | "filter_class": filters.ChoiceFilter, 13 | } 14 | } 15 | fields = {"type": ["exact"], "observable_supported": ["in"]} 16 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/migrations/0058_1_change_primary_key.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.8 on 2024-01-09 14:31 2 | from django.db import migrations 3 | 4 | 5 | class Migration(migrations.Migration): 6 | dependencies = [ 7 | ("analyzers_manager", "0002_0146_analyzer_config_zoomeye"), 8 | ("playbooks_manager", "0001_initial_squashed"), 9 | ("api_app", "0001_2_initial_squashed"), 10 | ] 11 | 12 | operations = [] 13 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/migrations/0073_remove_dragonfly_analyzer.py: -------------------------------------------------------------------------------- 1 | from django.db import migrations 2 | 3 | 4 | def migrate(apps, schema_editor): 5 | PythonModule = apps.get_model("api_app", "PythonModule") 6 | pm = PythonModule.objects.get( 7 | module="dragonfly.DragonflyEmulation", 8 | base_path="api_app.analyzers_manager.file_analyzers", 9 | ) 10 | pm.analyzerconfigs.all().delete() 11 | pm.delete() 12 | 13 | 14 | def reverse_migrate(apps, schema_editor): 15 | pass 16 | 17 | 18 | class Migration(migrations.Migration): 19 | dependencies = [ 20 | ("api_app", "0062_alter_parameter_python_module"), 21 | ("analyzers_manager", "0072_analyzer_config_tweetfeed"), 22 | ] 23 | operations = [ 24 | migrations.RunPython(migrate, reverse_migrate), 25 | ] 26 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/migrations/0075_adjust_greynoise.py: -------------------------------------------------------------------------------- 1 | from django.db import migrations 2 | 3 | 4 | def migrate(apps, schema_editor): 5 | PythonModule = apps.get_model("api_app", "PythonModule") 6 | 7 | pm = PythonModule.objects.get( 8 | module="greynoiseintel.GreyNoiseAnalyzer", 9 | base_path="api_app.analyzers_manager.observable_analyzers", 10 | ) 11 | param = pm.parameters.get(name="api_key_name") 12 | param.required = False 13 | param.values.filter(owner=None, for_organization=False).delete() 14 | param.save() 15 | 16 | 17 | def reverse_migrate(apps, schema_editor): ... 18 | 19 | 20 | class Migration(migrations.Migration): 21 | dependencies = [ 22 | ("api_app", "0062_alter_parameter_python_module"), 23 | ("analyzers_manager", "0074_adjust_maximum_tlp"), 24 | ] 25 | operations = [ 26 | migrations.RunPython(migrate, reverse_migrate), 27 | ] 28 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/migrations/0079_remove_dns0_rrsets_analyzer.py: -------------------------------------------------------------------------------- 1 | from django.db import migrations 2 | 3 | 4 | def migrate(apps, schema_editor): 5 | PythonModule = apps.get_model("api_app", "PythonModule") 6 | pm = PythonModule.objects.filter( 7 | module="dns0.dns0_rrsets.DNS0Rrsets", 8 | base_path="api_app.analyzers_manager.observable_analyzers", 9 | ).first() 10 | if pm: 11 | pm.analyzerconfigs.all().delete() 12 | pm.delete() 13 | 14 | 15 | def reverse_migrate(apps, schema_editor): 16 | pass 17 | 18 | 19 | class Migration(migrations.Migration): 20 | dependencies = [ 21 | ("api_app", "0062_alter_parameter_python_module"), 22 | ("playbooks_manager", "0032_delete_dns0_playbook_free_to_use_analyzers"), 23 | ("analyzers_manager", "0078_analyzer_config_hfinger"), 24 | ] 25 | operations = [ 26 | migrations.RunPython(migrate, reverse_migrate), 27 | ] 28 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/migrations/0080_remove_dns0_names_analyzer.py: -------------------------------------------------------------------------------- 1 | from django.db import migrations 2 | 3 | 4 | def migrate(apps, schema_editor): 5 | PythonModule = apps.get_model("api_app", "PythonModule") 6 | pm = PythonModule.objects.filter( 7 | module="dns0.dns0_names.DNS0Names", 8 | base_path="api_app.analyzers_manager.observable_analyzers", 9 | ).first() 10 | if pm: 11 | pm.analyzerconfigs.all().delete() 12 | pm.delete() 13 | 14 | 15 | def reverse_migrate(apps, schema_editor): 16 | pass 17 | 18 | 19 | class Migration(migrations.Migration): 20 | dependencies = [ 21 | ("api_app", "0062_alter_parameter_python_module"), 22 | ("playbooks_manager", "0032_delete_dns0_playbook_free_to_use_analyzers"), 23 | ("analyzers_manager", "0079_remove_dns0_rrsets_analyzer"), 24 | ] 25 | operations = [ 26 | migrations.RunPython(migrate, reverse_migrate), 27 | ] 28 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/migrations/0081_adjust_abusix.py: -------------------------------------------------------------------------------- 1 | from django.db import migrations 2 | 3 | 4 | def migrate(apps, schema_editor): 5 | AnalyzerConfig = apps.get_model("analyzers_manager", "AnalyzerConfig") 6 | 7 | AnalyzerConfig.objects.filter( 8 | name="Abusix", 9 | ).update(health_check_status=True) 10 | 11 | 12 | def reverse_migrate(apps, schema_editor): 13 | pass 14 | 15 | 16 | class Migration(migrations.Migration): 17 | dependencies = [ 18 | ("api_app", "0062_alter_parameter_python_module"), 19 | ("analyzers_manager", "0080_remove_dns0_names_analyzer"), 20 | ] 21 | operations = [ 22 | migrations.RunPython(migrate, reverse_migrate), 23 | ] 24 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/migrations/0083_adjust_docinfo.py: -------------------------------------------------------------------------------- 1 | from django.db import migrations 2 | 3 | 4 | def migrate(apps, schema_editor): 5 | AnalyzerConfig = apps.get_model("analyzers_manager", "AnalyzerConfig") 6 | 7 | ac = AnalyzerConfig.objects.get( 8 | name="Doc_Info", 9 | ) 10 | ac.supported_filetypes.remove("application/onenote") 11 | ac.save() 12 | 13 | 14 | def reverse_migrate(apps, schema_editor): 15 | pass 16 | 17 | 18 | class Migration(migrations.Migration): 19 | dependencies = [ 20 | ("api_app", "0062_alter_parameter_python_module"), 21 | ("analyzers_manager", "0082_analyzer_config_ip2whois"), 22 | ] 23 | operations = [ 24 | migrations.RunPython(migrate, reverse_migrate), 25 | ] 26 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/migrations/0087_alter_mmdbserver_param.py: -------------------------------------------------------------------------------- 1 | from django.db import migrations 2 | 3 | 4 | def migrate(apps, schema_editor): 5 | PythonModule = apps.get_model("api_app", "PythonModule") 6 | 7 | pm = PythonModule.objects.get( 8 | module="mmdb_server.MmdbServer", 9 | base_path="api_app.analyzers_manager.observable_analyzers", 10 | ) 11 | param = pm.parameters.get(name="base_url") 12 | param.name = "url" 13 | param.save() 14 | 15 | 16 | def reverse_migrate(apps, schema_editor): 17 | pass 18 | 19 | 20 | class Migration(migrations.Migration): 21 | dependencies = [ 22 | ("analyzers_manager", "0086_analyzer_config_blint"), 23 | ] 24 | operations = [ 25 | migrations.RunPython(migrate, reverse_migrate), 26 | ] 27 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/migrations/0134_analyzerconfig_mapping_data_model.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-10-14 07:24 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("analyzers_manager", "0133_analyzer_config_urldna_search"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name="analyzerconfig", 15 | name="mapping_data_model", 16 | field=models.JSONField( 17 | default=dict, help_text="Mapping data_model_key: analyzer_report_key. " 18 | ), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/migrations/0139_alter_analyzerconfig_mapping_data_model.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.16 on 2024-12-06 09:28 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("analyzers_manager", "0138_alter_analyzerreport_data_model_content_type"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name="analyzerconfig", 15 | name="mapping_data_model", 16 | field=models.JSONField( 17 | blank=True, 18 | default=dict, 19 | help_text="Mapping analyzer_report_key: data_model_key. Keys preceded by the symbol $ will be considered as constants.", 20 | ), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/migrations/0140_analyzerreport_analyzers_m_data_mo_a1952b_idx.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.16 on 2024-12-12 11:45 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("analyzers_manager", "0139_alter_analyzerconfig_mapping_data_model"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddIndex( 14 | model_name="analyzerreport", 15 | index=models.Index( 16 | fields=["data_model_content_type", "data_model_object_id"], 17 | name="analyzers_m_data_mo_a1952b_idx", 18 | ), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzers_manager/migrations/__init__.py -------------------------------------------------------------------------------- /api_app/analyzers_manager/observable_analyzers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzers_manager/observable_analyzers/__init__.py -------------------------------------------------------------------------------- /api_app/analyzers_manager/observable_analyzers/criminalip/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzers_manager/observable_analyzers/criminalip/__init__.py -------------------------------------------------------------------------------- /api_app/analyzers_manager/observable_analyzers/criminalip/criminalip_base.py: -------------------------------------------------------------------------------- 1 | import abc 2 | 3 | from api_app.analyzers_manager.classes import BaseAnalyzerMixin 4 | 5 | 6 | class CriminalIpBase(BaseAnalyzerMixin, metaclass=abc.ABCMeta): 7 | url = "https://api.criminalip.io" 8 | _api_key: str = None 9 | 10 | def update(self): 11 | pass 12 | 13 | def getHeaders(self): 14 | return {"x-api-key": self._api_key} 15 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/observable_analyzers/dns/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzers_manager/observable_analyzers/dns/__init__.py -------------------------------------------------------------------------------- /api_app/analyzers_manager/observable_analyzers/dns/dns_malicious_detectors/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzers_manager/observable_analyzers/dns/dns_malicious_detectors/__init__.py -------------------------------------------------------------------------------- /api_app/analyzers_manager/observable_analyzers/dns/dns_resolvers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzers_manager/observable_analyzers/dns/dns_resolvers/__init__.py -------------------------------------------------------------------------------- /api_app/analyzers_manager/observable_analyzers/mb_google.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | import googlesearch 5 | 6 | from .mb_get import MB_GET 7 | 8 | 9 | class MB_GOOGLE(MB_GET): 10 | """ 11 | This is a modified version of MB_GET. 12 | """ 13 | 14 | def update(self) -> bool: 15 | pass 16 | 17 | def run(self): 18 | results = {} 19 | 20 | query = f"{self.observable_name} site:bazaar.abuse.ch" 21 | for url in googlesearch.search(query, stop=20): 22 | mb_hash = url.split("/")[-2] 23 | res = super().query_mb_api( 24 | observable_name=mb_hash, 25 | headers=self.authentication_header, 26 | ) 27 | results[mb_hash] = res 28 | 29 | return results 30 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/observable_analyzers/phishing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzers_manager/observable_analyzers/phishing/__init__.py -------------------------------------------------------------------------------- /api_app/analyzers_manager/observable_analyzers/triage/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzers_manager/observable_analyzers/triage/__init__.py -------------------------------------------------------------------------------- /api_app/analyzers_manager/observable_analyzers/vt/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/analyzers_manager/observable_analyzers/vt/__init__.py -------------------------------------------------------------------------------- /api_app/analyzers_manager/queryset.py: -------------------------------------------------------------------------------- 1 | from typing import TYPE_CHECKING, Type 2 | 3 | from api_app.queryset import AbstractReportQuerySet 4 | 5 | if TYPE_CHECKING: 6 | from api_app.analyzers_manager.serializers import AnalyzerReportBISerializer 7 | 8 | 9 | class AnalyzerReportQuerySet(AbstractReportQuerySet): 10 | @classmethod 11 | def _get_bi_serializer_class(cls) -> Type["AnalyzerReportBISerializer"]: 12 | from api_app.analyzers_manager.serializers import AnalyzerReportBISerializer 13 | 14 | return AnalyzerReportBISerializer 15 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/signals.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import uuid 3 | 4 | from django.conf import settings 5 | from django.dispatch import receiver 6 | 7 | from api_app.analyzers_manager.models import AnalyzerConfig 8 | from api_app.signals import migrate_finished 9 | from intel_owl.celery import get_queue_name 10 | 11 | logger = logging.getLogger(__name__) 12 | 13 | 14 | @receiver(migrate_finished) 15 | def post_migrate_analyzers_manager( 16 | sender, 17 | *args, 18 | check_unapplied: bool = False, 19 | **kwargs, 20 | ): 21 | logger.info(f"Post migrate {args} {kwargs}") 22 | if check_unapplied: 23 | return 24 | from intel_owl.tasks import refresh_cache 25 | 26 | refresh_cache.apply_async( 27 | queue=get_queue_name(settings.CONFIG_QUEUE), 28 | MessageGroupId=str(uuid.uuid4()), 29 | priority=3, 30 | args=[AnalyzerConfig.python_path], 31 | ) 32 | -------------------------------------------------------------------------------- /api_app/analyzers_manager/ssh_gitpython.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ssh -i "/opt/deploy/files_required/my_gitpython_key" -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$@" -------------------------------------------------------------------------------- /api_app/apps.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | from logging import getLogger 4 | 5 | from django.apps import AppConfig 6 | 7 | logger = getLogger(__name__) 8 | 9 | 10 | class ApiAppConfig(AppConfig): 11 | name = "api_app" 12 | 13 | def ready(self): # skipcq: PYL-R0201 14 | from . import signals # noqa 15 | -------------------------------------------------------------------------------- /api_app/connectors_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/connectors_manager/__init__.py -------------------------------------------------------------------------------- /api_app/connectors_manager/admin.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.contrib import admin 5 | 6 | from api_app.admin import AbstractReportAdminView, PythonConfigAdminView 7 | from api_app.connectors_manager.models import ConnectorConfig, ConnectorReport 8 | 9 | 10 | @admin.register(ConnectorReport) 11 | # flake8: noqa 12 | class ConnectorReportAdminView(AbstractReportAdminView): ... 13 | 14 | 15 | @admin.register(ConnectorConfig) 16 | class ConnectorConfigAdminView(PythonConfigAdminView): 17 | list_display = PythonConfigAdminView.list_display + ( 18 | "maximum_tlp", 19 | "run_on_failure", 20 | ) 21 | -------------------------------------------------------------------------------- /api_app/connectors_manager/apps.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class ConnectorsManagerConfig(AppConfig): 8 | name = "api_app.connectors_manager" 9 | 10 | @staticmethod 11 | def ready() -> None: 12 | from . import signals # noqa 13 | -------------------------------------------------------------------------------- /api_app/connectors_manager/connectors/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/connectors_manager/connectors/__init__.py -------------------------------------------------------------------------------- /api_app/connectors_manager/exceptions.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | 5 | class NotRunnableConnector(Exception): 6 | pass 7 | 8 | 9 | class ConnectorConfigurationException(Exception): 10 | pass 11 | 12 | 13 | class ConnectorRunException(Exception): 14 | pass 15 | -------------------------------------------------------------------------------- /api_app/connectors_manager/forms.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/connectors_manager/forms.py -------------------------------------------------------------------------------- /api_app/connectors_manager/migrations/0029_1_change_primary_key.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.8 on 2024-01-09 14:31 2 | from django.db import migrations 3 | 4 | 5 | class Migration(migrations.Migration): 6 | dependencies = [ 7 | ("connectors_manager", "0002_0003_connector_config_yeti"), 8 | ("playbooks_manager", "0001_initial_squashed"), 9 | ("api_app", "0001_2_initial_squashed"), 10 | ] 11 | 12 | operations = [] 13 | -------------------------------------------------------------------------------- /api_app/connectors_manager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/connectors_manager/migrations/__init__.py -------------------------------------------------------------------------------- /api_app/connectors_manager/queryset.py: -------------------------------------------------------------------------------- 1 | from typing import TYPE_CHECKING, Type 2 | 3 | from api_app.queryset import AbstractReportQuerySet 4 | 5 | if TYPE_CHECKING: 6 | from api_app.connectors_manager.serializers import ConnectorReportBISerializer 7 | 8 | 9 | class ConnectorReportQuerySet(AbstractReportQuerySet): 10 | @classmethod 11 | def _get_bi_serializer_class(cls) -> Type["ConnectorReportBISerializer"]: 12 | from api_app.connectors_manager.serializers import ConnectorReportBISerializer 13 | 14 | return ConnectorReportBISerializer 15 | -------------------------------------------------------------------------------- /api_app/connectors_manager/signals.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import uuid 3 | 4 | from django.conf import settings 5 | from django.dispatch import receiver 6 | 7 | from api_app.connectors_manager.models import ConnectorConfig 8 | from api_app.signals import migrate_finished 9 | from intel_owl.celery import get_queue_name 10 | 11 | logger = logging.getLogger(__name__) 12 | 13 | 14 | @receiver(migrate_finished) 15 | def post_migrate_connectors_manager( 16 | sender, 17 | *args, 18 | check_unapplied: bool = False, 19 | **kwargs, 20 | ): 21 | logger.info(f"Post migrate {args} {kwargs}") 22 | if check_unapplied: 23 | return 24 | from intel_owl.tasks import refresh_cache 25 | 26 | refresh_cache.apply_async( 27 | queue=get_queue_name(settings.CONFIG_QUEUE), 28 | MessageGroupId=str(uuid.uuid4()), 29 | priority=3, 30 | args=[ConnectorConfig.python_path], 31 | ) 32 | -------------------------------------------------------------------------------- /api_app/connectors_manager/urls.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.urls import include, path 5 | from rest_framework import routers 6 | 7 | from .views import ( 8 | ConnectorActionViewSet, 9 | ConnectorConfigViewSet, 10 | ConnectorPluginConfigViewSet, 11 | ) 12 | 13 | # Routers provide an easy way of automatically determining the URL conf. 14 | router = routers.DefaultRouter(trailing_slash=False) 15 | router.register( 16 | r"jobs/(?P\d+)/connector/(?P\w+)", 17 | ConnectorActionViewSet, 18 | basename="connectorreport", 19 | ) 20 | router.register(r"connector", ConnectorConfigViewSet, basename="connector") 21 | router.register( 22 | r"connector/(?P\w+)", 23 | ConnectorPluginConfigViewSet, 24 | basename="plugin-config-connector", 25 | ) 26 | 27 | urlpatterns = [ 28 | path(r"", include(router.urls)), 29 | ] 30 | -------------------------------------------------------------------------------- /api_app/connectors_manager/views.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | import logging 5 | 6 | from ..views import PluginConfigViewSet, PythonConfigViewSet, PythonReportActionViewSet 7 | from .models import ConnectorConfig, ConnectorReport 8 | from .serializers import ConnectorConfigSerializer 9 | 10 | logger = logging.getLogger(__name__) 11 | 12 | 13 | __all__ = [ 14 | "ConnectorConfigViewSet", 15 | "ConnectorActionViewSet", 16 | ] 17 | 18 | 19 | class ConnectorConfigViewSet(PythonConfigViewSet): 20 | serializer_class = ConnectorConfigSerializer 21 | 22 | 23 | class ConnectorActionViewSet(PythonReportActionViewSet): 24 | @classmethod 25 | @property 26 | def report_model(cls): 27 | return ConnectorReport 28 | 29 | 30 | class ConnectorPluginConfigViewSet(PluginConfigViewSet): 31 | queryset = ConnectorConfig.objects.all() 32 | -------------------------------------------------------------------------------- /api_app/data_model_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/data_model_manager/__init__.py -------------------------------------------------------------------------------- /api_app/data_model_manager/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class DataModelConfig(AppConfig): 5 | name = "api_app.data_model_manager" 6 | -------------------------------------------------------------------------------- /api_app/data_model_manager/enums.py: -------------------------------------------------------------------------------- 1 | from django.db.models import Choices 2 | 3 | 4 | class SignatureProviderChoices(Choices): 5 | CLAMAV = "clam_av" 6 | SIGMA = "sigma" 7 | YARA = "yara" 8 | SURICATA = "suricata" 9 | 10 | 11 | class DataModelTags(Choices): 12 | PHISHING = "phishing" 13 | MALWARE = "malware" 14 | SOCIAL_ENGINEERING = "social_engineering" 15 | ANONYMIZER = "anonymizer" 16 | TOR_EXIT_NODE = "tor_exit_node" 17 | ABUSED = "abused" 18 | 19 | 20 | class DataModelEvaluations(Choices): 21 | TRUSTED = "trusted" 22 | MALICIOUS = "malicious" 23 | 24 | 25 | class DataModelKillChainPhases(Choices): 26 | RECONNAISSANCE = "reconnaissance" 27 | WEAPONIZATION = "weaponization" 28 | DELIVERY = "delivery" 29 | EXPLOITATION = "exploitation" 30 | INSTALLATION = "installation" 31 | C2 = "c2" 32 | ACTION = "action" 33 | -------------------------------------------------------------------------------- /api_app/data_model_manager/fields.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | 3 | from django.contrib.postgres.fields import ArrayField 4 | from django.db import models 5 | 6 | 7 | class SetField(ArrayField): 8 | def to_python(self, value): 9 | result = super().to_python(value) 10 | return list(set(result)) 11 | 12 | 13 | class LowercaseCharField(models.CharField): 14 | 15 | def to_python(self, value: Any): 16 | result = super().to_python(value) 17 | if result and isinstance(result, str): 18 | return result.lower() 19 | return result 20 | -------------------------------------------------------------------------------- /api_app/data_model_manager/migrations/0003_remove_ipdatamodel_ietf_report_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.16 on 2024-11-08 17:33 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("data_model_manager", "0002_domaindatamodel_resolutions_and_more"), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name="ipdatamodel", 15 | name="ietf_report", 16 | ), 17 | migrations.AddField( 18 | model_name="ipdatamodel", 19 | name="ietf_report", 20 | field=models.ManyToManyField( 21 | related_name="ips", to="data_model_manager.ietfreport" 22 | ), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /api_app/data_model_manager/migrations/0006_alter_ipdatamodel_asn_rank.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.16 on 2024-12-17 10:37 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ( 10 | "data_model_manager", 11 | "0005_alter_domaindatamodel_external_references_and_more", 12 | ), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name="ipdatamodel", 18 | name="asn_rank", 19 | field=models.DecimalField( 20 | blank=True, decimal_places=20, default=None, max_digits=21, null=True 21 | ), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /api_app/data_model_manager/migrations/0007_alter_signature_url.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.16 on 2024-12-19 09:58 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ( 10 | "data_model_manager", 11 | "0006_alter_ipdatamodel_asn_rank", 12 | ), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name="signature", 18 | name="url", 19 | field=models.URLField(blank=True, default=""), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /api_app/data_model_manager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/data_model_manager/migrations/__init__.py -------------------------------------------------------------------------------- /api_app/data_model_manager/queryset.py: -------------------------------------------------------------------------------- 1 | import typing 2 | from typing import Dict, List 3 | 4 | from django.db.models import QuerySet 5 | 6 | if typing.TYPE_CHECKING: 7 | from api_app.data_model_manager.models import BaseDataModel 8 | 9 | 10 | class BaseDataModelQuerySet(QuerySet): 11 | 12 | def merge(self, append: bool = True) -> "BaseDataModel": 13 | """ 14 | Base method of merge of multiple data models. 15 | :return: BaseDataModel 16 | """ 17 | result_obj: BaseDataModel = self.model.objects.create() 18 | for obj in self: 19 | result_obj.merge(obj, append=append) 20 | return result_obj 21 | 22 | def serialize(self) -> List[Dict]: 23 | try: 24 | serializer_class = self.model.get_serializer() 25 | except NotImplementedError: 26 | return [] 27 | return serializer_class(self, many=True, read_only=True).data 28 | -------------------------------------------------------------------------------- /api_app/data_model_manager/signals.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/data_model_manager/signals.py -------------------------------------------------------------------------------- /api_app/data_model_manager/urls.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.urls import include, path 5 | from rest_framework import routers 6 | 7 | # Routers provide an easy way of automatically determining the URL conf. 8 | from api_app.data_model_manager.views import ( 9 | DomainDataModelView, 10 | FileDataModelView, 11 | IPDataModelView, 12 | ) 13 | 14 | router = routers.DefaultRouter(trailing_slash=False) 15 | router.register(r"domain", DomainDataModelView, basename="domain") 16 | router.register(r"ip", IPDataModelView, basename="ip") 17 | router.register(r"file", FileDataModelView, basename="file") 18 | 19 | urlpatterns = [ 20 | # Viewsets 21 | path(r"", include(router.urls)), 22 | ] 23 | -------------------------------------------------------------------------------- /api_app/defaults.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | 4 | def config_default(): 5 | return dict(queue=settings.DEFAULT_QUEUE, soft_time_limit=60) 6 | 7 | 8 | def default_runtime(): 9 | return { 10 | "analyzers": {}, 11 | "connectors": {}, 12 | "pivots": {}, 13 | "visualizers": {}, 14 | } 15 | 16 | 17 | def file_directory_path(instance, filename): 18 | return instance.md5 19 | -------------------------------------------------------------------------------- /api_app/engines_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/engines_manager/__init__.py -------------------------------------------------------------------------------- /api_app/engines_manager/apps.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class EnginesManagerConfig(AppConfig): 8 | name = "api_app.engines_manager" 9 | 10 | @staticmethod 11 | def ready(**kwargs) -> None: 12 | from . import signals # noqa 13 | -------------------------------------------------------------------------------- /api_app/engines_manager/classes.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Dict 2 | 3 | from api_app.models import Job 4 | 5 | 6 | class EngineModule: 7 | def __init__(self, job: Job): 8 | self.job = job 9 | 10 | def run(self) -> Dict[str, Any]: 11 | raise NotImplementedError("Method run not implemented") 12 | -------------------------------------------------------------------------------- /api_app/engines_manager/engines/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/engines_manager/engines/__init__.py -------------------------------------------------------------------------------- /api_app/engines_manager/migrations/0003_engine.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.17 on 2025-01-15 09:34 2 | 3 | from django.db import migrations 4 | 5 | 6 | def migrate(apps, schema_editor): 7 | EngineConfig = apps.get_model("engines_manager", "EngineConfig") 8 | if not EngineConfig.objects.exists(): 9 | EngineConfig.objects.create( 10 | modules=["malware_family.MalwareFamilyEngineModule"] 11 | ) 12 | 13 | 14 | class Migration(migrations.Migration): 15 | 16 | dependencies = [ 17 | ("engines_manager", "0002_alter_engineconfig_modules"), 18 | ] 19 | 20 | operations = [ 21 | migrations.RunPython(migrate, migrations.RunPython.noop), 22 | ] 23 | -------------------------------------------------------------------------------- /api_app/engines_manager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/engines_manager/migrations/__init__.py -------------------------------------------------------------------------------- /api_app/engines_manager/queryset.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/engines_manager/queryset.py -------------------------------------------------------------------------------- /api_app/engines_manager/signals.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/engines_manager/signals.py -------------------------------------------------------------------------------- /api_app/engines_manager/tasks.py: -------------------------------------------------------------------------------- 1 | from celery import shared_task 2 | from django.utils.module_loading import import_string 3 | 4 | from intel_owl.tasks import FailureLoggedTask 5 | 6 | 7 | @shared_task(base=FailureLoggedTask, soft_time_limit=300) 8 | def execute_engine(job_pk: int): 9 | from api_app.engines_manager.models import EngineConfig 10 | from api_app.models import Job 11 | 12 | job = Job.objects.get(pk=job_pk) 13 | EngineConfig.objects.first().run(job) 14 | 15 | 16 | @shared_task(base=FailureLoggedTask, soft_time_limit=300) 17 | def execute_engine_module(job_pk: int, path: str): 18 | from api_app.engines_manager.classes import EngineModule 19 | from api_app.models import Job 20 | 21 | job = Job.objects.get(pk=job_pk) 22 | obj: EngineModule = import_string(path)(job) 23 | module_result = obj.run() 24 | job.data_model.merge(module_result, append=False) 25 | -------------------------------------------------------------------------------- /api_app/engines_manager/urls.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.urls import include, path 5 | from rest_framework import routers 6 | 7 | from api_app.engines_manager.views import EngineViewSet 8 | 9 | # Routers provide an easy way of automatically determining the URL conf. 10 | 11 | 12 | router = routers.DefaultRouter(trailing_slash=False) 13 | router.register(r"engine", EngineViewSet, basename="engine") 14 | 15 | urlpatterns = [ 16 | # Viewsets 17 | path(r"", include(router.urls)), 18 | ] 19 | -------------------------------------------------------------------------------- /api_app/engines_manager/validators.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.core.exceptions import ValidationError 3 | from django.utils.module_loading import import_string 4 | 5 | 6 | def validate_engine_module(value): 7 | path = f"{settings.BASE_ENGINE_MODULES_PYTHON_PATH}.{value}" 8 | try: 9 | import_string(path) 10 | except ImportError: 11 | raise ValidationError(f"Path {path} does not exist") 12 | -------------------------------------------------------------------------------- /api_app/enums.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/enums.py -------------------------------------------------------------------------------- /api_app/exceptions.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from rest_framework.exceptions import APIException, ValidationError 4 | from rest_framework.request import Request 5 | 6 | from certego_saas.ext.exceptions import custom_exception_handler 7 | 8 | logger = logging.getLogger(__name__) 9 | 10 | 11 | def logging_exception_handler(exc, context): 12 | if isinstance(exc, ValidationError): 13 | request: Request = context["request"] 14 | logger.info( 15 | f"Validation error: {str(exc)} " 16 | f"raised by user:{request.user}" 17 | f" with content:{request.data}" 18 | ) 19 | logger.info(context) 20 | return custom_exception_handler(exc, context) 21 | 22 | 23 | class NotImplementedException(APIException): 24 | status_code = 501 25 | default_detail = "Service not supported." 26 | default_code = "service_not_implemented" 27 | -------------------------------------------------------------------------------- /api_app/fields.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django import forms 5 | from django.contrib.postgres.fields import ArrayField 6 | 7 | 8 | class ChoiceArrayField(ArrayField): 9 | def formfield(self, **kwargs): 10 | defaults = { 11 | "form_class": forms.TypedMultipleChoiceField, 12 | "choices": self.base_field.choices, 13 | "coerce": self.base_field.to_python, 14 | "widget": forms.CheckboxSelectMultiple, 15 | } 16 | defaults.update(kwargs) 17 | # this super call parameter is required 18 | return super(ArrayField, self).formfield(**defaults) 19 | -------------------------------------------------------------------------------- /api_app/fixtures/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/fixtures/__init__.py -------------------------------------------------------------------------------- /api_app/ingestors_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/ingestors_manager/__init__.py -------------------------------------------------------------------------------- /api_app/ingestors_manager/admin.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.contrib import admin 5 | 6 | from api_app.admin import AbstractReportAdminView, PythonConfigAdminView 7 | from api_app.ingestors_manager.models import IngestorConfig, IngestorReport 8 | 9 | 10 | # flake8: noqa 11 | @admin.register(IngestorReport) 12 | class IngestorReportAdminView(AbstractReportAdminView): ... 13 | 14 | 15 | @admin.register(IngestorConfig) 16 | class IngestorConfigAdminView(PythonConfigAdminView): 17 | list_display = ( 18 | "name", 19 | "python_module", 20 | "disabled", 21 | "get_playbooks_choice", 22 | "schedule", 23 | ) 24 | exclude = ["user", "periodic_task"] 25 | 26 | @admin.display(description="Playbooks choice") 27 | def get_playbooks_choice(self, instance: IngestorConfig): 28 | return instance.playbooks_names 29 | -------------------------------------------------------------------------------- /api_app/ingestors_manager/apps.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class IngestorsManagerConfig(AppConfig): 8 | name = "api_app.ingestors_manager" 9 | 10 | @staticmethod 11 | def ready() -> None: 12 | from . import signals # noqa 13 | -------------------------------------------------------------------------------- /api_app/ingestors_manager/exceptions.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | 5 | class NotRunnableIngestor(Exception): 6 | pass 7 | 8 | 9 | class IngestorConfigurationException(Exception): 10 | pass 11 | 12 | 13 | class IngestorRunException(Exception): 14 | pass 15 | -------------------------------------------------------------------------------- /api_app/ingestors_manager/ingestors/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/ingestors_manager/ingestors/__init__.py -------------------------------------------------------------------------------- /api_app/ingestors_manager/migrations/0016_1_change_primary_key.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.8 on 2024-01-09 14:31 2 | from django.db import migrations 3 | 4 | 5 | class Migration(migrations.Migration): 6 | dependencies = [ 7 | ("ingestors_manager", "0002_0000_ingestor_config_threatfox"), 8 | ("playbooks_manager", "0001_initial_squashed"), 9 | ("api_app", "0001_2_initial_squashed"), 10 | ] 11 | 12 | operations = [] 13 | -------------------------------------------------------------------------------- /api_app/ingestors_manager/migrations/0016_2_change_primary_key.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.8 on 2024-01-09 14:31 2 | from django.db import migrations, models 3 | 4 | 5 | class Migration(migrations.Migration): 6 | dependencies = [ 7 | ("ingestors_manager", "0016_1_change_primary_key"), 8 | ] 9 | 10 | operations = [ 11 | migrations.AlterField( 12 | model_name="ingestorreport", 13 | name="config", 14 | field=models.CharField(max_length=100, null=False, blank=False), 15 | ), 16 | ] 17 | -------------------------------------------------------------------------------- /api_app/ingestors_manager/migrations/0017_2_change_primary_key.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.8 on 2024-01-09 14:31 2 | from django.db import migrations, models 3 | 4 | 5 | class Migration(migrations.Migration): 6 | dependencies = [ 7 | ("playbooks_manager", "0024_1_change_primary_key"), 8 | ("ingestors_manager", "0016_4_change_primary_key"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AlterField( 13 | model_name="ingestorconfig", 14 | name="playbook_to_execute", 15 | field=models.CharField(max_length=100, null=True, blank=True), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /api_app/ingestors_manager/migrations/0018_ingestorconfig_delay.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.11 on 2024-04-09 15:19 2 | 3 | import datetime 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | dependencies = [ 10 | ("ingestors_manager", "0017_4_change_primary_key"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name="ingestorconfig", 16 | name="delay", 17 | field=models.DurationField( 18 | default=datetime.timedelta, 19 | help_text="Expects data in the format 'DD HH:MM:SS'", 20 | ), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /api_app/ingestors_manager/migrations/0024_remove_ingestorconfig_playbook_to_execute.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.11 on 2024-07-09 08:22 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ( 9 | "ingestors_manager", 10 | "0023_remove_ingestorconfig_playbook_to_execute_and_more", 11 | ), 12 | ] 13 | 14 | operations = [ 15 | migrations.RemoveField( 16 | model_name="ingestorconfig", 17 | name="playbook_to_execute", 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /api_app/ingestors_manager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/ingestors_manager/migrations/__init__.py -------------------------------------------------------------------------------- /api_app/ingestors_manager/urls.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.urls import include, path 5 | from rest_framework import routers 6 | 7 | # Routers provide an easy way of automatically determining the URL conf. 8 | from api_app.ingestors_manager.views import ( 9 | IngestorConfigViewSet, 10 | IngestorPluginConfigViewSet, 11 | ) 12 | 13 | router = routers.DefaultRouter(trailing_slash=False) 14 | router.register(r"ingestor", IngestorConfigViewSet, basename="ingestor") 15 | router.register( 16 | r"ingestor/(?P\w+)", 17 | IngestorPluginConfigViewSet, 18 | basename="plugin-config-ingestor", 19 | ) 20 | 21 | urlpatterns = [ 22 | # Viewsets 23 | path(r"", include(router.urls)), 24 | ] 25 | -------------------------------------------------------------------------------- /api_app/investigations_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/investigations_manager/__init__.py -------------------------------------------------------------------------------- /api_app/investigations_manager/apps.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class InvestigationManagerConfig(AppConfig): 8 | name = "api_app.investigations_manager" 9 | 10 | @staticmethod 11 | def ready() -> None: 12 | from . import signals # noqa 13 | -------------------------------------------------------------------------------- /api_app/investigations_manager/choices.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | 4 | class InvestigationStatusChoices(models.TextChoices): 5 | CREATED = "created" 6 | RUNNING = "running" 7 | CONCLUDED = "concluded" 8 | -------------------------------------------------------------------------------- /api_app/investigations_manager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/investigations_manager/migrations/__init__.py -------------------------------------------------------------------------------- /api_app/investigations_manager/queryset.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from api_app.queryset import CleanOnCreateQuerySet, ModelWithOwnershipQuerySet 3 | 4 | 5 | class InvestigationQuerySet(CleanOnCreateQuerySet, ModelWithOwnershipQuerySet): ... 6 | -------------------------------------------------------------------------------- /api_app/investigations_manager/signals.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/investigations_manager/signals.py -------------------------------------------------------------------------------- /api_app/investigations_manager/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import include, path 2 | from rest_framework import routers 3 | 4 | from .views import InvestigationViewSet 5 | 6 | router = routers.DefaultRouter(trailing_slash=False) 7 | router.register(r"investigation", InvestigationViewSet, basename="investigation") 8 | 9 | urlpatterns = [ 10 | path(r"", include(router.urls)), 11 | ] 12 | -------------------------------------------------------------------------------- /api_app/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/management/__init__.py -------------------------------------------------------------------------------- /api_app/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/management/commands/__init__.py -------------------------------------------------------------------------------- /api_app/management/commands/migrate.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import no_translations 2 | from django.core.management.commands.migrate import Command as MigrateCommand 3 | 4 | 5 | class Command(MigrateCommand): 6 | @no_translations 7 | def handle(self, *args, **options): 8 | super().handle(*args, **options) 9 | from api_app.signals import migrate_finished 10 | 11 | migrate_finished.send(self, **options) 12 | -------------------------------------------------------------------------------- /api_app/migrations/0056_alter_organizationpluginconfiguration_content_type.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.8 on 2024-01-09 13:32 2 | 3 | import django.db.models.deletion 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | dependencies = [ 9 | ("contenttypes", "0002_remove_content_type_name"), 10 | ("api_app", "0055_organizationpluginconfiguration_and_more"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name="organizationpluginconfiguration", 16 | name="content_type", 17 | field=models.ForeignKey( 18 | limit_choices_to={ 19 | "model__endswith": "config", 20 | "app_label__endswith": "manager", 21 | }, 22 | on_delete=django.db.models.deletion.CASCADE, 23 | to="contenttypes.contenttype", 24 | ), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /api_app/migrations/0058_2_change_primary_key.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.8 on 2024-01-09 14:31 2 | from django.db import migrations, models 3 | 4 | 5 | class Migration(migrations.Migration): 6 | dependencies = [ 7 | ("playbooks_manager", "0024_1_change_primary_key"), 8 | ("api_app", "0057_4_change_primary_key"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AlterField( 13 | model_name="job", 14 | name="playbook_requested", 15 | field=models.CharField(max_length=100, null=True, blank=True), 16 | ), 17 | migrations.AlterField( 18 | model_name="job", 19 | name="playbook_to_execute", 20 | field=models.CharField(max_length=100, null=True, blank=True), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /api_app/migrations/0059_alter_organizationpluginconfiguration_unique_together.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.8 on 2024-01-19 08:58 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("certego_saas_organization", "0002_membership_is_admin"), 9 | ("contenttypes", "0002_remove_content_type_name"), 10 | ("api_app", "0058_4_change_primary_key"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterUniqueTogether( 15 | name="organizationpluginconfiguration", 16 | unique_together={("object_id", "organization", "content_type")}, 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /api_app/migrations/0062_alter_parameter_python_module.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.11 on 2024-03-28 11:41 2 | 3 | import django.db.models.deletion 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | dependencies = [ 9 | ("api_app", "0061_job_depth_analysis"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name="parameter", 15 | name="python_module", 16 | field=models.ForeignKey( 17 | on_delete=django.db.models.deletion.CASCADE, 18 | related_name="parameters", 19 | to="api_app.pythonmodule", 20 | ), 21 | ), 22 | migrations.AlterField( 23 | model_name="job", 24 | name="path", 25 | field=models.CharField(max_length=255, unique=True), 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /api_app/migrations/0065_job_mpnodesearch.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.16 on 2024-12-17 11:04 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("api_app", "0064_vt_sample_download"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddIndex( 14 | model_name="job", 15 | index=models.Index(fields=["depth", "path", "id"], name="MPNodeSearch"), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /api_app/migrations/0067_add_analyzable.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.17 on 2025-01-22 08:59 2 | 3 | import django.db.models.deletion 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ("contenttypes", "0002_remove_content_type_name"), 11 | ("api_app", "0066_remove_lastelasticreportupdate_singleton_and_more"), 12 | ("analyzables_manager", "0001_initial"), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name="job", 18 | name="analyzable", 19 | field=models.ForeignKey( 20 | blank=True, 21 | editable=False, 22 | null=True, 23 | on_delete=django.db.models.deletion.CASCADE, 24 | related_name="jobs", 25 | to="analyzables_manager.analyzable", 26 | ), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /api_app/migrations/0071_delete_last_elastic_report.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.17 on 2025-02-19 09:17 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("api_app", "0070_remove_comment_job_comment_analyzable"), 10 | ] 11 | 12 | operations = [ 13 | migrations.DeleteModel( 14 | name="LastElasticReportUpdate", 15 | ), 16 | ] 17 | -------------------------------------------------------------------------------- /api_app/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/migrations/__init__.py -------------------------------------------------------------------------------- /api_app/pivots_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/pivots_manager/__init__.py -------------------------------------------------------------------------------- /api_app/pivots_manager/apps.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class PivotsManagerConfig(AppConfig): 8 | name = "api_app.pivots_manager" 9 | 10 | @staticmethod 11 | def ready() -> None: 12 | from . import signals # noqa 13 | -------------------------------------------------------------------------------- /api_app/pivots_manager/exceptions.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | 5 | class NotRunnablePivot(Exception): 6 | pass 7 | 8 | 9 | class PivotConfigurationException(Exception): 10 | pass 11 | 12 | 13 | class PivotRunException(Exception): 14 | pass 15 | 16 | 17 | class PivotFieldNotFoundException(Exception): 18 | pass 19 | -------------------------------------------------------------------------------- /api_app/pivots_manager/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from api_app.pivots_manager.models import PivotConfig 4 | 5 | 6 | class PivotConfigAdminForm(forms.ModelForm): 7 | description = forms.CharField( 8 | disabled=True, 9 | required=False, 10 | initial="", 11 | widget=forms.Textarea(), 12 | ) 13 | 14 | class Meta: 15 | model = PivotConfig 16 | fields = [ 17 | "name", 18 | "description", 19 | "routing_key", 20 | "soft_time_limit", 21 | "disabled", 22 | "python_module", 23 | "related_analyzer_configs", 24 | "related_connector_configs", 25 | "playbooks_choice", 26 | ] 27 | -------------------------------------------------------------------------------- /api_app/pivots_manager/migrations/0025_alter_pivotmap_ending_job.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.8 on 2024-02-01 16:04 2 | 3 | import django.db.models.deletion 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | dependencies = [ 9 | ("api_app", "0058_4_change_primary_key"), 10 | ("pivots_manager", "0024_4_change_primary_key"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name="pivotmap", 16 | name="ending_job", 17 | field=models.OneToOneField( 18 | editable=False, 19 | on_delete=django.db.models.deletion.CASCADE, 20 | related_name="pivot_parent", 21 | to="api_app.job", 22 | ), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /api_app/pivots_manager/migrations/0030_pivot_config_delay.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.11 on 2024-04-09 15:19 2 | 3 | import datetime 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | dependencies = [ 10 | ("pivots_manager", "0029_pivot_config_downloadfilefromuri"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name="pivotconfig", 16 | name="delay", 17 | field=models.DurationField( 18 | default=datetime.timedelta, 19 | help_text="Expects data in the format 'DD HH:MM:SS'", 20 | ), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /api_app/pivots_manager/migrations/0032_remove_pivotconfig_playbook_to_execute.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.11 on 2024-07-09 08:22 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("pivots_manager", "0031_remove_pivotconfig_playbook_to_execute_and_more"), 9 | ] 10 | 11 | operations = [ 12 | migrations.RemoveField( 13 | model_name="pivotconfig", 14 | name="playbook_to_execute", 15 | ), 16 | ] 17 | -------------------------------------------------------------------------------- /api_app/pivots_manager/migrations/0034_changed_resubmitdownloadedfile_playbook_to_execute.py: -------------------------------------------------------------------------------- 1 | from django.db import migrations 2 | 3 | 4 | def migrate(apps, schema_editor): 5 | PivotConfig = apps.get_model("pivots_manager", "PivotConfig") 6 | 7 | pc = PivotConfig.objects.get( 8 | name="ResubmitDownloadedFile", 9 | ) 10 | pc.playbook_to_execute = "Sample_Static_Analysis" 11 | pc.save() 12 | 13 | 14 | def reverse_migrate(apps, schema_editor): 15 | pass 16 | 17 | 18 | class Migration(migrations.Migration): 19 | dependencies = [ 20 | ("api_app", "0062_alter_parameter_python_module"), 21 | ("pivots_manager", "0033_pivot_config_extractedonenotefiles"), 22 | ] 23 | operations = [ 24 | migrations.RunPython(migrate, reverse_migrate), 25 | ] 26 | -------------------------------------------------------------------------------- /api_app/pivots_manager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/pivots_manager/migrations/__init__.py -------------------------------------------------------------------------------- /api_app/pivots_manager/permissions.py: -------------------------------------------------------------------------------- 1 | from rest_framework.permissions import BasePermission 2 | 3 | 4 | class PivotOwnerPermission(BasePermission): 5 | @staticmethod 6 | def has_object_permission(request, view, obj): 7 | return ( 8 | obj.starting_job.user.pk == request.user.pk 9 | and obj.ending_job.user.pk == request.user.pk 10 | ) 11 | 12 | 13 | class PivotActionsPermission(BasePermission): 14 | @staticmethod 15 | def has_object_permission(request, view, obj): 16 | # only an admin or superuser can update or delete pivots 17 | if request.user.has_membership(): 18 | return request.user.membership.is_admin 19 | else: 20 | return request.user.is_superuser 21 | -------------------------------------------------------------------------------- /api_app/pivots_manager/pivots/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/pivots_manager/pivots/__init__.py -------------------------------------------------------------------------------- /api_app/pivots_manager/pivots/any_compare.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from typing import Optional, Tuple 3 | 4 | from api_app.pivots_manager.pivots.compare import Compare 5 | 6 | logger = logging.getLogger(__name__) 7 | 8 | 9 | class AnyCompare(Compare): 10 | def should_run(self) -> Tuple[bool, Optional[str]]: 11 | for report in self.related_reports.filter( 12 | status=self.report_model.STATUSES.SUCCESS.value 13 | ): 14 | try: 15 | self._value = report.get_value( 16 | report.report, self.field_to_compare.split(".") 17 | ) 18 | except (RuntimeError, ValueError): 19 | continue 20 | else: 21 | return True, "Key found with success" 22 | 23 | return ( 24 | False, 25 | f"Field {self.field_to_compare} not found in success reports", 26 | ) 27 | 28 | def update(self) -> bool: 29 | pass 30 | -------------------------------------------------------------------------------- /api_app/pivots_manager/pivots/load_file.py: -------------------------------------------------------------------------------- 1 | import base64 2 | from typing import Any, List 3 | 4 | from api_app.pivots_manager.pivots.compare import Compare 5 | 6 | 7 | class LoadFile(Compare): 8 | field_to_compare: str 9 | 10 | @classmethod 11 | def update(cls) -> bool: 12 | pass 13 | 14 | def get_value_to_pivot_to(self) -> Any: 15 | if isinstance(self._value, List): 16 | for v in self._value: 17 | if isinstance(v, (bytes, bytearray, str)): 18 | yield base64.b64decode(v) 19 | else: 20 | raise ValueError("Invalid data type to base64 decode") 21 | elif isinstance(self._value, (bytes, bytearray, str)): 22 | yield base64.b64decode(self._value) 23 | else: 24 | raise ValueError("Invalid data type to base64 decode") 25 | -------------------------------------------------------------------------------- /api_app/pivots_manager/pivots/load_file_same_playbook.py: -------------------------------------------------------------------------------- 1 | from api_app.pivots_manager.models import PivotConfig 2 | from api_app.pivots_manager.pivots.load_file import LoadFile 3 | 4 | 5 | class LoadFileSamePlaybook(LoadFile): 6 | field_to_compare: str 7 | 8 | @classmethod 9 | def update(cls) -> bool: 10 | pass 11 | 12 | def get_playbook_to_execute(self): 13 | self._config: PivotConfig 14 | # use the same playbook of the parent when resubmit a file 15 | return self._job.get_root().playbook_to_execute 16 | -------------------------------------------------------------------------------- /api_app/pivots_manager/urls.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.urls import include, path 5 | from rest_framework import routers 6 | 7 | # Routers provide an easy way of automatically determining the URL conf. 8 | from api_app.pivots_manager.views import ( 9 | PivotConfigViewSet, 10 | PivotMapViewSet, 11 | PivotPluginConfigViewSet, 12 | ) 13 | 14 | router = routers.DefaultRouter(trailing_slash=False) 15 | router.register(r"pivot", PivotConfigViewSet, basename="pivot") 16 | router.register(r"pivot_map", PivotMapViewSet, basename="pivot_map") 17 | router.register( 18 | r"pivot/(?P\w+)", PivotPluginConfigViewSet, basename="plugin-config-pivot" 19 | ) 20 | 21 | urlpatterns = [ 22 | path(r"", include(router.urls)), 23 | ] 24 | -------------------------------------------------------------------------------- /api_app/pivots_manager/validators.py: -------------------------------------------------------------------------------- 1 | from django.core.validators import RegexValidator 2 | 3 | pivot_regex_validator = RegexValidator( 4 | r"^\w+(\.\w+)*$", message="Object should be a python path" 5 | ) 6 | -------------------------------------------------------------------------------- /api_app/playbooks_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/playbooks_manager/__init__.py -------------------------------------------------------------------------------- /api_app/playbooks_manager/apps.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class PlaybooksManagerConfig(AppConfig): 8 | name = "api_app.playbooks_manager" 9 | 10 | @staticmethod 11 | def ready() -> None: 12 | from . import signals # noqa 13 | -------------------------------------------------------------------------------- /api_app/playbooks_manager/fields.py: -------------------------------------------------------------------------------- 1 | from django.utils.duration import _get_duration_components 2 | from rest_framework.fields import DurationField 3 | 4 | 5 | def duration_string(duration): 6 | """Version of str(timedelta) which is not English specific.""" 7 | days, hours, minutes, seconds, microseconds = _get_duration_components(duration) 8 | 9 | string = "{}:{:02d}:{:02d}:{:02d}".format(days, hours, minutes, seconds) 10 | if microseconds: 11 | string += ".{:06d}".format(microseconds) 12 | 13 | return string 14 | 15 | 16 | class DayDurationField(DurationField): 17 | @staticmethod 18 | def to_representation(value): 19 | return duration_string(value) 20 | -------------------------------------------------------------------------------- /api_app/playbooks_manager/migrations/0037_playbookconfig_starting.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.11 on 2024-05-07 13:54 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("playbooks_manager", "0036_static_analyzer_remove_visualizer"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name="playbookconfig", 14 | name="starting", 15 | field=models.BooleanField( 16 | default=True, 17 | help_text="If False, the playbook can only be executed by pivots", 18 | ), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /api_app/playbooks_manager/migrations/0038_playbooks_not_starting.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.11 on 2024-05-07 13:54 2 | 3 | from django.db import migrations 4 | 5 | playbooks_to_change = ["Abuse_IP"] 6 | 7 | 8 | def migrate(apps, schema_editor): 9 | PlaybookConfig = apps.get_model("playbooks_manager", "PlaybookConfig") 10 | for pc in PlaybookConfig.objects.filter(name__in=playbooks_to_change): 11 | pc.starting = False 12 | pc.save() 13 | 14 | 15 | def reverse_migrate(apps, schema_editor): 16 | PlaybookConfig = apps.get_model("playbooks_manager", "PlaybookConfig") 17 | for pc in PlaybookConfig.objects.filter(name__in=playbooks_to_change): 18 | pc.starting = True 19 | pc.save() 20 | 21 | 22 | class Migration(migrations.Migration): 23 | dependencies = [ 24 | ("playbooks_manager", "0037_playbookconfig_starting"), 25 | ] 26 | 27 | operations = [ 28 | migrations.RunPython(migrate, reverse_migrate), 29 | ] 30 | -------------------------------------------------------------------------------- /api_app/playbooks_manager/migrations/0057_alter_phishing_extractor_add_domain.py: -------------------------------------------------------------------------------- 1 | from django.db import migrations 2 | 3 | 4 | def migrate(apps, schema_editor): 5 | PlaybookConfig = apps.get_model("playbooks_manager", "PlaybookConfig") 6 | config = PlaybookConfig.objects.get(name="PhishingExtractor") 7 | config.type = [ 8 | "url", 9 | "domain", 10 | ] 11 | config.full_clean() 12 | config.save() 13 | 14 | 15 | def reverse_migrate(apps, schema_editor): 16 | PlaybookConfig = apps.get_model("playbooks_manager", "PlaybookConfig") 17 | config = PlaybookConfig.objects.get(name="PhishingExtractor") 18 | config.type = [ 19 | "url", 20 | ] 21 | config.full_clean() 22 | config.save() 23 | 24 | 25 | class Migration(migrations.Migration): 26 | dependencies = [ 27 | ("playbooks_manager", "0056_download_sample_vt"), 28 | ] 29 | 30 | operations = [migrations.RunPython(migrate, reverse_migrate)] 31 | -------------------------------------------------------------------------------- /api_app/playbooks_manager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/playbooks_manager/migrations/__init__.py -------------------------------------------------------------------------------- /api_app/playbooks_manager/urls.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.urls import include, path 5 | from rest_framework import routers 6 | 7 | from .views import PlaybookConfigViewSet 8 | 9 | router = routers.DefaultRouter(trailing_slash=False) 10 | router.register(r"playbook", PlaybookConfigViewSet, basename="playbook") 11 | 12 | urlpatterns = [ 13 | path(r"", include(router.urls)), 14 | ] 15 | -------------------------------------------------------------------------------- /api_app/serializers/celery.py: -------------------------------------------------------------------------------- 1 | from django_celery_beat.models import CrontabSchedule, PeriodicTask 2 | from rest_framework import serializers as rfs 3 | 4 | 5 | class CrontabScheduleSerializer(rfs.ModelSerializer): 6 | class Meta: 7 | model = CrontabSchedule 8 | fields = [ 9 | "minute", 10 | "hour", 11 | "day_of_week", 12 | "day_of_month", 13 | "month_of_year", 14 | ] 15 | 16 | 17 | class PeriodicTaskSerializer(rfs.ModelSerializer): 18 | crontab = CrontabScheduleSerializer(read_only=True) 19 | 20 | class Meta: 21 | model = PeriodicTask 22 | fields = [ 23 | "crontab", 24 | "name", 25 | "task", 26 | "kwargs", 27 | "queue", 28 | "enabled", 29 | ] 30 | -------------------------------------------------------------------------------- /api_app/serializers/test.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/serializers/test.py -------------------------------------------------------------------------------- /api_app/user_events_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/user_events_manager/__init__.py -------------------------------------------------------------------------------- /api_app/user_events_manager/apps.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class UserEventsManagerConfig(AppConfig): 8 | name = "api_app.user_events_manager" 9 | 10 | @staticmethod 11 | def ready(**kwargs) -> None: 12 | from . import signals # noqa 13 | -------------------------------------------------------------------------------- /api_app/user_events_manager/choices.py: -------------------------------------------------------------------------------- 1 | from django.db.models import IntegerChoices 2 | 3 | 4 | class DecayProgressionEnum(IntegerChoices): 5 | LINEAR = 0 # 10 -> N days -> 9 -> N days -> 8 6 | INVERSE_EXPONENTIAL = 1 # 10 -> N days -> 9 -> N*N days -> 8 7 | FIXED = 2 # 10 -> N days -> 10 -> N days -> 10 8 | -------------------------------------------------------------------------------- /api_app/user_events_manager/migrations/0002_alter_userdomainwildcardevent_query.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.17 on 2025-02-27 14:47 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("user_events_manager", "0001_initial"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name="userdomainwildcardevent", 15 | name="query", 16 | field=models.CharField( 17 | editable=False, 18 | help_text="This use classic regex syntax", 19 | max_length=100, 20 | ), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /api_app/user_events_manager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/user_events_manager/migrations/__init__.py -------------------------------------------------------------------------------- /api_app/user_events_manager/signals.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.dispatch import receiver 3 | 4 | from .models import UserAnalyzableEvent, UserDomainWildCardEvent, UserIPWildCardEvent 5 | 6 | 7 | @receiver(models.signals.post_delete, sender=UserDomainWildCardEvent) 8 | @receiver(models.signals.post_delete, sender=UserIPWildCardEvent) 9 | @receiver(models.signals.post_delete, sender=UserAnalyzableEvent) 10 | def post_delete_event_delete_data_model( 11 | sender, instance: UserDomainWildCardEvent, **kwargs 12 | ): 13 | instance.data_model.delete() 14 | -------------------------------------------------------------------------------- /api_app/user_events_manager/tasks.py: -------------------------------------------------------------------------------- 1 | from celery import shared_task 2 | 3 | from api_app.user_events_manager.models import ( 4 | UserAnalyzableEvent, 5 | UserDomainWildCardEvent, 6 | UserIPWildCardEvent, 7 | ) 8 | from intel_owl.tasks import FailureLoggedTask 9 | 10 | 11 | @shared_task(base=FailureLoggedTask, soft_time_limit=300) 12 | def user_events_decay(): 13 | UserAnalyzableEvent.objects.decay() 14 | UserDomainWildCardEvent.objects.decay() 15 | UserIPWildCardEvent.objects.decay() 16 | -------------------------------------------------------------------------------- /api_app/user_events_manager/validators.py: -------------------------------------------------------------------------------- 1 | import ipaddress 2 | 3 | from django.core.exceptions import ValidationError 4 | 5 | 6 | def validate_ipv4_network(value): 7 | try: 8 | ipaddress.IPv4Network(value) 9 | except ValueError: 10 | raise ValidationError( 11 | "Enter a valid IPv4 network.", code="invalid", params={"value": value} 12 | ) 13 | -------------------------------------------------------------------------------- /api_app/visualizers_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/visualizers_manager/__init__.py -------------------------------------------------------------------------------- /api_app/visualizers_manager/admin.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.contrib import admin 5 | 6 | from api_app.admin import AbstractReportAdminView, PythonConfigAdminView 7 | from api_app.visualizers_manager.models import VisualizerConfig, VisualizerReport 8 | 9 | 10 | # flake8: noqa 11 | @admin.register(VisualizerReport) 12 | class VisualizerReportAdminView(AbstractReportAdminView): ... 13 | 14 | 15 | @admin.register(VisualizerConfig) 16 | class VisualizerConfigAdminView(PythonConfigAdminView): 17 | list_display = PythonConfigAdminView.list_display + ("get_playbooks",) 18 | 19 | @admin.display(description="Playbooks") 20 | def get_playbooks(self, instance: VisualizerConfig): 21 | return list(instance.playbooks.values_list("name", flat=True)) 22 | -------------------------------------------------------------------------------- /api_app/visualizers_manager/apps.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class VisualizersManagerConfig(AppConfig): 8 | name = "api_app.visualizers_manager" 9 | 10 | @staticmethod 11 | def ready() -> None: 12 | from . import signals # noqa 13 | -------------------------------------------------------------------------------- /api_app/visualizers_manager/choices.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | 4 | class Position(models.TextChoices): 5 | LEFT = "left" 6 | CENTER = "center" 7 | RIGHT = "right" 8 | -------------------------------------------------------------------------------- /api_app/visualizers_manager/exceptions.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | 5 | class NotRunnableVisualizer(Exception): 6 | pass 7 | 8 | 9 | class VisualizerConfigurationException(Exception): 10 | pass 11 | 12 | 13 | class VisualizerRunException(Exception): 14 | pass 15 | -------------------------------------------------------------------------------- /api_app/visualizers_manager/forms.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/visualizers_manager/forms.py -------------------------------------------------------------------------------- /api_app/visualizers_manager/migrations/0036_1_change_primary_key.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.8 on 2024-01-09 14:31 2 | from django.db import migrations 3 | 4 | 5 | class Migration(migrations.Migration): 6 | dependencies = [ 7 | ("visualizers_manager", "0002_0004_visualizer_config_yara"), 8 | ("api_app", "0001_2_initial_squashed"), 9 | ] 10 | 11 | operations = [] 12 | -------------------------------------------------------------------------------- /api_app/visualizers_manager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/visualizers_manager/migrations/__init__.py -------------------------------------------------------------------------------- /api_app/visualizers_manager/queryset.py: -------------------------------------------------------------------------------- 1 | from typing import TYPE_CHECKING, Type 2 | 3 | from api_app.queryset import AbstractReportQuerySet 4 | 5 | if TYPE_CHECKING: 6 | from api_app.visualizers_manager.serializers import VisualizerReportBISerializer 7 | 8 | 9 | class VisualizerReportQuerySet(AbstractReportQuerySet): 10 | @classmethod 11 | def _get_bi_serializer_class(cls) -> Type["VisualizerReportBISerializer"]: 12 | from api_app.visualizers_manager.serializers import VisualizerReportBISerializer 13 | 14 | return VisualizerReportBISerializer 15 | -------------------------------------------------------------------------------- /api_app/visualizers_manager/signals.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import uuid 3 | 4 | from django.conf import settings 5 | from django.dispatch import receiver 6 | 7 | from api_app.signals import migrate_finished 8 | from api_app.visualizers_manager.models import VisualizerConfig 9 | from intel_owl.celery import get_queue_name 10 | 11 | logger = logging.getLogger(__name__) 12 | 13 | 14 | @receiver(migrate_finished) 15 | def post_migrate_visualizers_manager( 16 | sender, 17 | *args, 18 | check_unapplied: bool = False, 19 | **kwargs, 20 | ): 21 | logger.info(f"Post migrate {args} {kwargs}") 22 | if check_unapplied: 23 | return 24 | from intel_owl.tasks import refresh_cache 25 | 26 | refresh_cache.apply_async( 27 | queue=get_queue_name(settings.CONFIG_QUEUE), 28 | MessageGroupId=str(uuid.uuid4()), 29 | priority=3, 30 | args=[VisualizerConfig.python_path], 31 | ) 32 | -------------------------------------------------------------------------------- /api_app/visualizers_manager/visualizers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/api_app/visualizers_manager/visualizers/__init__.py -------------------------------------------------------------------------------- /authentication/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/authentication/__init__.py -------------------------------------------------------------------------------- /authentication/apps.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class ApiAppAuthConfig(AppConfig): 8 | name = "authentication" 9 | 10 | @staticmethod 11 | def ready() -> None: 12 | from . import signals # noqa 13 | -------------------------------------------------------------------------------- /authentication/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/authentication/migrations/__init__.py -------------------------------------------------------------------------------- /authentication/oauth.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | """This module configures OAuth authentication for the IntelOwl project using the Authlib library. 5 | It sets up OAuth for Google if it is specified in the Django settings. 6 | """ 7 | 8 | from authlib.integrations.django_client import OAuth 9 | from django.conf import settings 10 | 11 | oauth = OAuth() 12 | if "google" in settings.AUTHLIB_OAUTH_CLIENTS: 13 | GOOGLE_CONF_URL = "https://accounts.google.com/.well-known/openid-configuration" 14 | oauth.register( 15 | name="google", 16 | server_metadata_url=GOOGLE_CONF_URL, 17 | client_kwargs={"scope": "openid email profile"}, 18 | ) 19 | -------------------------------------------------------------------------------- /authentication/templates/authentication/emails/account-activated.html: -------------------------------------------------------------------------------- 1 | {% extends "./base.html" %} 2 | 3 | {% block content %} 4 |
5 | Hello, {{ full_name }}! 6 | 7 |

8 |

You've got access! 🎉

9 |

10 | 11 |

12 | Your account @{{ username }} has been verified by us and you 13 | can now 14 | login 15 | to and use {{ host_name }}. 16 |

17 |
18 | {% endblock %} -------------------------------------------------------------------------------- /authentication/templates/authentication/emails/account-declined.html: -------------------------------------------------------------------------------- 1 | {% extends "./base.html" %} {% block content %} 2 |
3 | Hello, {{ full_name }}! 4 | 5 |

6 | We regret to inform you that your account request (@{{ username }}) on {{ host_name }} has been declined. You can sign up again with a 9 | business email address and not a personal one to increase your chances of 10 | getting access. 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /authentication/templates/authentication/emails/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 |
5 | IntelOwl: logo 11 |
12 |
13 | 14 |
{% block content %} {% endblock %} 15 |

16 | Note: If you believe you received this email in error, please contact us at 17 | {{ default_email }}. 18 |

19 |
20 | 21 |
22 |
23 | Thank you, 24 |
25 | IntelOwl © 26 |
27 | 28 | -------------------------------------------------------------------------------- /authentication/templates/authentication/emails/duplicate-email.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 |
5 |
6 | Dear IntelOwl user, 7 | 8 |

9 | As part of our commitment to keep IntelOwl and its users secure, we notify 10 | you that someone just attempted to register with this email address. 11 |

12 |
13 |
14 | 15 |
16 |
17 | Thank you, 18 |
19 | IntelOwl © 20 |
21 | -------------------------------------------------------------------------------- /authentication/templates/authentication/emails/verify-email.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 |
5 |
6 | Hello! 7 | 8 |

9 | Please click the link below to verify your email address. 10 |

11 | 12 | 15 | 16 |

or, you may also copy and paste directly into your browser's URL bar.

17 | 18 |
{{ verification_url }}
19 | 20 |

21 | Note: This URL is valid only for the next 24 hours. 22 |

23 | 24 |
25 |
26 | 27 |
28 |
29 | Thank you, 30 |
31 | IntelOwl © 32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /configuration/cyberchef_recipes.json: -------------------------------------------------------------------------------- 1 | { 2 | "to decimal": [ 3 | { 4 | "op": "To Decimal", 5 | "args": [ 6 | "Space", false 7 | ] 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /configuration/intel_owl.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | project = intel_owl 3 | base = /opt/deploy/intel_owl 4 | 5 | chdir = %(base) 6 | module = %(project).wsgi:application 7 | 8 | master = true 9 | processes = 12 10 | enable-threads = true 11 | 12 | socket = 0.0.0.0:8001 13 | chown = www-data:www-data 14 | vacuum = true 15 | single-interpreter = true 16 | harakiri = 300 17 | 18 | logto = /var/log/intel_owl/uwsgi/intel_owl.log 19 | uid = www-data 20 | gid = www-data 21 | 22 | max-requests = 1000 23 | max-worker-lifetime = 3600 24 | reload-on-rss = 2048 25 | worker-reload-mercy = 3600 26 | 27 | buffer-size = 32768 28 | 29 | need-app = true -------------------------------------------------------------------------------- /configuration/nginx/django_server.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | 4 | server_name intel_owl.honeynet.org; 5 | 6 | charset utf-8; 7 | 8 | location = /favicon.ico { 9 | access_log off; 10 | log_not_found off; 11 | } 12 | 13 | # All requests to the Django/UWSGI server. 14 | location / { 15 | proxy_set_header X-Forwarded-Proto https; 16 | proxy_set_header X-Url-Scheme $scheme; 17 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 18 | proxy_set_header Host $http_host; 19 | proxy_redirect off; 20 | proxy_pass http://uwsgi:8001; 21 | client_max_body_size 100m; 22 | } 23 | 24 | # Websocket 25 | include websocket.conf; 26 | 27 | # Error pages 28 | include errors.conf; 29 | } 30 | -------------------------------------------------------------------------------- /configuration/nginx/flower_http.conf: -------------------------------------------------------------------------------- 1 | # flower 2 | server { 3 | listen 5555; 4 | 5 | server_name intel_owl.honeynet.org; 6 | 7 | server_tokens off; 8 | 9 | charset utf-8; 10 | location / { 11 | proxy_pass http://flower:5555; 12 | proxy_set_header Host $host; 13 | proxy_redirect off; 14 | proxy_http_version 1.1; 15 | proxy_set_header Upgrade $http_upgrade; 16 | proxy_set_header Connection "upgrade"; 17 | auth_basic "Restricted"; 18 | auth_basic_user_file /etc/nginx/shared/.htpasswd; 19 | } 20 | } -------------------------------------------------------------------------------- /configuration/nginx/flower_https.conf: -------------------------------------------------------------------------------- 1 | # flower 2 | server { 3 | listen 5555 ssl; 4 | ssl on; 5 | ssl_protocols TLSv1.2; 6 | ssl_certificate certificate_chain.chain.crt; 7 | ssl_certificate_key private_key.key; 8 | 9 | server_name intel_owl.honeynet.org; 10 | 11 | server_tokens off; 12 | 13 | charset utf-8; 14 | location / { 15 | proxy_pass http://flower:5555; 16 | proxy_set_header Host $host; 17 | proxy_redirect off; 18 | proxy_http_version 1.1; 19 | proxy_set_header Upgrade $http_upgrade; 20 | proxy_set_header Connection "upgrade"; 21 | auth_basic "Restricted"; 22 | auth_basic_user_file /etc/nginx/shared/.htpasswd; 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /configuration/nginx/http.conf: -------------------------------------------------------------------------------- 1 | # the upstream component nginx needs to connect to 2 | upstream django { 3 | server uwsgi:8001 fail_timeout=30s; 4 | } 5 | 6 | limit_req_zone $binary_remote_addr zone=adminlimit:10m rate=1r/s; 7 | 8 | server { 9 | listen 80; 10 | server_name intelowl.honeynet.org; 11 | 12 | server_tokens off; 13 | 14 | # Locations 15 | include locations.conf; 16 | 17 | # Error pages 18 | include errors.conf; 19 | } 20 | -------------------------------------------------------------------------------- /configuration/nginx/https.conf: -------------------------------------------------------------------------------- 1 | # the upstream component nginx needs to connect to 2 | upstream django { 3 | server uwsgi:8001 fail_timeout=30s; 4 | } 5 | 6 | server { 7 | listen 80; 8 | server_name intelowl.honeynet.org; 9 | return 301 https://intelowl.honeynet.org$request_uri; 10 | } 11 | 12 | limit_req_zone $binary_remote_addr zone=adminlimit:10m rate=1r/s; 13 | 14 | server { 15 | listen 443 ssl; 16 | 17 | ssl_protocols TLSv1.2 TLSv1.3; 18 | ssl_certificate /usr/local/share/ca-certificates/intelowl.crt; 19 | ssl_certificate_key /etc/ssl/private/intelowl.key; 20 | #ssl_password_file /etc/ssl/private/ssl_passwords.txt; 21 | 22 | server_name intelowl.honeynet.org; 23 | 24 | server_tokens off; 25 | 26 | # Locations 27 | include locations.conf; 28 | 29 | # Error pages 30 | include errors.conf; 31 | } 32 | -------------------------------------------------------------------------------- /configuration/nginx/locations.conf: -------------------------------------------------------------------------------- 1 | location = /favicon.ico { 2 | access_log off; 3 | log_not_found off; 4 | } 5 | 6 | location /hc { 7 | return 200; 8 | } 9 | 10 | # All requests to the Django/UWSGI server. 11 | location / { 12 | root /; 13 | uwsgi_pass django; 14 | uwsgi_pass_header Authorization; 15 | uwsgi_pass_request_headers on; 16 | uwsgi_read_timeout 600; 17 | include uwsgi_params; 18 | client_max_body_size 100m; 19 | } 20 | 21 | 22 | # rate limiting for django admin panel 23 | location ^~/admin { 24 | limit_req zone=adminlimit; 25 | 26 | uwsgi_pass django; 27 | uwsgi_pass_header Authorization; 28 | uwsgi_pass_request_headers on; 29 | uwsgi_read_timeout 600; 30 | include uwsgi_params; 31 | client_max_body_size 100m; 32 | } 33 | 34 | # Websocket 35 | include websocket.conf; 36 | -------------------------------------------------------------------------------- /configuration/nginx/websocket.conf: -------------------------------------------------------------------------------- 1 | location /ws { 2 | proxy_pass http://daphne:8011; 3 | proxy_http_version 1.1; 4 | proxy_set_header Upgrade $http_upgrade; 5 | proxy_set_header Connection "Upgrade"; 6 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 7 | # timeout on connect should be fine with default value: 8 | # comment the config in case errors will rise and could be related to this config 9 | # proxy_connect_timeout 86400; 10 | proxy_read_timeout 86400; 11 | proxy_send_timeout 86400; 12 | } -------------------------------------------------------------------------------- /configuration/rabbitmq.conf: -------------------------------------------------------------------------------- 1 | # 150 hours, see https://www.rabbitmq.com/consumers.html#acknowledgement-timeout 2 | # the time is long to avoid a lot of critical errors 3 | consumer_timeout = 540000000 -------------------------------------------------------------------------------- /docker/.env: -------------------------------------------------------------------------------- 1 | ### DO NOT CHANGE THIS VALUE !! 2 | ### It should be updated only when you pull latest changes off from the 'master' branch of IntelOwl. 3 | # this variable must start with "REACT_APP_" to be used in the frontend too 4 | REACT_APP_INTELOWL_VERSION=v6.4.0 5 | # if you want to use a nfs volume for shared files 6 | # NFS_ADDRESS= 7 | -------------------------------------------------------------------------------- /docker/.env.start.test.template: -------------------------------------------------------------------------------- 1 | # Disabling repo_downloader.sh 2 | REPO_DOWNLOADER_ENABLED=false 3 | -------------------------------------------------------------------------------- /docker/Dockerfile_nginx: -------------------------------------------------------------------------------- 1 | FROM library/nginx:1.27.3-alpine 2 | 3 | ENV NGINX_LOG_DIR=/var/log/nginx 4 | # this is to avoid having these logs redirected to stdout/stderr 5 | RUN rm $NGINX_LOG_DIR/access.log $NGINX_LOG_DIR/error.log && touch $NGINX_LOG_DIR/access.log $NGINX_LOG_DIR/error.log 6 | VOLUME /var/log/nginx 7 | 8 | HEALTHCHECK --interval=3s --start-period=2s --timeout=2s --retries=5 CMD curl --fail http://localhost/hc || exit 1 -------------------------------------------------------------------------------- /docker/bin/README.md: -------------------------------------------------------------------------------- 1 | # Embedded binary list 2 | 3 | ### Osslsigncode 4 | 5 | We embedded the compiled version for Ubuntu for that can be retrieved from its original repo [here](https://github.com/mtrojnar/osslsigncode). 6 | 7 | We decided to do not use the version shipped by default Ubuntu packages because it were too old (2.1) 8 | 9 | At the last time of writing we uploaded the version 2.6-dev -------------------------------------------------------------------------------- /docker/bin/osslsigncode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/docker/bin/osslsigncode -------------------------------------------------------------------------------- /docker/entrypoints/celery_beat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | until cd /opt/deploy/intel_owl 4 | do 5 | echo "Waiting for server volume..." 6 | done 7 | ARGUMENTS="-A intel_owl.celery beat --uid www-data --gid www-data --pidfile= --schedule=/tmp/celerybeat-schedule --scheduler django_celery_beat.schedulers:DatabaseScheduler" 8 | if [[ $DEBUG == "True" ]] && [[ $DJANGO_TEST_SERVER == "True" ]]; 9 | then 10 | echo "Running celery with autoreload" 11 | python3 manage.py celery_reload -c "$ARGUMENTS" 12 | else 13 | # shellcheck disable=SC2086 14 | /usr/local/bin/celery $ARGUMENTS 15 | fi -------------------------------------------------------------------------------- /docker/entrypoints/celery_default.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | until cd /opt/deploy/intel_owl 4 | do 5 | echo "Waiting for server volume..." 6 | done 7 | 8 | echo "environment: $STAGE" 9 | if [ "$STAGE" = "ci" ] 10 | then 11 | worker_number=1 12 | else 13 | # default is prod 14 | worker_number=8 15 | fi 16 | 17 | 18 | if [ "$AWS_SQS" = "True" ] 19 | then 20 | queues="default.fifo,config.fifo" 21 | else 22 | queues="default,broadcast,config" 23 | fi 24 | 25 | 26 | ARGUMENTS="-A intel_owl.celery worker -n worker_default --uid www-data --gid www-data --time-limit=10000 --pidfile= -c $worker_number -Ofair -Q ${queues} -E --without-gossip" 27 | if [[ $DEBUG == "True" ]] && [[ $DJANGO_TEST_SERVER == "True" ]]; 28 | then 29 | echo "Running celery with autoreload" 30 | python3 manage.py celery_reload -c "$ARGUMENTS" 31 | else 32 | # shellcheck disable=SC2086 33 | /usr/local/bin/celery $ARGUMENTS 34 | fi -------------------------------------------------------------------------------- /docker/entrypoints/celery_ingestor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | until cd /opt/deploy/intel_owl 4 | do 5 | echo "Waiting for server volume..." 6 | done 7 | 8 | if [ "$AWS_SQS" = "True" ] 9 | then 10 | queues="ingestor.fifo,config.fifo" 11 | else 12 | queues="ingestor,broadcast,config" 13 | fi 14 | 15 | ARGUMENTS="-A intel_owl.celery worker -n worker_ingestor --uid www-data --gid www-data --time-limit=40000 --pidfile= -Ofair -Q ${queues} -E --autoscale=1,15 --without-gossip" 16 | if [[ $DEBUG == "True" ]] && [[ $DJANGO_TEST_SERVER == "True" ]]; 17 | then 18 | echo "Running celery with autoreload" 19 | python3 manage.py celery_reload -c "$ARGUMENTS" 20 | else 21 | # shellcheck disable=SC2086 22 | /usr/local/bin/celery $ARGUMENTS 23 | fi -------------------------------------------------------------------------------- /docker/entrypoints/celery_local.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | until cd /opt/deploy/intel_owl 4 | do 5 | echo "Waiting for server volume..." 6 | done 7 | if [ "$AWS_SQS" = "True" ] 8 | then 9 | queues="local.fifo,config.fifo" 10 | else 11 | queues="local,broadcast,config" 12 | fi 13 | 14 | ARGUMENTS="-A intel_owl.celery worker -n worker_local --uid www-data --time-limit=10000 --gid www-data --pidfile= -Ofair -Q ${queues} -E --without-gossip" 15 | if [[ $DEBUG == "True" ]] && [[ $DJANGO_TEST_SERVER == "True" ]]; 16 | then 17 | echo "Running celery with autoreload" 18 | python3 manage.py celery_reload -c "$ARGUMENTS" 19 | else 20 | # shellcheck disable=SC2086 21 | /usr/local/bin/celery $ARGUMENTS 22 | fi -------------------------------------------------------------------------------- /docker/entrypoints/celery_long.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | until cd /opt/deploy/intel_owl 4 | do 5 | echo "Waiting for server volume..." 6 | done 7 | if [ "$AWS_SQS" = "True" ] 8 | then 9 | queues="long.fifo,config.fifo" 10 | else 11 | queues="long,broadcast,config" 12 | fi 13 | 14 | ARGUMENTS="-A intel_owl.celery worker -n worker_long --uid www-data --gid www-data --time-limit=40000 --pidfile= -Ofair -Q ${queues} -E --without-gossip" 15 | if [[ $DEBUG == "True" ]] && [[ $DJANGO_TEST_SERVER == "True" ]]; 16 | then 17 | echo "Running celery with autoreload" 18 | python3 manage.py celery_reload -c "$ARGUMENTS" 19 | else 20 | # shellcheck disable=SC2086 21 | /usr/local/bin/celery $ARGUMENTS 22 | fi -------------------------------------------------------------------------------- /docker/entrypoints/daphne.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | until cd /opt/deploy/intel_owl 4 | do 5 | echo "Waiting for server volume..." 6 | done 7 | 8 | # verbosity param levels: https://github.com/django/daphne/blob/df0680c9ad699817725e18a9264df17fff2927da/daphne/cli.py#L213 9 | # not useful to improve logging 10 | /usr/local/bin/daphne --proxy-headers --access-log /var/log/intel_owl/asgi/daphne.log -p 8011 -b 0.0.0.0 --no-server-name --application-close-timeout 60 --ping-interval 30 --ping-timeout 35 intel_owl.asgi:application 11 | -------------------------------------------------------------------------------- /docker/env_file_elasticsearch_template: -------------------------------------------------------------------------------- 1 | ELASTIC_PASSWORD= -------------------------------------------------------------------------------- /docker/env_file_integrations_template: -------------------------------------------------------------------------------- 1 | ### ---- Environment variables for additional integrations --- 2 | ### All env variables for docker based integrations should be added here 3 | ### IMPORTANT: don't change these values unless you know what you are doing. It can have breaking changes! 4 | 5 | # Applies to all integrations, choose from: INFO (recommended), ERROR, DEBUG. 6 | LOG_LEVEL=INFO -------------------------------------------------------------------------------- /docker/env_file_postgres_template: -------------------------------------------------------------------------------- 1 | POSTGRES_PASSWORD=password 2 | POSTGRES_USER=user 3 | POSTGRES_DB=intel_owl_db -------------------------------------------------------------------------------- /docker/hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "display path" 4 | pwd 5 | echo "display dockerfile path" 6 | echo "$DOCKERFILE_PATH" 7 | cd .. 8 | echo "current branch" 9 | echo "$SOURCE_BRANCH" 10 | 11 | version_regex='^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' 12 | if [[ "$SOURCE_BRANCH" == "master" || "$SOURCE_BRANCH" == "test_arm" || "$SOURCE_BRANCH" == "develop_old" || "$SOURCE_BRANCH" =~ $version_regex ]]; then 13 | echo "The branch is master, proceeding with multi-arch build" 14 | docker buildx create --name multiarch --use 15 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --platform linux/arm64,linux/amd64 --push . 16 | else 17 | echo "The branch is not master, proceeding with classic build" 18 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --push . 19 | fi 20 | -------------------------------------------------------------------------------- /docker/https.override.yml: -------------------------------------------------------------------------------- 1 | services: 2 | nginx: 3 | volumes: 4 | - ../configuration/nginx/https.conf:/etc/nginx/conf.d/default.conf 5 | - /usr/local/share/ca-certificates:/usr/local/share/ca-certificates 6 | - /etc/ssl/private:/etc/ssl/private 7 | ports: 8 | - "443:443" -------------------------------------------------------------------------------- /docker/nfs.override.yml: -------------------------------------------------------------------------------- 1 | services: 2 | uwsgi: 3 | volumes: 4 | - nfs_files:/opt/deploy/files_required 5 | environment: 6 | - NFS=True 7 | 8 | celery_worker_default: 9 | volumes: 10 | - nfs_files:/opt/deploy/files_required 11 | environment: 12 | - NFS=True 13 | ports: 14 | - "2049:2049" 15 | - "2049:2049/udp" 16 | 17 | celery_beat: 18 | volumes: 19 | - nfs_files:/opt/deploy/files_required 20 | environment: 21 | - NFS=True 22 | 23 | 24 | 25 | volumes: 26 | nfs_files: 27 | driver: "local" 28 | driver_opts: 29 | type: "nfs" 30 | o: "addr=${NFS_ADDRESS},nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2" 31 | device: ":/" -------------------------------------------------------------------------------- /docker/nginx.override.yml: -------------------------------------------------------------------------------- 1 | services: 2 | nginx: 3 | ports: 4 | - "80:80" 5 | -------------------------------------------------------------------------------- /docker/postgres.override.yml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | postgres: 4 | image: library/postgres:16-alpine 5 | container_name: intelowl_postgres 6 | volumes: 7 | - postgres_data:/var/lib/postgresql/data/ 8 | env_file: 9 | - ./env_file_postgres 10 | healthcheck: 11 | test: [ "CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB" ] 12 | interval: 5s 13 | timeout: 2s 14 | retries: 6 15 | start_period: 3s 16 | 17 | 18 | uwsgi: 19 | depends_on: 20 | postgres: 21 | condition: service_healthy 22 | 23 | 24 | celery_worker_default: 25 | depends_on: 26 | postgres: 27 | condition: service_healthy 28 | -------------------------------------------------------------------------------- /docker/rabbitmq.override.yml: -------------------------------------------------------------------------------- 1 | services: 2 | rabbitmq: 3 | image: library/rabbitmq:3.11-alpine 4 | container_name: intelowl_rabbitmq 5 | volumes: 6 | - ../configuration/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf 7 | logging: 8 | driver: none 9 | 10 | uwsgi: 11 | environment: 12 | - BROKER_URL="amqp://guest:guest@rabbitmq:5672" 13 | depends_on: 14 | - rabbitmq 15 | 16 | celery_worker_default: 17 | environment: 18 | - BROKER_URL="amqp://guest:guest@rabbitmq:5672" 19 | 20 | celery_beat: 21 | environment: 22 | - BROKER_URL="amqp://guest:guest@rabbitmq:5672" 23 | -------------------------------------------------------------------------------- /docker/scripts/cron/application_restart: -------------------------------------------------------------------------------- 1 | 0 2 * * 0 root /opt/deploy/intel_owl/start test down --all_analyzers && /opt/deploy/intel_owl/start test up --all_analyzers -- -d -------------------------------------------------------------------------------- /docker/scripts/cron/update_repositories: -------------------------------------------------------------------------------- 1 | 0 1 * * 3 root python3 docker exec -ti $(docker ps | grep intelowl_celery_worker_default | awk '{print $1}') python3 manage.py update_analyzer MaxMindGeoIP 2 | 5 */6 * * * root python3 docker exec -ti $(docker ps | grep intelowl_celery_worker_default | awk '{print $1}') python3 manage.py update_analyzer TalosReputation 3 | 5 */6 * * * root python3 docker exec -ti $(docker ps | grep intelowl_celery_worker_default | awk '{print $1}') python3 manage.py update_analyzer PhishingArmy 4 | */10 * * * * root python3 docker exec -ti $(docker ps | grep intelowl_celery_worker_default | awk '{print $1}') python3 manage.py update_analyzer TorProject 5 | 0 4 * * * root python3 docker exec -ti $(docker ps | grep intelowl_celery_worker_default | awk '{print $1}') python3 manage.py update_analyzer Yara 6 | 0 3 * * 2,5 root python3 docker exec -ti $(docker ps | grep intelowl_celery_worker_default | awk '{print $1}') python3 manage.py update_analyzer Quark_Engine 7 | -------------------------------------------------------------------------------- /docker/scripts/initdb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker exec intelowl_uwsgi python3 manage.py makemigrations 3 | docker exec intelowl_uwsgi python3 manage.py migrate 4 | docker exec -ti intelowl_uwsgi python3 manage.py createsuperuser \ 5 | --username admin --email admin@admin.com --first_name admin --last_name admin 6 | -------------------------------------------------------------------------------- /docker/scripts/install_crontab.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cp cron/* /etc/cron.d -------------------------------------------------------------------------------- /docker/scripts/install_logrotate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo cp -r logrotate /etc/logrotate.d -------------------------------------------------------------------------------- /docker/scripts/logrotate/application: -------------------------------------------------------------------------------- 1 | /var/lib/docker/volumes/*_logs/_data/*/*.log { 2 | daily 3 | missingok 4 | rotate 2 5 | size 10M 6 | compress 7 | delaycompress 8 | notifempty 9 | create 0644 www-data www-data 10 | copytruncate 11 | } -------------------------------------------------------------------------------- /docker/scripts/logrotate/docker: -------------------------------------------------------------------------------- 1 | /var/log/docker/*.log { 2 | daily 3 | missingok 4 | rotate 2 5 | size 10M 6 | compress 7 | delaycompress 8 | notifempty 9 | create 0655 syslog adm 10 | copytruncate 11 | } 12 | -------------------------------------------------------------------------------- /docker/scripts/logrotate/nginx: -------------------------------------------------------------------------------- 1 | /var/lib/docker/volumes/*_nginx/_data/*.log { 2 | daily 3 | missingok 4 | rotate 8 5 | size 1M 6 | compress 7 | delaycompress 8 | notifempty 9 | create 0644 www-data www-data 10 | sharedscripts 11 | prerotate 12 | if [ -d /etc/logrotate.d/httpd-prerotate ]; then \ 13 | run-parts /etc/logrotate.d/httpd-prerotate; \ 14 | fi \ 15 | endscript 16 | postrotate 17 | container_id=$(docker ps -f name=intelowl_nginx --quiet) 18 | docker exec $container_id killall -USR1 nginx 19 | endscript 20 | } -------------------------------------------------------------------------------- /docker/scripts/manage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker exec -ti intelowl_uwsgi python3 manage.py "$@" 3 | -------------------------------------------------------------------------------- /docker/scripts/tail-logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker exec intelowl_uwsgi ls -al /var/log/intel_owl/"$1" 4 | docker exec -ti intelowl_uwsgi tail -f /var/log/intel_owl/"$1" 5 | -------------------------------------------------------------------------------- /docker/sqs.override.yml: -------------------------------------------------------------------------------- 1 | services: 2 | uwsgi: 3 | environment: 4 | - AWS_SQS=True 5 | - BROKER_URL=sqs:// 6 | 7 | celery_beat: 8 | environment: 9 | - AWS_SQS=True 10 | - BROKER_URL=sqs:// 11 | 12 | celery_worker_default: 13 | environment: 14 | - AWS_SQS=True 15 | - BROKER_URL=sqs:// 16 | -------------------------------------------------------------------------------- /docker/test.flower.override.yml: -------------------------------------------------------------------------------- 1 | services: 2 | flower: 3 | image: intelowlproject/intelowl:test 4 | volumes: 5 | - ../:/opt/deploy/intel_owl -------------------------------------------------------------------------------- /docker/test.multi-queue.override.yml: -------------------------------------------------------------------------------- 1 | services: 2 | celery_worker_local: 3 | image: intelowlproject/intelowl:test 4 | volumes: 5 | - ../:/opt/deploy/intel_owl 6 | 7 | celery_worker_long: 8 | image: intelowlproject/intelowl:test 9 | volumes: 10 | - ../:/opt/deploy/intel_owl 11 | 12 | celery_worker_ingestor: 13 | image: intelowlproject/intelowl:test 14 | volumes: 15 | - ../:/opt/deploy/intel_owl -------------------------------------------------------------------------------- /docker/traefik.yml: -------------------------------------------------------------------------------- 1 | services: 2 | traefik: 3 | image: "traefik:3.0" 4 | labels: 5 | - "traefik.enable=true" 6 | 7 | nginx: 8 | depends_on: 9 | - traefik 10 | labels: 11 | - "traefik.enable=true" 12 | - "traefik.http.services.nginx.loadbalancer.server.port=80" 13 | expose: 14 | - "80" 15 | 16 | -------------------------------------------------------------------------------- /docker/traefik_local.yml: -------------------------------------------------------------------------------- 1 | services: 2 | traefik: 3 | container_name: "intelowl_traefik_local" 4 | command: 5 | # Pleases refer to the official documentation: https://doc.traefik.io/traefik/ 6 | # LOGS 7 | - "--log.level=DEBUG" 8 | # DASHBOARD 9 | - "--api.insecure=true" 10 | - "--api.dashboard=true" 11 | # ENTRYPOINTS - redirect every request to use HTTPS 12 | - "--entrypoints.web.address=:80" 13 | # PROVIDERS 14 | - "--providers.docker=true" 15 | - "--providers.docker.watch=true" 16 | - "--providers.docker.exposedbydefault=false" 17 | ports: 18 | - "80:80" 19 | - "8080:8080" 20 | volumes: 21 | - "/var/run/docker.sock:/var/run/docker.sock:ro" 22 | 23 | nginx: 24 | depends_on: 25 | - traefik 26 | labels: 27 | - "traefik.http.routers.nginx.rule=Host(`localhost`)" 28 | - "traefik.http.routers.nginx.entrypoints=web" 29 | -------------------------------------------------------------------------------- /elasticsearch_instances.yml: -------------------------------------------------------------------------------- 1 | instances: 2 | - name: elasticsearch 3 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | 6 | # builds 7 | build 8 | dist 9 | .rpt2_cache 10 | 11 | # misc 12 | .DS_Store 13 | .env 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | public/env.js 19 | 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | pnpm-lock.yaml 24 | -------------------------------------------------------------------------------- /frontend/.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts: 2 | .coverage 3 | -------------------------------------------------------------------------------- /frontend/.prettierrc: -------------------------------------------------------------------------------- 1 | # http://json.schemastore.org/prettierrc 2 | 3 | tabWidth: 2 4 | useTabs: false 5 | -------------------------------------------------------------------------------- /frontend/.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["stylelint-config-standard-scss", "stylelint-config-prettier"], 3 | "rules": { 4 | "selector-no-qualifying-type": [true, { "ignore": ["class", "attribute"] }], 5 | "color-function-notation": "legacy" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /frontend/FixJSDOMEnvironment.js: -------------------------------------------------------------------------------- 1 | // FixJSDOMEnvironment.ts 2 | 3 | // eslint-disable-next-line import/no-extraneous-dependencies 4 | import JSDOMEnvironment from "jest-environment-jsdom"; 5 | 6 | // https://github.com/facebook/jest/blob/v29.4.3/website/versioned_docs/version-29.4/Configuration.md#testenvironment-string 7 | export default class FixJSDOMEnvironment extends JSDOMEnvironment { 8 | constructor(...args) { 9 | // @ts-ignore 10 | super(...args); 11 | 12 | // https://github.com/jsdom/jsdom/issues/3363 13 | this.global.structuredClone = structuredClone; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /frontend/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | "@babel/preset-env", 4 | ["@babel/preset-react", { runtime: "automatic" }], 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /frontend/public/icons/192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/192x192.png -------------------------------------------------------------------------------- /frontend/public/icons/512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/512x512.png -------------------------------------------------------------------------------- /frontend/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /frontend/public/icons/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /frontend/public/icons/cloudflare-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/cloudflare-icon.png -------------------------------------------------------------------------------- /frontend/public/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/favicon-16x16.png -------------------------------------------------------------------------------- /frontend/public/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/favicon-32x32.png -------------------------------------------------------------------------------- /frontend/public/icons/favicon-notification.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/favicon-notification.ico -------------------------------------------------------------------------------- /frontend/public/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/favicon.ico -------------------------------------------------------------------------------- /frontend/public/icons/google-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/google-icon.png -------------------------------------------------------------------------------- /frontend/public/icons/honeynet.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/honeynet.ico -------------------------------------------------------------------------------- /frontend/public/icons/hybrid-analysis-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/hybrid-analysis-icon.png -------------------------------------------------------------------------------- /frontend/public/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/mstile-150x150.png -------------------------------------------------------------------------------- /frontend/public/icons/quad9-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/quad9-icon.png -------------------------------------------------------------------------------- /frontend/public/icons/quokka-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/quokka-icon.png -------------------------------------------------------------------------------- /frontend/public/icons/urlhaus-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/icons/urlhaus-icon.png -------------------------------------------------------------------------------- /frontend/public/logo-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/logo-blue.png -------------------------------------------------------------------------------- /frontend/public/logo-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/logo-dark.png -------------------------------------------------------------------------------- /frontend/public/logo-negative-reduced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/logo-negative-reduced.png -------------------------------------------------------------------------------- /frontend/public/logo-negative.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/logo-negative.png -------------------------------------------------------------------------------- /frontend/public/logo-positive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/logo-positive.png -------------------------------------------------------------------------------- /frontend/public/logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/logo-white.png -------------------------------------------------------------------------------- /frontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "IntelOwl", 3 | "name": "IntelOwl", 4 | "description": "Analyze files, domains, IPs in multiple ways from a single API at scale.", 5 | "theme_color": "#0b2b38", 6 | "background_color": "#00161f", 7 | "display": "standalone", 8 | "orientation": "portrait", 9 | "start_url": ".", 10 | "icons": [ 11 | { 12 | "src": "icons/favicon.ico", 13 | "sizes": "48x48 32x32 16x16", 14 | "type": "image/x-icon" 15 | }, 16 | { 17 | "src": "icons/192x192.png", 18 | "sizes": "192x192", 19 | "type": "image/png" 20 | }, 21 | { 22 | "src": "icons/512x512.png", 23 | "sizes": "512x512", 24 | "type": "image/png" 25 | }, 26 | { 27 | "src": "logo-blue.png", 28 | "type": "image/png", 29 | "sizes": "4614x4092" 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /frontend/public/notification.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/frontend/public/notification.mp3 -------------------------------------------------------------------------------- /frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /frontend/src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { BrowserRouter } from "react-router-dom"; 3 | import { GuideProvider } from "./contexts/GuideContext"; 4 | 5 | // layout 6 | import AppMain from "./layouts/AppMain"; 7 | import GuideWrapper from "./components/GuideWrapper"; 8 | 9 | function App() { 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | export default App; 21 | -------------------------------------------------------------------------------- /frontend/src/components/auth/Logout.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { FallBackLoading } from "@certego/certego-ui"; 4 | 5 | import { useAuthStore } from "../../stores/useAuthStore"; 6 | 7 | export default function Logout() { 8 | // auth store 9 | const [loading, logoutUser] = useAuthStore( 10 | React.useCallback((state) => [state.loading, state.service.logoutUser], []), 11 | ); 12 | 13 | React.useEffect(() => { 14 | if (!loading) { 15 | logoutUser(); 16 | } 17 | }, [loading, logoutUser]); 18 | 19 | return ; 20 | } 21 | -------------------------------------------------------------------------------- /frontend/src/components/common/JobTag.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import { Badge } from "reactstrap"; 4 | 5 | export function JobTag(props) { 6 | const { tag, ...rest } = props; 7 | 8 | return ( 9 | 16 | {tag.label} 17 | 18 | ); 19 | } 20 | 21 | JobTag.propTypes = { 22 | tag: PropTypes.shape({ 23 | label: PropTypes.string.isRequired, 24 | color: PropTypes.string.isRequired, 25 | }).isRequired, 26 | }; 27 | -------------------------------------------------------------------------------- /frontend/src/components/common/PlaybookTag.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import { Badge } from "reactstrap"; 4 | 5 | export function PlaybookTag(props) { 6 | const { playbook, ...rest } = props; 7 | 8 | return ( 9 | 10 | {playbook} 11 | 12 | ); 13 | } 14 | 15 | PlaybookTag.propTypes = { 16 | playbook: PropTypes.string.isRequired, 17 | }; 18 | -------------------------------------------------------------------------------- /frontend/src/components/common/areYouSureConfirmDialog.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { IoMdWarning } from "react-icons/io"; 3 | 4 | import { confirm } from "@certego/certego-ui"; 5 | 6 | export const areYouSureConfirmDialog = (opName) => 7 | confirm({ 8 | title: ( 9 |
10 | 11 | Confirm 12 |
13 | ), 14 | message: ( 15 |
16 |
Operation:
17 |
{opName}
18 |
19 | Are you sure ? 20 |
21 | ), 22 | confirmColor: "secondary", 23 | cancelColor: "link text-gray", 24 | }); 25 | -------------------------------------------------------------------------------- /frontend/src/components/common/markdownToHtml.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactMarkdown from "react-markdown"; 3 | 4 | /** 5 | * @param {string} text 6 | */ 7 | export function markdownToHtml(text) { 8 | return ( 9 | , 15 | // eslint-disable-next-line id-length 16 | a: ({ node: _, ...props }) => ( 17 | // eslint-disable-next-line jsx-a11y/anchor-has-content 18 | 19 | ), 20 | }} 21 | /> 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /frontend/src/components/home/Home.scss: -------------------------------------------------------------------------------- 1 | // Home.jsx 2 | 3 | @import url("https://fonts.googleapis.com/css?family=Pacifico:400"); 4 | 5 | html { 6 | overflow-x: hidden; 7 | } 8 | 9 | #home__bgImg { 10 | background-color: #000; 11 | position: relative; 12 | height: 20vh; 13 | width: 100vw; 14 | top: -25px; 15 | left: -50px; 16 | opacity: 1; 17 | background-position: center; 18 | background-size: 35%; 19 | background-repeat: no-repeat; 20 | min-height: 100% !important; 21 | } 22 | 23 | #home__versionText { 24 | position: absolute; 25 | top: 10%; 26 | left: 70%; 27 | font-family: Pacifico; 28 | transform: rotate(335deg) !important; 29 | -ms-transform: rotate(335deg) !important; 30 | } 31 | 32 | #guidebox { 33 | border-radius: 10px; 34 | } 35 | -------------------------------------------------------------------------------- /frontend/src/components/jobs/notification/notificationApi.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | 3 | import { addToast } from "@certego/certego-ui"; 4 | 5 | import { NOTIFICATION_BASE_URI } from "../../../constants/apiURLs"; 6 | 7 | export async function notificationMarkAsRead(notifId) { 8 | try { 9 | await axios.post(`${NOTIFICATION_BASE_URI}/${notifId}/mark-as-read`); 10 | return Promise.resolve(true); 11 | } catch (error) { 12 | addToast("Failed!", error.parsedMsg, "danger", true); 13 | return Promise.reject(error); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /frontend/src/components/jobs/result/visualizer/elements/const.js: -------------------------------------------------------------------------------- 1 | export const VisualizerComponentType = Object.freeze({ 2 | BASE: "base", 3 | BOOL: "bool", 4 | VLIST: "vertical_list", 5 | HLIST: "horizontal_list", 6 | TITLE: "title", 7 | TABLE: "table", 8 | DOWNLOAD: "download", 9 | }); 10 | -------------------------------------------------------------------------------- /frontend/src/components/jobs/result/visualizer/elements/horizontalList.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import { Row } from "reactstrap"; 4 | 5 | export function HorizontalListVisualizer({ values, alignment, id }) { 6 | return ( 7 | 8 | {values} 9 | 10 | ); 11 | } 12 | 13 | HorizontalListVisualizer.propTypes = { 14 | values: PropTypes.arrayOf(PropTypes.element).isRequired, 15 | alignment: PropTypes.string, 16 | id: PropTypes.string.isRequired, 17 | }; 18 | 19 | HorizontalListVisualizer.defaultProps = { 20 | alignment: "around", 21 | }; 22 | -------------------------------------------------------------------------------- /frontend/src/components/jobs/result/visualizer/elements/title.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export function TitleVisualizer({ size, title, value, alignment, id }) { 5 | return ( 6 |
10 |
{title}
11 | {value} 12 |
13 | ); 14 | } 15 | 16 | TitleVisualizer.propTypes = { 17 | size: PropTypes.string.isRequired, 18 | title: PropTypes.element.isRequired, 19 | value: PropTypes.element.isRequired, 20 | alignment: PropTypes.string, 21 | id: PropTypes.string.isRequired, 22 | }; 23 | 24 | TitleVisualizer.defaultProps = { 25 | alignment: "center", 26 | }; 27 | -------------------------------------------------------------------------------- /frontend/src/components/organization/utils/InvitationStatusBadge.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | import { CustomMapBadge } from "@certego/certego-ui"; 5 | 6 | // constant 7 | const INVITATION_STATUS_COLOR_MAP = { 8 | pending: "warning", 9 | accepted: "success", 10 | declined: "danger", 11 | }; 12 | 13 | export function InvitationStatusBadge({ status, ...rest }) { 14 | return ( 15 | 20 | ); 21 | } 22 | 23 | InvitationStatusBadge.propTypes = { 24 | status: PropTypes.string.isRequired, 25 | }; 26 | -------------------------------------------------------------------------------- /frontend/src/components/plugins/tables/Ingestors.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { ingestorTableColumns } from "./pluginTableColumns"; 4 | import PluginWrapper from "./PluginWrapper"; 5 | import { PluginsTypes } from "../../../constants/pluginConst"; 6 | 7 | export default function Ingestors() { 8 | console.debug("Ingestors rendered!"); 9 | 10 | const stateSelector = React.useCallback( 11 | (state) => [ 12 | state.ingestorsLoading, 13 | state.ingestorsError, 14 | state.ingestors, 15 | state.retrieveIngestorsConfiguration, 16 | ], 17 | [], 18 | ); 19 | 20 | return ( 21 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /frontend/src/components/plugins/tables/Pivots.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { pivotTableColumns } from "./pluginTableColumns"; 4 | import PluginWrapper from "./PluginWrapper"; 5 | import { PluginsTypes } from "../../../constants/pluginConst"; 6 | 7 | export default function Pivots() { 8 | console.debug("Pivots rendered!"); 9 | 10 | const stateSelector = React.useCallback( 11 | (state) => [ 12 | state.pivotsLoading, 13 | state.pivotsError, 14 | state.pivots, 15 | state.retrievePivotsConfiguration, 16 | ], 17 | [], 18 | ); 19 | 20 | return ( 21 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /frontend/src/components/plugins/tables/Playbooks.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { playbookTableColumns } from "./pluginTableColumns"; 4 | import { PluginsTypes } from "../../../constants/pluginConst"; 5 | import PluginWrapper from "./PluginWrapper"; 6 | 7 | export default function Playbooks() { 8 | console.debug("Playbooks rendered!"); 9 | 10 | const stateSelector = React.useCallback( 11 | (state) => [ 12 | state.playbooksLoading, 13 | state.playbooksError, 14 | state.playbooks, 15 | state.retrievePlaybooksConfiguration, 16 | ], 17 | [], 18 | ); 19 | 20 | return ( 21 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /frontend/src/components/search/utils.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | import { JsonEditor } from "../common/JsonEditor"; 5 | import { useJsonEditorStore } from "../../stores/useJsonEditorStore"; 6 | 7 | export function SearchJSONReport({ row }) { 8 | // store 9 | const [textToHighlight] = useJsonEditorStore((state) => [ 10 | state.textToHighlight, 11 | ]); 12 | return ( 13 |
17 | 24 |
25 | ); 26 | } 27 | 28 | SearchJSONReport.propTypes = { 29 | row: PropTypes.object.isRequired, 30 | }; 31 | -------------------------------------------------------------------------------- /frontend/src/constants/advancedSettingsConst.js: -------------------------------------------------------------------------------- 1 | export const ScanTypes = Object.freeze({ 2 | playbooks: "Playbooks", 3 | analyzers_and_connectors: "Analyzers/Connectors", 4 | }); 5 | 6 | export const ScanModesNumeric = Object.freeze({ 7 | FORCE_NEW_ANALYSIS: "1", 8 | CHECK_PREVIOUS_ANALYSIS: "2", 9 | }); 10 | 11 | export const TLPs = Object.freeze({ 12 | CLEAR: "CLEAR", 13 | GREEN: "GREEN", 14 | AMBER: "AMBER", 15 | RED: "RED", 16 | }); 17 | 18 | export const TlpChoices = Object.values(TLPs); 19 | -------------------------------------------------------------------------------- /frontend/src/constants/engineConst.js: -------------------------------------------------------------------------------- 1 | export const EvaluationIcons = Object.freeze({ 2 | trusted: "like", 3 | malicious: "malware", 4 | }); 5 | 6 | export const TagsIcons = Object.freeze({ 7 | phishing: "hook", 8 | anonymizer: "incognito", 9 | malware: "malware", 10 | social_engineering: "creditCard", 11 | tor_exit_node: "tor", 12 | scanner: "magnifyingGlass", 13 | ip_only: "networkNode", 14 | }); 15 | 16 | export const Evaluations = Object.freeze({ 17 | TRUSTED: "trusted", 18 | MALICIOUS: "malicious", 19 | }); 20 | -------------------------------------------------------------------------------- /frontend/src/constants/environment.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-destructuring */ 2 | export const INTELOWL_DOCS_URL = "https://intelowlproject.github.io/docs/"; 3 | export const PYINTELOWL_GH_URL = 4 | "https://github.com/intelowlproject/pyintelowl"; 5 | export const INTELOWL_TWITTER_ACCOUNT = "intel_owl"; 6 | export const INTELOWL_REPO_URL = "https://github.com/intelowlproject/IntelOwl/"; 7 | 8 | // env variables 9 | export const VERSION = process.env.REACT_APP_INTELOWL_VERSION; 10 | export const PUBLIC_URL = process.env.PUBLIC_URL; 11 | -------------------------------------------------------------------------------- /frontend/src/constants/investigationConst.js: -------------------------------------------------------------------------------- 1 | export const InvestigationStatuses = Object.freeze({ 2 | CREATED: "created", 3 | RUNNING: "running", 4 | CONCLUDED: "concluded", 5 | }); 6 | -------------------------------------------------------------------------------- /frontend/src/constants/miscConst.js: -------------------------------------------------------------------------------- 1 | export const JobResultSections = Object.freeze({ 2 | RAW: "raw", 3 | VISUALIZER: "visualizer", 4 | }); 5 | 6 | export const TLPDescriptions = Object.freeze({ 7 | CLEAR: "TLP: use all analyzers", 8 | GREEN: "TLP: disable analyzers that could impact privacy", 9 | AMBER: 10 | "TLP: disable analyzers that could impact privacy and limit access to my organization", 11 | RED: "TLP: disable analyzers that could impact privacy, limit access to my organization and do not use any external service", 12 | }); 13 | 14 | export const HACKER_MEME_STRING = 15 | "LoOk At YoU hAcKeR a PaThEtIc CrEaTuRe Of MeAt AnD bOnE"; 16 | 17 | export const HTTPMethods = Object.freeze({ 18 | GET: "get", 19 | POST: "post", 20 | PUT: "put", 21 | PATCH: "patch", 22 | DELETE: "delete", 23 | }); 24 | 25 | export const datetimeFormatStr = "yyyy-MM-dd'T'HH:mm:ss"; 26 | -------------------------------------------------------------------------------- /frontend/src/constants/regexConst.js: -------------------------------------------------------------------------------- 1 | export const UUID_REGEX = 2 | /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i; 3 | 4 | // OBSERVABLES 5 | // ip regex is valid for both IPv4 and IPv6 6 | export const IP_REGEX = 7 | /^(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::[0-9a-fA-F]{1,4}|[0-9a-fA-F]{1,4}::|(?:(?:[0-9a-fA-F]{1,4}:){1,6}:)(?::[0-9a-fA-F]{1,4}){1,2}))$/; 8 | export const DOMAIN_REGEX = /^(?:[\w-]{1,63}\.)+[\w-]{2,63}$/; 9 | export const URL_REGEX = /^.{2,20}:\/\/.+$/; 10 | export const HASH_REGEX = /^[a-zA-Z0-9]{32,}$/; 11 | export const PHONE_REGEX = /^\+[1-9]\d{1,14}$/; 12 | 13 | export const EMAIL_REGEX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i; 14 | export const PASSWORD_REGEX = /^(?=.*[a-zA-Z])[a-zA-Z0-9]{12,}$/i; 15 | -------------------------------------------------------------------------------- /frontend/src/hooks/index.js: -------------------------------------------------------------------------------- 1 | export { default as useQuotaBadge } from "./useQuotaBadge"; 2 | -------------------------------------------------------------------------------- /frontend/src/index.jsx: -------------------------------------------------------------------------------- 1 | // import "./wdyr"; 2 | 3 | import "./styles/App.scss"; 4 | 5 | import React from "react"; 6 | import ReactDOM from "react-dom"; 7 | import App from "./App"; 8 | import * as serviceWorker from "./serviceWorker"; 9 | 10 | import initAxios from "./utils/initAxios"; 11 | 12 | function noop() {} 13 | // hack to disable console.debug statements in production build 14 | if (process.env.NODE_ENV !== "development") { 15 | console.debug = noop; 16 | } 17 | 18 | initAxios(); 19 | 20 | ReactDOM.render(, document.getElementById("root")); 21 | 22 | // If you want your app to work offline and load faster, you can change 23 | // unregister() to register() below. Note this comes with some pitfalls. 24 | // Learn more about service workers: https://bit.ly/CRA-PWA 25 | serviceWorker.unregister(); 26 | -------------------------------------------------------------------------------- /frontend/src/layouts/NoMatch.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import { Container } from "reactstrap"; 4 | import useTitle from "react-use/lib/useTitle"; 5 | 6 | function NoMatch() { 7 | console.debug("NoMatch rendered!"); 8 | 9 | // page title 10 | useTitle("IntelOwl | 404: Not Found", { restoreOnUnmount: true }); 11 | 12 | return ( 13 | 14 | 404: Not Found 15 |
16 | 17 | Go back to home page ? 18 | 19 |
20 | ); 21 | } 22 | 23 | export default NoMatch; 24 | -------------------------------------------------------------------------------- /frontend/src/layouts/Toast.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useToastr, Toaster } from "@certego/certego-ui"; 3 | 4 | function Toast() { 5 | // consume store 6 | const toasts = useToastr((state) => state.toasts); 7 | console.debug("Toasts:", toasts); 8 | 9 | return ( 10 |
11 | {toasts.map((tProps) => ( 12 | 13 | ))} 14 |
15 | ); 16 | } 17 | 18 | export default Toast; 19 | -------------------------------------------------------------------------------- /frontend/src/stores/useJsonEditorStore.jsx: -------------------------------------------------------------------------------- 1 | import { create } from "zustand"; 2 | 3 | export const useJsonEditorStore = create((set, _get) => ({ 4 | textToHighlight: "", 5 | setTextToHighlight: (data) => { 6 | set({ textToHighlight: data }); 7 | }, 8 | })); 9 | -------------------------------------------------------------------------------- /frontend/src/utils/files.js: -------------------------------------------------------------------------------- 1 | export const fileDownload = (blob, filename) => { 2 | // create URL blob and a hidden
tag to serve file for download 3 | const fileLink = document.createElement("a"); 4 | fileLink.href = window.URL.createObjectURL(blob); 5 | fileLink.rel = "noopener,noreferrer"; 6 | fileLink.download = `${filename}`; 7 | // triggers the click event 8 | fileLink.click(); 9 | console.debug("clicked"); 10 | }; 11 | 12 | export const humanReadbleSize = (byteNumber) => { 13 | if (byteNumber === 0) { 14 | return "0.00 B"; 15 | } 16 | const number = Math.floor(Math.log(byteNumber) / Math.log(1024)); 17 | return `${(byteNumber / 1024 ** number).toFixed(2)} ${" KMGTP".charAt( 18 | number, 19 | )}B`; 20 | }; 21 | -------------------------------------------------------------------------------- /frontend/src/utils/time.js: -------------------------------------------------------------------------------- 1 | export function processTimeMMSS(value) { 2 | return new Date(value * 1000).toISOString().substring(14, 19); 3 | } 4 | 5 | export function parseScanCheckTime(time) { 6 | // scan_check_time is in format days:hours:minutes:seconds, we need to convert them to hours 7 | const [daysAgo, hoursAgo] = time 8 | .split(":") 9 | .map((token) => parseInt(token, 10)); 10 | return daysAgo * 24 + hoursAgo; 11 | } 12 | -------------------------------------------------------------------------------- /frontend/src/wrappers/IfAuthRedirectGuard.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import { Navigate } from "react-router-dom"; 4 | import useSearchParam from "react-use/lib/useSearchParam"; 5 | 6 | import { useAuthStore } from "../stores/useAuthStore"; 7 | 8 | /* 9 | Wrapper for Routes which should be accessible only to a non-authenticated user 10 | */ 11 | export default function IfAuthRedirectGuard({ children }) { 12 | // store 13 | const [loading, isAuthenticated] = useAuthStore( 14 | React.useCallback((state) => [state.loading, state.isAuthenticated()], []), 15 | ); 16 | const next = useSearchParam("next") || "/"; 17 | 18 | if (isAuthenticated && !loading) { 19 | return ; 20 | } 21 | return children; 22 | } 23 | 24 | IfAuthRedirectGuard.propTypes = { 25 | children: PropTypes.node.isRequired, 26 | }; 27 | -------------------------------------------------------------------------------- /frontend/tests/components/user/token/TokenPage.test.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "@testing-library/jest-dom"; 3 | import { render, screen } from "@testing-library/react"; 4 | 5 | import useAxios from "axios-hooks"; 6 | 7 | import TokenPage from "../../../../src/components/user/token/TokenPage"; 8 | 9 | jest.mock("axios-hooks"); 10 | 11 | useAxios.mockReturnValue([ 12 | { 13 | data: { 14 | key: "123456789", 15 | created: "2024-02-22T15:48:18.257944", 16 | }, 17 | }, 18 | ]); 19 | 20 | describe("test TokenPage", () => { 21 | test("render", () => { 22 | render(); 23 | expect(screen.getByText("API Access")).toBeInTheDocument(); 24 | expect(screen.getByText("Created")).toBeInTheDocument(); 25 | expect(screen.getByText("03:48 PM Feb 22nd, 2024")).toBeInTheDocument(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /frontend/tests/components/utils/time.test.js: -------------------------------------------------------------------------------- 1 | import { processTimeMMSS, parseScanCheckTime } from "../../../src/utils/time"; 2 | 3 | describe("test time utilities", () => { 4 | test("processTimeMMSS", () => { 5 | expect(processTimeMMSS(3.08)).toBe("00:03"); 6 | expect(processTimeMMSS(0.23)).toBe("00:00"); 7 | }); 8 | 9 | test("parseScanCheckTime - correct time: days:hours:minutes:seconds", () => { 10 | const time = parseScanCheckTime("01:02:00:00"); 11 | expect(time).toBe(26); 12 | }); 13 | 14 | test("parseScanCheckTime - not correct time: days-hours-minutes-seconds", () => { 15 | const time = parseScanCheckTime("01-02-00-00"); 16 | expect(time).toBe(NaN); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/tests/test-setup.js: -------------------------------------------------------------------------------- 1 | // suppression of the logs for the frontend tests (suppression for the CI is in the action) 2 | if (process.env.SUPPRESS_JEST_LOG) { 3 | global.console = { 4 | ...console, 5 | log: jest.fn(), 6 | debug: jest.fn(), 7 | error: jest.fn(), 8 | warn: jest.fn(), 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /frontend/tests/utils/files.test.js: -------------------------------------------------------------------------------- 1 | const { humanReadbleSize } = require("../../src/utils/files"); 2 | 3 | describe("test utilities functions for files", () => { 4 | test("test humanReadbleSize", () => { 5 | expect(humanReadbleSize(0)).toBe("0.00 B"); 6 | expect(humanReadbleSize(1)).toBe("1.00 B"); 7 | expect(humanReadbleSize(1024 ** 1)).toBe("1.00 KB"); 8 | expect(humanReadbleSize(1024 ** 2)).toBe("1.00 MB"); 9 | expect(humanReadbleSize(1024 ** 3)).toBe("1.00 GB"); 10 | expect(humanReadbleSize(1024 ** 4)).toBe("1.00 TB"); 11 | expect(humanReadbleSize(1024 ** 5)).toBe("1.00 PB"); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /integrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/integrations/__init__.py -------------------------------------------------------------------------------- /integrations/bbot/compose-tests.yml: -------------------------------------------------------------------------------- 1 | # All additional integrations should be added following this format only. 2 | 3 | services: 4 | bbot_analyzer: 5 | build: 6 | context: ../integrations/bbot 7 | dockerfile: Dockerfile 8 | image: intelowlproject/intelowl_bbot_analyzer:test 9 | -------------------------------------------------------------------------------- /integrations/bbot/compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | bbot_analyzer: 3 | image: intelowlproject/intelowl_bbot_analyzer:${REACT_APP_INTELOWL_VERSION} 4 | container_name: intelowl_bbot_analyzer 5 | restart: unless-stopped 6 | expose: 7 | - "5001" 8 | volumes: 9 | - generic_logs:/var/log/intel_owl 10 | depends_on: 11 | - uwsgi 12 | -------------------------------------------------------------------------------- /integrations/bbot/requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi==0.115.12 2 | uvicorn[standard]==0.34.0 3 | bbot==2.4.0 -------------------------------------------------------------------------------- /integrations/cyberchef/Dockerfile: -------------------------------------------------------------------------------- 1 | # Adapted from https://github.com/gchq/CyberChef-server/blob/master/Dockerfile 2 | FROM node:lts-alpine3.21 3 | RUN apk update && apk --no-cache add git 4 | LABEL author = "Wes Lambert, wlambertts@gmail.com" 5 | LABEL description="Dockerised version of Cyberchef server (https://github.com/gchq/CyberChef-server)" 6 | LABEL copyright = "Crown Copyright 2020" 7 | LABEL license = "Apache-2.0" 8 | WORKDIR /CyberChef-server 9 | RUN git clone https://github.com/gchq/CyberChef-server.git /CyberChef-server 10 | RUN npm cache clean --force && \ 11 | npm install /CyberChef-server 12 | ENTRYPOINT ["npm", "--prefix", "/CyberChef-server", "run", "prod"] 13 | -------------------------------------------------------------------------------- /integrations/cyberchef/compose-tests.yml: -------------------------------------------------------------------------------- 1 | services: 2 | cyberchef-server: 3 | build: 4 | context: ../integrations/cyberchef 5 | dockerfile: Dockerfile 6 | image: intelowlproject/cyberchef:test 7 | -------------------------------------------------------------------------------- /integrations/cyberchef/compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | cyberchef-server: 3 | image: intelowlproject/intelowl_cyberchef:${REACT_APP_INTELOWL_VERSION} 4 | container_name: intelowl_cyberchef 5 | restart: unless-stopped 6 | expose: 7 | - '3000' 8 | depends_on: 9 | - uwsgi 10 | -------------------------------------------------------------------------------- /integrations/cyberchef/hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "display path" 4 | pwd 5 | 6 | echo "display dockerfile path" 7 | echo "$DOCKERFILE_PATH" 8 | 9 | echo "current branch" 10 | echo "$SOURCE_BRANCH" 11 | 12 | version_regex='^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' 13 | if [[ "$SOURCE_BRANCH" == "master" || "$SOURCE_BRANCH" == "test_arm" || "$SOURCE_BRANCH" =~ $version_regex ]]; then 14 | echo "The branch is master, proceeding with multi-arch build" 15 | docker buildx create --name multiarch --use 16 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --platform linux/arm64,linux/amd64 --push . 17 | else 18 | echo "The branch is not master, proceeding with classic build" 19 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --push . 20 | fi 21 | -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/clamav/etc/fangfrisch.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | db_url = sqlite:////var/lib/fangfrisch/db.sqlite 3 | local_directory = /var/lib/clamav 4 | interval=12h 5 | on_update_exec = clamdscan --reload 6 | on_update_timeout = 120 7 | log_level = INFO 8 | log_method = console 9 | 10 | [malwarepatrol] 11 | enabled = no 12 | # Replace with your personal Malwarepatrol receipt 13 | receipt = abcd1234 14 | 15 | [sanesecurity] 16 | enabled = yes 17 | 18 | [securiteinfo] 19 | enabled = no 20 | # Replace with your personal SecuriteInfo customer ID 21 | customer_id = abcdef123456 22 | 23 | [urlhaus] 24 | enabled = yes 25 | max_size = 2MB -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/clamav/etc/freshclam.conf: -------------------------------------------------------------------------------- 1 | ############### 2 | # General 3 | ############### 4 | 5 | DatabaseDirectory /var/lib/clamav 6 | DNSDatabaseInfo current.cvd.clamav.net 7 | LogSyslog false 8 | LogTime yes 9 | PidFile /run/clamav/freshclam.pid 10 | Foreground true 11 | UpdateLogFile /var/log/intel_owl/malware_tools_analyzers/clamav/freshclam.log 12 | LogVerbose false 13 | LogSyslog false 14 | LogFacility LOG_LOCAL6 15 | LogFileMaxSize 0 16 | LogRotate true 17 | LogTime true 18 | 19 | ############### 20 | # Updates 21 | ############### 22 | 23 | DatabaseMirror db.local.clamav.net 24 | DatabaseMirror database.clamav.net 25 | ScriptedUpdates yes 26 | Bytecode yes -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/compose-tests.yml: -------------------------------------------------------------------------------- 1 | # All additional integrations should be added following this format only. 2 | 3 | services: 4 | malware_tools_analyzers: 5 | build: 6 | context: ../integrations/malware_tools_analyzers 7 | dockerfile: Dockerfile 8 | image: intelowlproject/intelowl_malware_tools_analyzers:test 9 | -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/compose.yml: -------------------------------------------------------------------------------- 1 | # All additional integrations should be added following this format only. 2 | 3 | services: 4 | malware_tools_analyzers: 5 | image: intelowlproject/intelowl_malware_tools_analyzers:${REACT_APP_INTELOWL_VERSION} 6 | container_name: intelowl_malware_tools_analyzers 7 | restart: unless-stopped 8 | expose: 9 | - "4002" 10 | env_file: 11 | - env_file_integrations 12 | volumes: 13 | - generic_logs:/var/log/intel_owl 14 | - ../integrations/malware_tools_analyzers/clamav/etc:/etc/clamav 15 | - ../integrations/malware_tools_analyzers/clamav/sigs:/var/lib/clamav 16 | - ../integrations/malware_tools_analyzers/qiling/rootfs:/opt/deploy/rootfs 17 | - ../integrations/malware_tools_analyzers/qiling/profiles:/opt/deploy/profiles 18 | depends_on: 19 | - uwsgi 20 | 21 | -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/crontab: -------------------------------------------------------------------------------- 1 | HOME=/var/lib/fangfrisch 2 | LOG_LEVEL=INFO 3 | # minute hour day-of-month month day-of-week user command 4 | */15 * * * * malware_tools_analyzers-user fangfrisch --conf /etc/clamav/fangfrisch.conf refresh 2>&1 >> /var/log/cron.log -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/droidlysis/general.conf: -------------------------------------------------------------------------------- 1 | [tools] 2 | apktool = /root/softs/apktool_2.9.3.jar 3 | baksmali = /root/softs/baksmali-2.5.2.jar 4 | dex2jar = /root/softs/dex-tools-v2.4/d2j-dex2jar.sh 5 | keytool = /usr/bin/keytool 6 | [general] 7 | db_file = droidlysis.db 8 | smali_config = /opt/deploy/droidlysis/conf/smali.conf 9 | wide_config = /opt/deploy/droidlysis/conf/wide.conf 10 | arm_config = /opt/deploy/droidlysis/conf/arm.conf 11 | kit_config = /opt/deploy/droidlysis/conf/kit.conf -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "display path" 4 | pwd 5 | echo "display dockerfile path" 6 | echo "$DOCKERFILE_PATH" 7 | echo "current branch" 8 | echo "$SOURCE_BRANCH" 9 | 10 | version_regex='^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' 11 | if [[ "$SOURCE_BRANCH" == "master" || "$SOURCE_BRANCH" == "test_arm" || "$SOURCE_BRANCH" == "develop_old" || "$SOURCE_BRANCH" =~ $version_regex ]]; then 12 | echo "The branch is master, proceeding with multi-arch build" 13 | docker buildx create --name multiarch --use 14 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --platform linux/arm64,linux/amd64 --push . 15 | else 16 | echo "The branch is not master, proceeding with classic build" 17 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --push . 18 | fi -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/qiling/profiles/README.md: -------------------------------------------------------------------------------- 1 | # Please add your profile files here -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/qiling/rootfs/README.md: -------------------------------------------------------------------------------- 1 | # Please add your rootfs folder here -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/requirements/apkid-requirements.txt: -------------------------------------------------------------------------------- 1 | apkid==2.1.4 -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/requirements/droidlysis-requirements.txt: -------------------------------------------------------------------------------- 1 | # they do not make releases 2 | # if you update this, you should take into considerations all the other dependencies in the Dockerfile too 3 | git+https://github.com/cryptax/droidlysis@c1645a5 -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/requirements/flask-requirements.txt: -------------------------------------------------------------------------------- 1 | # Flask-Shell2HTTP dynamically install the most recent supported version of Flask 2 | # So, if you want reproducible builds, you must explicitly state the flask version you want to install 3 | Flask-Shell2HTTP-fork==1.9.2 4 | flask==3.1.0 5 | gunicorn==23.0.0 6 | fangfrisch==1.9.0 -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/requirements/mobsf-requirements.txt: -------------------------------------------------------------------------------- 1 | mobsfscan==0.4.5 2 | 3 | -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/requirements/peframe-requirements.txt: -------------------------------------------------------------------------------- 1 | peframe-ds==6.1.0 -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/requirements/qiling-requirements.txt: -------------------------------------------------------------------------------- 1 | qiling==1.4.6 -------------------------------------------------------------------------------- /integrations/malware_tools_analyzers/requirements/stringsifter-requirements.txt: -------------------------------------------------------------------------------- 1 | stringsifter==3.20230711 -------------------------------------------------------------------------------- /integrations/nuclei_analyzer/compose-tests.yml: -------------------------------------------------------------------------------- 1 | services: 2 | nuclei_analyzer: 3 | build: 4 | context: ../integrations/nuclei_analyzer 5 | dockerfile: Dockerfile 6 | image: intelowlproject/nuclei_analyzer:test -------------------------------------------------------------------------------- /integrations/nuclei_analyzer/compose.yml: -------------------------------------------------------------------------------- 1 | # All additional integrations should be added following this format only. 2 | 3 | services: 4 | nuclei_analyzer: 5 | image: intelowlproject/nuclei_analyzer:${REACT_APP_INTELOWL_VERSION} 6 | container_name: nuclei_analyzer 7 | restart: unless-stopped 8 | expose: 9 | - "4008" 10 | env_file: 11 | - env_file_integrations 12 | volumes: 13 | - generic_logs:/var/log/intel_owl 14 | depends_on: 15 | - uwsgi 16 | -------------------------------------------------------------------------------- /integrations/nuclei_analyzer/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir -p "${LOG_PATH}" 3 | touch "${LOG_PATH}/gunicorn_access.log" "${LOG_PATH}/gunicorn_errors.log" 4 | chown -R "${USER}":"${USER}" "${LOG_PATH}" 5 | 6 | TEMPLATES_DIR="/opt/nuclei-api/nuclei-templates" 7 | echo "Updating Nuclei templates..." 8 | nuclei -update-template-dir $TEMPLATES_DIR -update-templates 9 | sleep 30 10 | echo "Verifying Nuclei templates..." 11 | if [ ! -d "$TEMPLATES_DIR" ] || [ -z "$(ls -A $TEMPLATES_DIR)" ]; then 12 | echo "Error: Nuclei templates not found or directory is empty. Please check you internet connection. Exiting..." 13 | exit 1 14 | else 15 | echo "Nuclei templates successfully updated." 16 | fi 17 | echo "Templates downloaded successfully. Starting Flask API..." 18 | exec gunicorn 'app:app' \ 19 | --bind '0.0.0.0:4008' \ 20 | --access-logfile "${LOG_PATH}"/gunicorn_access.log \ 21 | --error-logfile "${LOG_PATH}"/gunicorn_errors.log -------------------------------------------------------------------------------- /integrations/nuclei_analyzer/hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "display path" 4 | pwd 5 | echo "display dockerfile path" 6 | echo "$DOCKERFILE_PATH" 7 | echo "current branch" 8 | echo "$SOURCE_BRANCH" 9 | 10 | version_regex='^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' 11 | if [[ "$SOURCE_BRANCH" == "master" || "$SOURCE_BRANCH" == "test_arm" || "$SOURCE_BRANCH" =~ $version_regex ]]; then 12 | echo "The branch is master, proceeding with multi-arch build" 13 | docker buildx create --name multiarch --use 14 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --platform linux/arm64,linux/amd64 --push . 15 | else 16 | echo "The branch is not master, proceeding with classic build" 17 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --push . 18 | fi -------------------------------------------------------------------------------- /integrations/nuclei_analyzer/requirements.txt: -------------------------------------------------------------------------------- 1 | # Flask-Shell2HTTP dynamically install the most recent supported version of Flask 2 | # So, if you want reproducible builds, you must explicitly state the flask version you want to install 3 | Flask-Shell2HTTP-fork==1.9.2 4 | flask==3.1.0 5 | gunicorn==23.0.0 6 | -------------------------------------------------------------------------------- /integrations/pcap_analyzers/compose-tests.yml: -------------------------------------------------------------------------------- 1 | services: 2 | pcap_analyzers: 3 | build: 4 | context: ../integrations/pcap_analyzers 5 | dockerfile: Dockerfile 6 | image: intelowlproject/intelowl_pcap_analyzers:test 7 | -------------------------------------------------------------------------------- /integrations/pcap_analyzers/compose.yml: -------------------------------------------------------------------------------- 1 | # All additional integrations should be added following this format only. 2 | 3 | services: 4 | pcap_analyzers: 5 | image: intelowlproject/intelowl_pcap_analyzers:${REACT_APP_INTELOWL_VERSION} 6 | container_name: intelowl_pcap_analyzers 7 | restart: unless-stopped 8 | expose: 9 | - "4004" 10 | env_file: 11 | - env_file_integrations 12 | volumes: 13 | - generic_logs:/var/log/intel_owl 14 | - ../integrations/pcap_analyzers/config/suricata/etc:/etc/suricata:ro 15 | - ../integrations/pcap_analyzers/config/suricata/rules:/var/lib/suricata/rules/ 16 | depends_on: 17 | - uwsgi 18 | -------------------------------------------------------------------------------- /integrations/pcap_analyzers/config/suricata/etc/disable.conf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/integrations/pcap_analyzers/config/suricata/etc/disable.conf -------------------------------------------------------------------------------- /integrations/pcap_analyzers/config/suricata/etc/enable.conf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/integrations/pcap_analyzers/config/suricata/etc/enable.conf -------------------------------------------------------------------------------- /integrations/pcap_analyzers/config/suricata/etc/update.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/integrations/pcap_analyzers/config/suricata/etc/update.yaml -------------------------------------------------------------------------------- /integrations/pcap_analyzers/config/suricata/rules/custom.rules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/integrations/pcap_analyzers/config/suricata/rules/custom.rules -------------------------------------------------------------------------------- /integrations/pcap_analyzers/crontab: -------------------------------------------------------------------------------- 1 | # remember to keep the newline otherwise the Cron breaks 2 | # once a day 3 | 0 0 * * * /update_signatures.sh 2>&1 >> /var/log/cron.log 4 | -------------------------------------------------------------------------------- /integrations/pcap_analyzers/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir -p "${LOG_PATH}" "${LOG_PATH}"/suricata 3 | touch "${LOG_PATH}"/gunicorn_access.log "${LOG_PATH}"/gunicorn_errors.log "${LOG_PATH}"/suricata/suricata.log 4 | chown -R pcap_analyzers-user:pcap_analyzers-user "${LOG_PATH}" 5 | su pcap_analyzers-user -s /bin/bash 6 | suricata-update update-sources 7 | suricata-update enable-source sslbl/ssl-fp-blacklist 8 | suricata-update enable-source sslbl/ja3-fingerprints 9 | suricata-update enable-source etnetera/aggressive 10 | suricata-update enable-source tgreen/hunting 11 | suricata-update enable-source malsilo/win-malware 12 | suricata-update 13 | crond 14 | crontab /etc/cron.d/suricata 15 | suricata --unix-socket=/tmp/suricata.socket & 16 | exec gunicorn 'app:app' \ 17 | --bind '0.0.0.0:4004' \ 18 | --user "${USER}" \ 19 | --log-level "${LOG_LEVEL}" \ 20 | --access-logfile "${LOG_PATH}"/gunicorn_access.log \ 21 | --error-logfile "${LOG_PATH}"/gunicorn_errors.log 22 | 23 | -------------------------------------------------------------------------------- /integrations/pcap_analyzers/hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "display path" 4 | pwd 5 | echo "display dockerfile path" 6 | echo "$DOCKERFILE_PATH" 7 | echo "current branch" 8 | echo "$SOURCE_BRANCH" 9 | 10 | version_regex='^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' 11 | if [[ "$SOURCE_BRANCH" == "master" || "$SOURCE_BRANCH" == "test_arm" || "$SOURCE_BRANCH" =~ $version_regex ]]; then 12 | echo "The branch is master, proceeding with multi-arch build" 13 | docker buildx create --name multiarch --use 14 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --platform linux/arm64,linux/amd64 --push . 15 | else 16 | echo "The branch is not master, proceeding with classic build" 17 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --push . 18 | fi -------------------------------------------------------------------------------- /integrations/pcap_analyzers/requirements.txt: -------------------------------------------------------------------------------- 1 | # Flask-Shell2HTTP dynamically install the most recent supported version of Flask 2 | # So, if you want reproducible builds, you must explicitly state the flask version you want to install 3 | Flask-Shell2HTTP-fork==1.9.2 4 | flask==3.1.0 5 | gunicorn==23.0.0 6 | PyYAML==6.0 -------------------------------------------------------------------------------- /integrations/pcap_analyzers/update_signatures.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | suricata-update update-sources 3 | suricata-update enable-source sslbl/ssl-fp-blacklist 4 | suricata-update enable-source sslbl/ja3-fingerprints 5 | suricata-update enable-source etnetera/aggressive 6 | suricata-update enable-source tgreen/hunting 7 | suricata-update enable-source malsilo/win-malware 8 | suricata-update 9 | kill "$(pidof suricata)" 10 | suricata --unix-socket=/tmp/suricata.socket & -------------------------------------------------------------------------------- /integrations/phishing_analyzers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/integrations/phishing_analyzers/__init__.py -------------------------------------------------------------------------------- /integrations/phishing_analyzers/analyzers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/integrations/phishing_analyzers/analyzers/__init__.py -------------------------------------------------------------------------------- /integrations/phishing_analyzers/compose-tests.yml: -------------------------------------------------------------------------------- 1 | # All additional integrations should be added following this format only. 2 | 3 | services: 4 | phishing_analyzers: 5 | build: 6 | context: ../integrations/phishing_analyzers 7 | dockerfile: Dockerfile 8 | image: intelowlproject/intelowl_phishing_analyzers:test 9 | -------------------------------------------------------------------------------- /integrations/phishing_analyzers/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | /usr/bin/sudo /usr/bin/mkdir -p /var/log/intel_owl/phishing_analyzers 3 | /usr/bin/sudo /usr/bin/touch /var/log/intel_owl/phishing_analyzers/gunicorn_access.log \ 4 | /var/log/intel_owl/phishing_analyzers/gunicorn_errors.log 5 | /usr/bin/sudo /usr/bin/chown -R phishing-user:phishing-user \ 6 | /opt/deploy/phishing_analyzers /var/log/intel_owl/phishing_analyzers 7 | 8 | /usr/local/bin/gunicorn 'app:app' \ 9 | --bind '0.0.0.0:4005' \ 10 | --log-level "${LOG_LEVEL}" \ 11 | --user phishing-user \ 12 | --group phishing-user \ 13 | --access-logfile /var/log/intel_owl/phishing_analyzers/gunicorn_access.log \ 14 | --error-logfile /var/log/intel_owl/phishing_analyzers/gunicorn_errors.log -------------------------------------------------------------------------------- /integrations/phishing_analyzers/hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "display path" 4 | pwd 5 | echo "display dockerfile path" 6 | echo "$DOCKERFILE_PATH" 7 | echo "current branch" 8 | echo "$SOURCE_BRANCH" 9 | 10 | version_regex='^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' 11 | if [[ "$SOURCE_BRANCH" == "master" || "$SOURCE_BRANCH" == "test_arm" || "$SOURCE_BRANCH" =~ $version_regex ]]; then 12 | echo "The branch is master, proceeding with multi-arch build" 13 | docker buildx create --name multiarch --use 14 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --platform linux/arm64,linux/amd64 --push . 15 | else 16 | echo "The branch is not master, proceeding with classic build" 17 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --push . 18 | fi -------------------------------------------------------------------------------- /integrations/phishing_analyzers/requirements.txt: -------------------------------------------------------------------------------- 1 | # Flask-Shell2HTTP dynamically install the most recent supported version of Flask 2 | # So, if you want reproducible builds, you must explicitly state the flask version you want to install 3 | Flask-Shell2HTTP-fork==1.9.2 4 | # Flask most recent versions require most recent versions of blinker 5 | flask==3.0.3 6 | gunicorn==23.0.0 7 | selenium==4.25.0 8 | selenium-wire==5.1.0 9 | blinker==1.7.0 # selenium-wire depends on this library version <1.8 -------------------------------------------------------------------------------- /integrations/phoneinfoga/compose-tests.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' -------------------------------------------------------------------------------- /integrations/phoneinfoga/compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | phoneinfoga: 3 | container_name: intelowl_phoneinfoga 4 | restart: unless-stopped 5 | image: sundowndev/phoneinfoga:v2.11.0 6 | command: 7 | - "serve" 8 | - "--no-client" 9 | expose: 10 | - "5000" 11 | env_file: 12 | - env_file_integrations 13 | depends_on: 14 | - uwsgi -------------------------------------------------------------------------------- /integrations/thug/Dockerfile: -------------------------------------------------------------------------------- 1 | # This base image is the one currently (02/2025) updated by the maintainer 2 | # but it does not support ARM 3 | FROM thughoneyclient/thug:v6.13 4 | 5 | USER root 6 | ENV PROJECT_PATH=/opt/deploy 7 | ENV LOG_PATH=/var/log/intel_owl/thug 8 | 9 | # 2. Build Flask REST API 10 | WORKDIR ${PROJECT_PATH}/flask 11 | COPY app.py requirements.txt entrypoint.sh ./ 12 | 13 | RUN pip3 install -r requirements.txt --no-cache-dir \ 14 | && mkdir -p ${PROJECT_PATH}/thug \ 15 | && chown -R ${USER}:${USER} . ${PROJECT_PATH}/thug \ 16 | && chmod +x entrypoint.sh 17 | 18 | # Serve Flask application using gunicorn 19 | EXPOSE 4002 20 | ENTRYPOINT ["./entrypoint.sh"] 21 | -------------------------------------------------------------------------------- /integrations/thug/compose-tests.yml: -------------------------------------------------------------------------------- 1 | services: 2 | thug: 3 | build: 4 | context: ../integrations/thug 5 | dockerfile: Dockerfile 6 | image: intelowlproject/intelowl_thug:test 7 | -------------------------------------------------------------------------------- /integrations/thug/compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | thug: 3 | image: intelowlproject/intelowl_thug:${REACT_APP_INTELOWL_VERSION} 4 | container_name: intelowl_thug 5 | restart: unless-stopped 6 | expose: 7 | - "4002" 8 | env_file: 9 | - env_file_integrations 10 | volumes: 11 | - generic_logs:/var/log/intel_owl 12 | depends_on: 13 | - uwsgi 14 | 15 | -------------------------------------------------------------------------------- /integrations/thug/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p "${LOG_PATH}" 3 | touch "${LOG_PATH}"/gunicorn_access.log "${LOG_PATH}"/gunicorn_errors.log "${LOG_PATH}"/thug.log "${LOG_PATH}"/thug_errors.log 4 | chown -R "${USER}":"${USER}" "${LOG_PATH}" 5 | # change user 6 | su thug -s /bin/bash 7 | echo "running gunicorn" 8 | # start flask server 9 | /usr/local/bin/gunicorn 'app:app' \ 10 | --bind '0.0.0.0:4002' \ 11 | --user thug \ 12 | --log-level "${LOG_LEVEL}" \ 13 | --access-logfile "${LOG_PATH}"/gunicorn_access.log \ 14 | --error-logfile "${LOG_PATH}"/gunicorn_errors.log 15 | -------------------------------------------------------------------------------- /integrations/thug/requirements.txt: -------------------------------------------------------------------------------- 1 | # Flask-Shell2HTTP dynamically install the most recent supported version of Flask 2 | # So, if you want reproducible builds, you must explicitly state the flask version you want to install 3 | Flask-Shell2HTTP-fork==1.9.2 4 | flask==3.1.0 5 | gunicorn==23.0.0 -------------------------------------------------------------------------------- /integrations/tor_analyzers/bundled/onionscan: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/integrations/tor_analyzers/bundled/onionscan -------------------------------------------------------------------------------- /integrations/tor_analyzers/compose-tests.yml: -------------------------------------------------------------------------------- 1 | # All additional integrations should be added following this format only. 2 | 3 | services: 4 | tor_analyzers: 5 | build: 6 | context: ../integrations/tor_analyzers 7 | dockerfile: Dockerfile 8 | image: intelowlproject/intelowl_tor_analyzers:test 9 | -------------------------------------------------------------------------------- /integrations/tor_analyzers/compose.yml: -------------------------------------------------------------------------------- 1 | # All additional integrations should be added following this format only. 2 | 3 | services: 4 | tor_analyzers: 5 | image: intelowlproject/intelowl_tor_analyzers:${REACT_APP_INTELOWL_VERSION} 6 | container_name: intelowl_tor_analyzers 7 | restart: unless-stopped 8 | expose: 9 | - "4001" 10 | env_file: 11 | - env_file_integrations 12 | volumes: 13 | - generic_logs:/var/log/intel_owl 14 | depends_on: 15 | - uwsgi 16 | -------------------------------------------------------------------------------- /integrations/tor_analyzers/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir -p "${LOG_PATH}" 3 | touch "${LOG_PATH}/gunicorn_access.log" "${LOG_PATH}/gunicorn_errors.log" 4 | chown -R tor-user:tor-user "${LOG_PATH}" 5 | su tor-user -s /bin/bash 6 | exec tor & 7 | exec gunicorn 'app:app' \ 8 | --bind '0.0.0.0:4001' \ 9 | --user "${USER}" \ 10 | --log-level "${LOG_LEVEL}" \ 11 | --access-logfile "${LOG_PATH}/gunicorn_access.log" \ 12 | --error-logfile "${LOG_PATH}/gunicorn_errors.log" 13 | -------------------------------------------------------------------------------- /integrations/tor_analyzers/hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "display path" 4 | pwd 5 | echo "display dockerfile path" 6 | echo "$DOCKERFILE_PATH" 7 | echo "current branch" 8 | echo "$SOURCE_BRANCH" 9 | 10 | version_regex='^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' 11 | if [[ "$SOURCE_BRANCH" == "master" || "$SOURCE_BRANCH" == "test_arm" || "$SOURCE_BRANCH" =~ $version_regex ]]; then 12 | echo "The branch is master, proceeding with multi-arch build" 13 | docker buildx create --name multiarch --use 14 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --platform linux/arm64,linux/amd64 --push . 15 | else 16 | echo "The branch is not master, proceeding with classic build" 17 | docker buildx build -f "$DOCKERFILE_PATH" -t "$IMAGE_NAME" --push . 18 | fi -------------------------------------------------------------------------------- /integrations/tor_analyzers/requirements.txt: -------------------------------------------------------------------------------- 1 | # Flask-Shell2HTTP dynamically install the most recent supported version of Flask 2 | # So, if you want reproducible builds, you must explicitly state the flask version you want to install 3 | Flask-Shell2HTTP-fork==1.9.2 4 | flask==3.1.0 5 | gunicorn==23.0.0 -------------------------------------------------------------------------------- /intel_owl/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/intel_owl/__init__.py -------------------------------------------------------------------------------- /intel_owl/backends.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from radiusauth.backends import RADIUSRealmBackend 5 | 6 | from configuration.radius_config import GET_SERVER_CUSTOMISED, custom_get_server 7 | 8 | 9 | class CustomRADIUSBackend(RADIUSRealmBackend): 10 | def get_server(self, realm): 11 | if GET_SERVER_CUSTOMISED: 12 | return custom_get_server(self, realm) 13 | else: 14 | return super().get_server(realm) 15 | -------------------------------------------------------------------------------- /intel_owl/consts.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 5 | # See the file 'LICENSE' for copying permission. 6 | 7 | REGEX_EMAIL = r"^[\w\.\+\-]+\@[\w]+\.[a-z]{2,3}$" 8 | REGEX_CVE = r"CVE-\d{4}-\d{4,7}" 9 | REGEX_PASSWORD = r"^[a-zA-Z0-9]{12,}$" 10 | 11 | DEFAULT_SOFT_TIME_LIMIT = 300 12 | -------------------------------------------------------------------------------- /intel_owl/middleware.py: -------------------------------------------------------------------------------- 1 | class WSAuthMiddleware: 2 | def __init__(self, app): 3 | self.app = app 4 | 5 | async def __call__(self, scope, receive, send): 6 | user = scope["user"] 7 | if user.is_anonymous: 8 | return await send({"type": "websocket.close", "code": 1008}) 9 | 10 | return await self.app(scope, receive, send) 11 | -------------------------------------------------------------------------------- /intel_owl/settings/a_secrets.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | from intel_owl import secrets 5 | 6 | # this must be first because the function get_secretes depends from it 7 | AWS_REGION = secrets.get_secret("AWS_REGION", "eu-central-1") 8 | -------------------------------------------------------------------------------- /intel_owl/settings/aws.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | import sys 5 | 6 | from intel_owl import secrets 7 | 8 | # AWS settings 9 | AWS_IAM_ACCESS = secrets.get_secret("AWS_IAM_ACCESS", False) == "True" 10 | if not AWS_IAM_ACCESS: 11 | AWS_ACCESS_KEY_ID = secrets.get_secret("AWS_ACCESS_KEY_ID") 12 | AWS_SECRET_ACCESS_KEY = secrets.get_secret("AWS_SECRET_ACCESS_KEY") 13 | AWS_SECRETS = secrets.get_secret("AWS_SECRETS", False) == "True" 14 | AWS_SQS = secrets.get_secret("AWS_SQS", False) == "True" 15 | if AWS_SQS: 16 | AWS_USER_NUMBER = secrets.get_secret("AWS_USER_NUMBER") 17 | if not AWS_USER_NUMBER: 18 | print("you must specify the USER NUMBER") 19 | sys.exit(4) 20 | 21 | AWS_RDS_IAM_ROLE = secrets.get_secret("AWS_RDS_IAM_ROLE", False) == "True" 22 | -------------------------------------------------------------------------------- /intel_owl/settings/celery.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | # this module must run before the others 5 | 6 | from ._util import get_secret 7 | from .aws import AWS_SQS 8 | 9 | RESULT_BACKEND = "django-db" 10 | BROKER_URL = get_secret("BROKER_URL", None) 11 | if not BROKER_URL: 12 | if AWS_SQS: 13 | BROKER_URL = "sqs://" 14 | else: 15 | BROKER_URL = "redis://redis:6379/1" # 0 is used by channels 16 | 17 | DEFAULT_QUEUE = "default" 18 | BROADCAST_QUEUE = "broadcast" 19 | CONFIG_QUEUE = "config" 20 | 21 | CELERY_QUEUES = get_secret("CELERY_QUEUES", DEFAULT_QUEUE).split(",") 22 | for queue in [DEFAULT_QUEUE, CONFIG_QUEUE]: 23 | if queue not in CELERY_QUEUES: 24 | CELERY_QUEUES.append(queue) 25 | -------------------------------------------------------------------------------- /intel_owl/settings/certego.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | # certego_saas 5 | from ._util import get_secret 6 | from .security import WEB_CLIENT_URL 7 | 8 | HOST_URI = WEB_CLIENT_URL 9 | HOST_NAME = "IntelOwl" 10 | CERTEGO_SAAS = { 11 | "USER_ACCESS_SERIALIZER": "authentication.serializers.UserAccessSerializer", 12 | "HOST_URI": HOST_URI, 13 | "HOST_NAME": HOST_NAME, 14 | "ORGANIZATION_MAX_MEMBERS": get_secret("ORGANIZATION_MAX_MEMBERS", 100), 15 | } 16 | DEFAULT_SLACK_CHANNEL = get_secret("DEFAULT_SLACK_CHANNEL") 17 | SLACK_TOKEN = get_secret("SLACK_TOKEN") 18 | -------------------------------------------------------------------------------- /intel_owl/settings/websocket.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | from intel_owl import secrets 4 | 5 | websockets_url = secrets.get_secret("WEBSOCKETS_URL", "redis://redis:6379/0") 6 | if not websockets_url: 7 | if socket.gethostname() in ["uwsgi", "daphne"]: 8 | raise RuntimeError("Unable to configure websockets. Please set WEBSOCKETS_URL") 9 | else: 10 | ASGI_APPLICATION = "intel_owl.asgi.application" 11 | CHANNEL_LAYERS = { 12 | "default": { 13 | "BACKEND": "channels_redis.core.RedisChannelLayer", 14 | "CONFIG": { 15 | "hosts": [websockets_url], 16 | }, 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /intel_owl/urls.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 5 | # See the file 'LICENSE' for copying permission. 6 | from django.conf import settings 7 | from django.contrib import admin 8 | from django.shortcuts import render 9 | from django.urls import include, path, re_path 10 | 11 | 12 | def render_reactapp(request): 13 | return render(request, "index.html") 14 | 15 | 16 | urlpatterns = [ 17 | path("admin/", admin.site.urls, name="admin"), 18 | path("api/", include("api_app.urls")), 19 | re_path(r"^(?!api|silk)$", render_reactapp), 20 | re_path(r"^(?!api|silk)(?:.*)/?$", render_reactapp), 21 | ] 22 | if settings.STAGE_STAGING or settings.STAGE_LOCAL: 23 | urlpatterns.append(path("silk/", include("silk.urls"), name="silk")) 24 | -------------------------------------------------------------------------------- /intel_owl/wsgi.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | 4 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 5 | # See the file 'LICENSE' for copying permission. 6 | 7 | import os 8 | 9 | from django.core.wsgi import get_wsgi_application 10 | 11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "intel_owl.settings") 12 | 13 | application = get_wsgi_application() 14 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | // this is a config file for VSCode. It allows to suggest the imports in the frontend. 2 | 3 | /* Note: Add "javascript.validate.enable": true in you vs Code config to allow Quick fix to suggest import in frontend. 4 | This trigger other linting errors not checked by the CI, and it's quite annoying. 5 | */ 6 | { 7 | "compilerOptions": { 8 | "checkJs": true, 9 | "jsx": "react" 10 | } 11 | } -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 4 | # See the file 'LICENSE' for copying permission. 5 | 6 | """Django's command-line utility for administrative tasks.""" 7 | import os 8 | import sys 9 | 10 | 11 | def main(): 12 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "intel_owl.settings") 13 | try: 14 | from django.core.management import execute_from_command_line 15 | except ImportError as exc: 16 | raise ImportError( 17 | "Couldn't import Django. Are you sure it's installed and " 18 | "available on your PYTHONPATH environment variable? Did you " 19 | "forget to activate a virtual environment?" 20 | ) from exc 21 | execute_from_command_line(sys.argv) 22 | 23 | 24 | if __name__ == "__main__": 25 | main() 26 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | exclude = ''' 3 | /( 4 | venv 5 | | frontend 6 | | node_modules 7 | )/ 8 | ''' 9 | [tool.isort] 10 | profile = "black" 11 | multi_line_output = 3 12 | use_parentheses = true 13 | known_first_party = ["certego_saas"] 14 | [tool.codereviewdoctor] 15 | disable = ["missing-reverse-migration"] -------------------------------------------------------------------------------- /requirements/certego-requirements.txt: -------------------------------------------------------------------------------- 1 | certego-saas==0.7.11 2 | # While developing for certego-saas, comment the previous line. 3 | # Then, add a line like the one below to your forked repo and your most recent commit 4 | # In this way you can test your changes directly in IntelOwl with the complete application 5 | # git+https://github.com/certego/certego-saas.git@23d699340dca0b90b81d7df43000f53464196c21#egg=certego_saas -------------------------------------------------------------------------------- /requirements/django-server-requirements.txt: -------------------------------------------------------------------------------- 1 | # to allow Watchman to be used with Django Development Server 2 | pywatchman==2.0.0 -------------------------------------------------------------------------------- /requirements/hardcoded-requirements.txt: -------------------------------------------------------------------------------- 1 | # This file is used exclusively to trigger dependabot PR. 2 | # The update of the dependencies here has no actual effect. 3 | # For each updated dependency here you have to update its relative version hardcoded in the code. 4 | # So please add a comment for each dependency explaining where the related code must be updated. 5 | 6 | # docker/Dockerfile 7 | pycti==6.5.1 8 | # integrations/malware_tools_analyzers/Dockerfile 9 | flare-capa==9.0.0 10 | flare-floss==3.1.1 11 | 12 | # other unmanaged versions 13 | # droydlys - they make no new versions, we pin the commit 14 | # goresym - they create releases in the repo 15 | # boxjs - we can get that info from npm packages -------------------------------------------------------------------------------- /requirements/test-requirements.txt: -------------------------------------------------------------------------------- 1 | flake8==7.1.1 2 | black==24.10.0 3 | isort==5.12.0 4 | pre-commit==4.0.1 5 | coverage==7.6.1 -------------------------------------------------------------------------------- /static/Certego.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/static/Certego.png -------------------------------------------------------------------------------- /static/greedybear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/static/greedybear.png -------------------------------------------------------------------------------- /static/gsoc_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/static/gsoc_logo.png -------------------------------------------------------------------------------- /static/honeynet_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/static/honeynet_logo.png -------------------------------------------------------------------------------- /static/intel_owl_negative.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/static/intel_owl_negative.png -------------------------------------------------------------------------------- /static/intel_owl_positive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/static/intel_owl_positive.png -------------------------------------------------------------------------------- /static/threathunter_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/static/threathunter_logo.png -------------------------------------------------------------------------------- /tests/api_app/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/__init__.py -------------------------------------------------------------------------------- /tests/api_app/analyzable_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/analyzable_manager/__init__.py -------------------------------------------------------------------------------- /tests/api_app/analyzers_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/analyzers_manager/__init__.py -------------------------------------------------------------------------------- /tests/api_app/analyzers_manager/file_analyzers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/analyzers_manager/file_analyzers/__init__.py -------------------------------------------------------------------------------- /tests/api_app/analyzers_manager/observable_analyzers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/analyzers_manager/observable_analyzers/__init__.py -------------------------------------------------------------------------------- /tests/api_app/connectors_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/connectors_manager/__init__.py -------------------------------------------------------------------------------- /tests/api_app/data_model_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/data_model_manager/__init__.py -------------------------------------------------------------------------------- /tests/api_app/engines_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/engines_manager/__init__.py -------------------------------------------------------------------------------- /tests/api_app/ingestors_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/ingestors_manager/__init__.py -------------------------------------------------------------------------------- /tests/api_app/investigations_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/investigations_manager/__init__.py -------------------------------------------------------------------------------- /tests/api_app/pivots_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/pivots_manager/__init__.py -------------------------------------------------------------------------------- /tests/api_app/playbooks_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/playbooks_manager/__init__.py -------------------------------------------------------------------------------- /tests/api_app/user_events_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/user_events_manager/__init__.py -------------------------------------------------------------------------------- /tests/api_app/visualizers_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/api_app/visualizers_manager/__init__.py -------------------------------------------------------------------------------- /tests/api_app/visualizers_manager/test_views.py: -------------------------------------------------------------------------------- 1 | # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl 2 | # See the file 'LICENSE' for copying permission. 3 | from typing import Type 4 | 5 | from api_app.visualizers_manager.models import VisualizerConfig 6 | from tests import CustomViewSetTestCase 7 | from tests.api_app.test_views import AbstractConfigViewSetTestCaseMixin 8 | 9 | 10 | class VisualizerConfigViewSetTestCase( 11 | AbstractConfigViewSetTestCaseMixin, CustomViewSetTestCase 12 | ): 13 | URL = "/api/visualizer" 14 | 15 | @classmethod 16 | @property 17 | def model_class(cls) -> Type[VisualizerConfig]: 18 | return VisualizerConfig 19 | -------------------------------------------------------------------------------- /tests/intel_owl/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/intel_owl/__init__.py -------------------------------------------------------------------------------- /tests/test_files.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intelowlproject/IntelOwl/987765d03c7baf0aa1e0182d19b9f74938331f5d/tests/test_files.zip --------------------------------------------------------------------------------