txt2stix 1.0.2__tar.gz → 1.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {txt2stix-1.0.2 → txt2stix-1.0.4}/PKG-INFO +1 -1
- {txt2stix-1.0.2 → txt2stix-1.0.4}/pyproject.toml +1 -1
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/src/test_attack_flow.py +151 -48
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/src/test_main.py +15 -1
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/attack_flow.py +28 -11
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/txt2stix.py +2 -2
- {txt2stix-1.0.2 → txt2stix-1.0.4}/.env.example +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/.env.markdown +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/.github/workflows/create-release.yml +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/.github/workflows/run-tests.yml +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/.gitignore +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/LICENSE +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/README.md +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/docs/README.md +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/docs/stix-mapping.md +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/docs/txt2stix.png +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/extractions/ai/config.yaml +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/extractions/lookup/config.yaml +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/extractions/pattern/config.yaml +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/helpers/mimetype_filename_extension_list.csv +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/helpers/stix_relationship_types.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/helpers/tlds.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/helpers/windows_registry_key_prefix.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/_README.md +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/_generate_lookups.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/attack_pattern.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/campaign.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/country_iso3166_alpha2.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/course_of_action.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/disarm_id_v1_5.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/disarm_name_v1_5.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/extensions.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/identity.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/infrastructure.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/intrusion_set.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/malware.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_atlas_id_v4_5_2.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_atlas_name_v4_5_2.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_attack_enterprise_aliases_v16_0.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_attack_enterprise_id_v16_0.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_attack_enterprise_name_v16_0.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_attack_ics_aliases_v16_0.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_attack_ics_id_v16_0.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_attack_ics_name_v16_0.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_attack_mobile_aliases_v16_0.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_attack_mobile_id_v16_0.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_attack_mobile_name_v16_0.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_capec_id_v3_9.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_capec_name_v3_9.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_cwe_id_v4_15.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_cwe_name_v4_15.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/threat_actor.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/tld.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/tool.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/includes/tests/test_cases.yaml +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/requirements.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/README.md +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/ai_country.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/ai_mitre_attack_enterprise.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/ai_mitre_attack_ics.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/ai_mitre_attack_mobile.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/ai_mitre_capec.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/ai_mitre_cwe.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/all_cases.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_autonomous_system_number.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_bank_card_all.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_bank_card_amex.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_bank_card_diners.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_bank_card_discover.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_bank_card_jcb.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_bank_card_mastercard.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_bank_card_union_pay.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_bank_card_visa.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_country_alpha2.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_cpe_uri.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_cryptocurrency_btc_transaction.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_cryptocurrency_btc_wallet.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_cryptocurrency_eth_transaction.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_cryptocurrency_eth_wallet.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_cryptocurrency_xmr_transaction.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_cryptocurrency_xmr_wallet.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_cve_id.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_directory_unix.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_directory_unix_file.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_directory_windows.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_directory_windows_with_file.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_disarm.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_disarm_name.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_domain_name_only.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_domain_name_subdomain.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_email_address.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_file_hash_md5.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_file_hash_sha_1.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_file_hash_sha_224.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_file_hash_sha_256.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_file_hash_sha_384.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_file_hash_sha_512.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_file_name.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_host_name.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_host_name_file.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_host_name_path.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_host_name_subdomain.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_host_name_url.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_iban_number.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_ipv4_address_cidr.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_ipv4_address_only.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_ipv4_address_port.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_ipv6_address_cidr.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_ipv6_address_only.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_ipv6_address_port.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mac_address.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_atlas.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_atlas_name.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_attack_enterprise.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_attack_enterprise_aliases.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_attack_enterprise_name.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_attack_ics.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_attack_ics_aliases.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_attack_ics_name.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_attack_mobile.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_attack_mobile_aliases.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_attack_mobile_name.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_capec.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_capec_name.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_cwe.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_mitre_cwe_name.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_phone_number.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_url.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_url_file.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_url_path.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_user_agent.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/generic_windows_registry_key.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/lookup_attack_pattern.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/lookup_campaign.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/lookup_course_of_action.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/lookup_identity.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/lookup_infrastructure.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/lookup_intrusion_set.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/lookup_malware.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/lookup_threat_actor.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/extraction_types/lookup_tool.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/attack_flow_demo.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/attack_navigator_demo.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/basic_relationship.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/char_length_too_long.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/descriptive_for_ai_relationships_1.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/disarm_demo.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/embedded_img_ignore.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/embedded_link_ignore.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/ip1.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/ip2.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/known_whitelist_match.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/mitre_attack_enterprise_ai_demo.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/mitre_attack_enterprise_lookup_demo.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/mixed_extractions.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/not_security_content.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/test_ai_hash_error_with_stix2_lib.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/test_aliases.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/test_extraction_boundary.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/manually_generated_reports/test_extraction_escapes.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/real_intel_reports/APT28-Center-of-Storm-2017.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/real_intel_reports/Bitdefender-Labs-Report-X-creat6958-en-EN.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/real_intel_reports/FireEyeAPT39.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/real_intel_reports/France_CERT_APT31_Pakdoor_TLPWHITE.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/real_intel_reports/Group-IB_Ransomware_Uncovered_whitepaper_eng.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/real_intel_reports/JOINT_CSA_HUNTING_RU_INTEL_SNAKE_MALWARE_20230509.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/real_intel_reports/TA22-0126-QAKBOT-analysis-TLP-GREEN.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/real_intel_reports/dinners_card.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/real_intel_reports/mandiant-apt1.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/data/real_intel_reports/mykings_report_final.txt +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/manual-tests/cases-ai-relationships.md +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/manual-tests/cases-extraction-type-ai.md +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/manual-tests/cases-extraction-type-lookup.md +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/manual-tests/cases-extraction-type-pattern.md +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/manual-tests/cases-standard-tests.md +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/scripts/generate_simple_extraction_test_cases_txt_files.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/src/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/src/test_bundler.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/src/test_extractors.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/src/test_indicator.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/src/test_lookups.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/src/test_run_txt2stix.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/src/test_utils.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/tests/src/utils.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/ai_extractor/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/ai_extractor/anthropic.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/ai_extractor/base.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/ai_extractor/deepseek.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/ai_extractor/gemini.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/ai_extractor/openai.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/ai_extractor/openrouter.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/ai_extractor/prompts.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/ai_extractor/utils.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/bundler.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/common.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/extractions.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/indicator.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/lookups.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/base_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/card/README.md +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/card/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/card/amex_card_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/card/diners_card_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/card/discover_card_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/card/jcb_card_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/card/master_card_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/card/union_card_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/card/visa_card_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/crypto/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/crypto/btc_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/directory/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/directory/unix_directory_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/directory/unix_file_path_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/directory/windows_directory_path_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/directory/windows_file_path_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/domain/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/domain/domain_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/domain/hostname_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/domain/sub_domain_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/hashes/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/hashes/md5_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/hashes/sha1_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/hashes/sha224_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/hashes/sha2_256_exactor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/hashes/sha2_512_exactor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/hashes/sha3_256_exactor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/hashes/sha3_512_exactor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/helper.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/ip/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/ip/ipv4_cidr_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/ip/ipv4_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/ip/ipv4_port_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/ip/ipv6_cidr_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/ip/ipv6_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/ip/ipv6_port_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/others/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/others/asn_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/others/cpe_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/others/cve_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/others/email_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/others/filename_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/others/iban_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/others/mac_address_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/others/phonenumber_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/others/user_agent_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/others/windows_registry_key_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/url/__init__.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/url/url_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/url/url_file_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/pattern/extractors/url/url_path_extractor.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/retriever.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/stix.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix/utils.py +0 -0
- {txt2stix-1.0.2 → txt2stix-1.0.4}/txt2stix.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: txt2stix
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.4
|
4
4
|
Summary: txt2stix is a Python script that is designed to identify and extract IoCs and TTPs from text files, identify the relationships between them, convert them to STIX 2.1 objects, and output as a STIX 2.1 bundle.
|
5
5
|
Project-URL: Homepage, https://github.com/muchdogesec/txt2stix
|
6
6
|
Project-URL: Issues, https://github.com/muchdogesec/txt2stix/issues
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "txt2stix"
|
7
|
-
version = "1.0.
|
7
|
+
version = "1.0.4"
|
8
8
|
authors = [{ name = "dogesec" }]
|
9
9
|
maintainers = [{ name = "dogesec" }]
|
10
10
|
description = "txt2stix is a Python script that is designed to identify and extract IoCs and TTPs from text files, identify the relationships between them, convert them to STIX 2.1 objects, and output as a STIX 2.1 bundle."
|
@@ -3,9 +3,7 @@ import pytest
|
|
3
3
|
from unittest.mock import MagicMock, patch
|
4
4
|
from stix2extensions._extensions import attack_flow_ExtensionDefinitionSMO
|
5
5
|
|
6
|
-
from txt2stix.ai_extractor.utils import
|
7
|
-
AttackFlowList,
|
8
|
-
)
|
6
|
+
from txt2stix.ai_extractor.utils import AttackFlowList, AttackFlowItem
|
9
7
|
from txt2stix.attack_flow import (
|
10
8
|
create_navigator_layer,
|
11
9
|
get_all_tactics,
|
@@ -55,6 +53,7 @@ def test_parse_flow__no_success(dummy_report):
|
|
55
53
|
success=False,
|
56
54
|
matrix="enterprise",
|
57
55
|
items=[],
|
56
|
+
tactic_selection=[],
|
58
57
|
),
|
59
58
|
None,
|
60
59
|
None,
|
@@ -71,28 +70,28 @@ def test_get_techniques_from_extracted_objects(dummy_objects):
|
|
71
70
|
"T0814": {
|
72
71
|
"domain": "ics-attack",
|
73
72
|
"name": "Denial of Service",
|
74
|
-
"possible_tactics": {"
|
73
|
+
"possible_tactics": {"inhibit-response-function": "TA0107"},
|
75
74
|
"id": "T0814",
|
76
75
|
"platforms": [],
|
77
76
|
},
|
78
77
|
"T0887": {
|
79
78
|
"domain": "ics-attack",
|
80
79
|
"name": "Wireless Sniffing",
|
81
|
-
"possible_tactics": {"
|
80
|
+
"possible_tactics": {"discovery": "TA0102", "collection": "TA0100"},
|
82
81
|
"id": "T0887",
|
83
82
|
"platforms": [],
|
84
83
|
},
|
85
84
|
"T1505.001": {
|
86
85
|
"domain": "enterprise-attack",
|
87
86
|
"name": "SQL Stored Procedures",
|
88
|
-
"possible_tactics": {"
|
87
|
+
"possible_tactics": {"persistence": "TA0003"},
|
89
88
|
"id": "T1505.001",
|
90
89
|
"platforms": ["Windows", "Linux"],
|
91
90
|
},
|
92
91
|
"T1555.002": {
|
93
92
|
"domain": "enterprise-attack",
|
94
93
|
"name": "Securityd Memory",
|
95
|
-
"possible_tactics": {"
|
94
|
+
"possible_tactics": {"credential-access": "TA0006"},
|
96
95
|
"id": "T1555.002",
|
97
96
|
"platforms": ["Linux", "macOS"],
|
98
97
|
},
|
@@ -128,7 +127,7 @@ def test_extract_attack_flow_and_navigator(dummy_objects, dummy_report):
|
|
128
127
|
"txt2stix.attack_flow.create_navigator_layer"
|
129
128
|
) as mock_create_navigator_layer,
|
130
129
|
):
|
131
|
-
|
130
|
+
# ================= Both flow and navigator ===================
|
132
131
|
flow, nav = extract_attack_flow_and_navigator(
|
133
132
|
bundler, text, True, True, ai_extractor
|
134
133
|
)
|
@@ -151,7 +150,7 @@ def test_extract_attack_flow_and_navigator(dummy_objects, dummy_report):
|
|
151
150
|
mock_create_navigator_layer.reset_mock()
|
152
151
|
mock_extract_flow.reset_mock()
|
153
152
|
|
154
|
-
|
153
|
+
# ================= only flow ===================
|
155
154
|
flow, nav = extract_attack_flow_and_navigator(
|
156
155
|
bundler, text, True, False, ai_extractor
|
157
156
|
)
|
@@ -169,7 +168,7 @@ def test_extract_attack_flow_and_navigator(dummy_objects, dummy_report):
|
|
169
168
|
mock_create_navigator_layer.reset_mock()
|
170
169
|
mock_extract_flow.reset_mock()
|
171
170
|
|
172
|
-
|
171
|
+
# ================= only navigator ===================
|
173
172
|
flow, nav = extract_attack_flow_and_navigator(
|
174
173
|
bundler, text, False, True, ai_extractor
|
175
174
|
)
|
@@ -185,6 +184,21 @@ def test_extract_attack_flow_and_navigator(dummy_objects, dummy_report):
|
|
185
184
|
bundler.report, bundler.summary, mock_extract_flow.return_value, techniques
|
186
185
|
)
|
187
186
|
|
187
|
+
### reset mocks
|
188
|
+
mock_parse_flow.reset_mock()
|
189
|
+
mock_create_navigator_layer.reset_mock()
|
190
|
+
mock_extract_flow.reset_mock()
|
191
|
+
# ============ no technique object ============
|
192
|
+
bundler.bundle.objects = []
|
193
|
+
flow, nav = extract_attack_flow_and_navigator(
|
194
|
+
bundler, text, True, True, ai_extractor
|
195
|
+
)
|
196
|
+
mock_extract_flow.assert_not_called()
|
197
|
+
assert (flow, nav) == (None, None)
|
198
|
+
mock_parse_flow.assert_not_called()
|
199
|
+
|
200
|
+
mock_create_navigator_layer.assert_not_called()
|
201
|
+
|
188
202
|
|
189
203
|
def test_create_navigator_layer(dummy_report):
|
190
204
|
summary = "this is a summary"
|
@@ -202,15 +216,36 @@ def test_create_navigator_layer(dummy_report):
|
|
202
216
|
"TA91": "exfiltration",
|
203
217
|
}
|
204
218
|
flow.items = [
|
205
|
-
SimpleNamespace(
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
SimpleNamespace(
|
211
|
-
|
212
|
-
|
213
|
-
|
219
|
+
SimpleNamespace(
|
220
|
+
attack_technique_id="T0001",
|
221
|
+
attack_tactic_id="TA01",
|
222
|
+
description="description 1",
|
223
|
+
),
|
224
|
+
SimpleNamespace(
|
225
|
+
attack_technique_id="T0003",
|
226
|
+
attack_tactic_id="TA03",
|
227
|
+
description="description 2",
|
228
|
+
),
|
229
|
+
SimpleNamespace(
|
230
|
+
attack_technique_id="T1001",
|
231
|
+
attack_tactic_id="TA11",
|
232
|
+
description="description 3",
|
233
|
+
),
|
234
|
+
SimpleNamespace(
|
235
|
+
attack_technique_id="T1002",
|
236
|
+
attack_tactic_id="TA12",
|
237
|
+
description="description 4",
|
238
|
+
),
|
239
|
+
SimpleNamespace(
|
240
|
+
attack_technique_id="T2001",
|
241
|
+
attack_tactic_id="TA11",
|
242
|
+
description="description 28jhsjhs",
|
243
|
+
),
|
244
|
+
SimpleNamespace(
|
245
|
+
attack_technique_id="T2003",
|
246
|
+
attack_tactic_id="TA91",
|
247
|
+
description="description sasa",
|
248
|
+
),
|
214
249
|
]
|
215
250
|
techniques = {
|
216
251
|
"T0001": dict(
|
@@ -232,25 +267,31 @@ def test_create_navigator_layer(dummy_report):
|
|
232
267
|
|
233
268
|
retval = create_navigator_layer(dummy_report, summary, flow, techniques)
|
234
269
|
assert len(retval) == 3
|
235
|
-
print(retval)
|
236
270
|
assert retval == [
|
237
271
|
{
|
238
272
|
"version": "4.5",
|
239
273
|
"name": "some markdown document",
|
240
274
|
"domain": "enterprise-attack",
|
241
275
|
"description": "this is a summary",
|
242
|
-
"techniques": [
|
243
|
-
{"techniqueID": "T0001", "tactic": "initial-access"},
|
244
|
-
{"techniqueID": "T0002", "tactic": "lateral-movement"},
|
245
|
-
{"techniqueID": "T0003", "tactic": "command-and-control"},
|
246
|
-
],
|
276
|
+
"techniques": [],
|
247
277
|
"gradient": {
|
248
278
|
"colors": ["#ffffff", "#ff6666"],
|
249
279
|
"minValue": 0,
|
250
280
|
"maxValue": 100,
|
251
281
|
},
|
252
282
|
"legendItems": [],
|
253
|
-
"metadata": [
|
283
|
+
"metadata": [
|
284
|
+
{
|
285
|
+
"name": "report_id",
|
286
|
+
"value": "report--9c88fbcb-8c0d-4124-868b-3dcb1e9b696c",
|
287
|
+
}
|
288
|
+
],
|
289
|
+
"links": [
|
290
|
+
{
|
291
|
+
"label": "Generated using txt2stix",
|
292
|
+
"url": "https://github.com/muchdogesec/txt2stix/",
|
293
|
+
}
|
294
|
+
],
|
254
295
|
"layout": {"layout": "side"},
|
255
296
|
},
|
256
297
|
{
|
@@ -258,18 +299,25 @@ def test_create_navigator_layer(dummy_report):
|
|
258
299
|
"name": "some markdown document",
|
259
300
|
"domain": "ics-attack",
|
260
301
|
"description": "this is a summary",
|
261
|
-
"techniques": [
|
262
|
-
{"techniqueID": "T1001", "tactic": "initial-access"},
|
263
|
-
{"techniqueID": "T1002", "tactic": "lateral-movement"},
|
264
|
-
{"techniqueID": "T1003", "tactic": "command-and-control"},
|
265
|
-
],
|
302
|
+
"techniques": [],
|
266
303
|
"gradient": {
|
267
304
|
"colors": ["#ffffff", "#ff6666"],
|
268
305
|
"minValue": 0,
|
269
306
|
"maxValue": 100,
|
270
307
|
},
|
271
308
|
"legendItems": [],
|
272
|
-
"metadata": [
|
309
|
+
"metadata": [
|
310
|
+
{
|
311
|
+
"name": "report_id",
|
312
|
+
"value": "report--9c88fbcb-8c0d-4124-868b-3dcb1e9b696c",
|
313
|
+
}
|
314
|
+
],
|
315
|
+
"links": [
|
316
|
+
{
|
317
|
+
"label": "Generated using txt2stix",
|
318
|
+
"url": "https://github.com/muchdogesec/txt2stix/",
|
319
|
+
}
|
320
|
+
],
|
273
321
|
"layout": {"layout": "side"},
|
274
322
|
},
|
275
323
|
{
|
@@ -277,18 +325,25 @@ def test_create_navigator_layer(dummy_report):
|
|
277
325
|
"name": "some markdown document",
|
278
326
|
"domain": "mobile-attack",
|
279
327
|
"description": "this is a summary",
|
280
|
-
"techniques": [
|
281
|
-
{"techniqueID": "T2001", "tactic": "initial-access"},
|
282
|
-
{"techniqueID": "T2002", "tactic": "persistence"},
|
283
|
-
{"techniqueID": "T2003", "tactic": "exfiltration"},
|
284
|
-
],
|
328
|
+
"techniques": [],
|
285
329
|
"gradient": {
|
286
330
|
"colors": ["#ffffff", "#ff6666"],
|
287
331
|
"minValue": 0,
|
288
332
|
"maxValue": 100,
|
289
333
|
},
|
290
334
|
"legendItems": [],
|
291
|
-
"metadata": [
|
335
|
+
"metadata": [
|
336
|
+
{
|
337
|
+
"name": "report_id",
|
338
|
+
"value": "report--9c88fbcb-8c0d-4124-868b-3dcb1e9b696c",
|
339
|
+
}
|
340
|
+
],
|
341
|
+
"links": [
|
342
|
+
{
|
343
|
+
"label": "Generated using txt2stix",
|
344
|
+
"url": "https://github.com/muchdogesec/txt2stix/",
|
345
|
+
}
|
346
|
+
],
|
292
347
|
"layout": {"layout": "side"},
|
293
348
|
},
|
294
349
|
]
|
@@ -307,8 +362,20 @@ def test_create_navigator_layer__real_flow(dummy_report, dummy_flow, dummy_objec
|
|
307
362
|
"domain": "ics-attack",
|
308
363
|
"description": "a summary",
|
309
364
|
"techniques": [
|
310
|
-
{
|
311
|
-
|
365
|
+
{
|
366
|
+
"techniqueID": "T0814",
|
367
|
+
"tactic": "inhibit-response-function",
|
368
|
+
"score": 100,
|
369
|
+
"showSubtechniques": True,
|
370
|
+
"comment": "The SQL injection requests lead to a denial of service condition, disrupting the availability of the targeted service.",
|
371
|
+
},
|
372
|
+
{
|
373
|
+
"techniqueID": "T0887",
|
374
|
+
"tactic": "discovery",
|
375
|
+
"score": 100,
|
376
|
+
"showSubtechniques": True,
|
377
|
+
"comment": "The attack begins by using Wireshark to sniff network packets with a specific source, indicating a reconnaissance or discovery phase to gather information about the network traffic.",
|
378
|
+
},
|
312
379
|
],
|
313
380
|
"gradient": {
|
314
381
|
"colors": ["#ffffff", "#ff6666"],
|
@@ -316,7 +383,18 @@ def test_create_navigator_layer__real_flow(dummy_report, dummy_flow, dummy_objec
|
|
316
383
|
"maxValue": 100,
|
317
384
|
},
|
318
385
|
"legendItems": [],
|
319
|
-
"metadata": [
|
386
|
+
"metadata": [
|
387
|
+
{
|
388
|
+
"name": "report_id",
|
389
|
+
"value": "report--9c88fbcb-8c0d-4124-868b-3dcb1e9b696c",
|
390
|
+
}
|
391
|
+
],
|
392
|
+
"links": [
|
393
|
+
{
|
394
|
+
"label": "Generated using txt2stix",
|
395
|
+
"url": "https://github.com/muchdogesec/txt2stix/",
|
396
|
+
}
|
397
|
+
],
|
320
398
|
"layout": {"layout": "side"},
|
321
399
|
},
|
322
400
|
{
|
@@ -325,8 +403,20 @@ def test_create_navigator_layer__real_flow(dummy_report, dummy_flow, dummy_objec
|
|
325
403
|
"domain": "enterprise-attack",
|
326
404
|
"description": "a summary",
|
327
405
|
"techniques": [
|
328
|
-
{
|
329
|
-
|
406
|
+
{
|
407
|
+
"techniqueID": "T1505.001",
|
408
|
+
"tactic": "persistence",
|
409
|
+
"score": 100,
|
410
|
+
"showSubtechniques": True,
|
411
|
+
"comment": "A series of SQL injection requests are sent to a specific port, potentially to establish persistence or manipulate database operations.",
|
412
|
+
},
|
413
|
+
{
|
414
|
+
"techniqueID": "T1555.002",
|
415
|
+
"tactic": "credential-access",
|
416
|
+
"score": 100,
|
417
|
+
"showSubtechniques": True,
|
418
|
+
"comment": "An additional method is employed to bypass Securityd, likely to gain unauthorized access to credentials or sensitive information.",
|
419
|
+
},
|
330
420
|
],
|
331
421
|
"gradient": {
|
332
422
|
"colors": ["#ffffff", "#ff6666"],
|
@@ -334,7 +424,18 @@ def test_create_navigator_layer__real_flow(dummy_report, dummy_flow, dummy_objec
|
|
334
424
|
"maxValue": 100,
|
335
425
|
},
|
336
426
|
"legendItems": [],
|
337
|
-
"metadata": [
|
427
|
+
"metadata": [
|
428
|
+
{
|
429
|
+
"name": "report_id",
|
430
|
+
"value": "report--9c88fbcb-8c0d-4124-868b-3dcb1e9b696c",
|
431
|
+
}
|
432
|
+
],
|
433
|
+
"links": [
|
434
|
+
{
|
435
|
+
"label": "Generated using txt2stix",
|
436
|
+
"url": "https://github.com/muchdogesec/txt2stix/",
|
437
|
+
}
|
438
|
+
],
|
338
439
|
"layout": {"layout": "side"},
|
339
440
|
},
|
340
441
|
]
|
@@ -623,33 +724,35 @@ def dummy_flow():
|
|
623
724
|
"items": [
|
624
725
|
{
|
625
726
|
"position": 0,
|
626
|
-
"attack_tactic_id": "TA0102",
|
627
727
|
"attack_technique_id": "T0887",
|
628
728
|
"name": "Packet Sniffing with Wireshark",
|
629
729
|
"description": "The attack begins by using Wireshark to sniff network packets with a specific source, indicating a reconnaissance or discovery phase to gather information about the network traffic.",
|
630
730
|
},
|
631
731
|
{
|
632
732
|
"position": 1,
|
633
|
-
"attack_tactic_id": "TA0003",
|
634
733
|
"attack_technique_id": "T1505.001",
|
635
734
|
"name": "SQL Injection for Persistence",
|
636
735
|
"description": "A series of SQL injection requests are sent to a specific port, potentially to establish persistence or manipulate database operations.",
|
637
736
|
},
|
638
737
|
{
|
639
738
|
"position": 2,
|
640
|
-
"attack_tactic_id": "TA0107",
|
641
739
|
"attack_technique_id": "T0814",
|
642
740
|
"name": "Denial of Service via SQLi",
|
643
741
|
"description": "The SQL injection requests lead to a denial of service condition, disrupting the availability of the targeted service.",
|
644
742
|
},
|
645
743
|
{
|
646
744
|
"position": 3,
|
647
|
-
"attack_tactic_id": "TA0006",
|
648
745
|
"attack_technique_id": "T1555.002",
|
649
746
|
"name": "Bypassing Securityd",
|
650
747
|
"description": "An additional method is employed to bypass Securityd, likely to gain unauthorized access to credentials or sensitive information.",
|
651
748
|
},
|
652
749
|
],
|
653
750
|
"success": True,
|
751
|
+
"tactic_selection": [
|
752
|
+
("T0887", "discovery"),
|
753
|
+
("T1505.001", "persistence"),
|
754
|
+
("T0814", "inhibit-response-function"),
|
755
|
+
("T1555.002", "credential-access"),
|
756
|
+
],
|
654
757
|
}
|
655
758
|
)
|
@@ -146,7 +146,21 @@ def test_parse_args_fails(monkeypatch):
|
|
146
146
|
"standard",
|
147
147
|
"--ai_create_attack_flow",
|
148
148
|
])
|
149
|
-
with pytest.raises(argparse.ArgumentError, match="--ai_create_attack_flow
|
149
|
+
with pytest.raises(argparse.ArgumentError, match="argument --ai_create_attack_flow: --ai_settings_relationships must be set"):
|
150
|
+
parse_args()
|
151
|
+
|
152
|
+
|
153
|
+
monkeypatch.setattr(sys, 'argv', [
|
154
|
+
"program",
|
155
|
+
"--input-file",
|
156
|
+
tmp.name,
|
157
|
+
"--name",
|
158
|
+
"a",
|
159
|
+
"--relationship_mode",
|
160
|
+
"standard",
|
161
|
+
"--ai_create_attack_navigator_layer",
|
162
|
+
])
|
163
|
+
with pytest.raises(argparse.ArgumentError, match="argument --ai_create_attack_navigator_layer: --ai_settings_relationships must be set"):
|
150
164
|
parse_args()
|
151
165
|
|
152
166
|
monkeypatch.setattr(sys, 'argv', [
|
@@ -21,14 +21,14 @@ def parse_flow(report, flow: AttackFlowList, techniques, tactics):
|
|
21
21
|
for i, item in enumerate(flow.items):
|
22
22
|
try:
|
23
23
|
technique = techniques[item.attack_technique_id]
|
24
|
-
tactic_id = technique[
|
24
|
+
tactic_id = technique["possible_tactics"][
|
25
|
+
flow.tactic_mapping[item.attack_technique_id]
|
26
|
+
]
|
25
27
|
technique_obj = technique["stix_obj"]
|
26
28
|
tactic_obj = tactics[technique["domain"]][tactic_id]
|
27
29
|
action_obj = AttackAction(
|
28
30
|
**{
|
29
|
-
"id": flow_id(
|
30
|
-
report["id"], item.attack_technique_id, tactic_id
|
31
|
-
),
|
31
|
+
"id": flow_id(report["id"], item.attack_technique_id, tactic_id),
|
32
32
|
"effect_refs": [f"attack-action--{str(uuid.uuid4())}"],
|
33
33
|
"technique_id": item.attack_technique_id,
|
34
34
|
"technique_ref": technique_obj["id"],
|
@@ -149,14 +149,21 @@ def get_techniques_from_extracted_objects(objects: dict, tactics: dict):
|
|
149
149
|
|
150
150
|
def create_navigator_layer(report, summary, flow: AttackFlowList, techniques):
|
151
151
|
domains = {}
|
152
|
+
comments = {item.attack_technique_id: item.description for item in flow.items}
|
152
153
|
for technique in techniques.values():
|
153
154
|
domain_techniques = domains.setdefault(technique["domain"], [])
|
154
155
|
technique_id = technique["id"]
|
155
156
|
if technique_id not in flow.tactic_mapping:
|
156
157
|
continue
|
157
|
-
|
158
|
-
|
158
|
+
technique_item = dict(
|
159
|
+
techniqueID=technique_id,
|
160
|
+
tactic=flow.tactic_mapping[technique_id],
|
161
|
+
score=100,
|
162
|
+
showSubtechniques=True,
|
159
163
|
)
|
164
|
+
if comment := comments.get(technique_id):
|
165
|
+
technique_item["comment"] = comment
|
166
|
+
domain_techniques.append(technique_item)
|
160
167
|
|
161
168
|
retval = []
|
162
169
|
|
@@ -174,7 +181,13 @@ def create_navigator_layer(report, summary, flow: AttackFlowList, techniques):
|
|
174
181
|
"maxValue": 100,
|
175
182
|
},
|
176
183
|
"legendItems": [],
|
177
|
-
"metadata": [],
|
184
|
+
"metadata": [{"name": "report_id", "value": report.id}],
|
185
|
+
"links": [
|
186
|
+
{
|
187
|
+
"label": "Generated using txt2stix",
|
188
|
+
"url": "https://github.com/muchdogesec/txt2stix/",
|
189
|
+
}
|
190
|
+
],
|
178
191
|
"layout": {"layout": "side"},
|
179
192
|
}
|
180
193
|
)
|
@@ -191,10 +204,12 @@ def extract_attack_flow_and_navigator(
|
|
191
204
|
ex: BaseAIExtractor = ai_settings_relationships
|
192
205
|
tactics = get_all_tactics()
|
193
206
|
techniques = get_techniques_from_extracted_objects(bundler.bundle.objects, tactics)
|
207
|
+
if not techniques:
|
208
|
+
return None, None
|
209
|
+
|
194
210
|
logged_techniques = [
|
195
|
-
|
196
|
-
|
197
|
-
]
|
211
|
+
{k: v for k, v in t.items() if k != "stix_obj"} for t in techniques.values()
|
212
|
+
]
|
198
213
|
logging.debug(f"parsed techniques: {json.dumps(logged_techniques, indent=4)}")
|
199
214
|
|
200
215
|
flow = ex.extract_attack_flow(preprocessed_text, techniques)
|
@@ -204,5 +219,7 @@ def extract_attack_flow_and_navigator(
|
|
204
219
|
bundler.flow_objects = parse_flow(bundler.report, flow, techniques, tactics)
|
205
220
|
|
206
221
|
if ai_create_attack_navigator_layer:
|
207
|
-
navigator = create_navigator_layer(
|
222
|
+
navigator = create_navigator_layer(
|
223
|
+
bundler.report, bundler.summary, flow, techniques
|
224
|
+
)
|
208
225
|
return flow, navigator
|
@@ -440,11 +440,11 @@ def main():
|
|
440
440
|
output_path = output_dir/f"{bundler.bundle.id}.json"
|
441
441
|
output_path.write_text(out)
|
442
442
|
logger.info(f"Wrote bundle output to `{output_path}`")
|
443
|
-
data_path = output_dir/"data.json"
|
443
|
+
data_path = output_dir/f"data--{args.report_id}.json"
|
444
444
|
data_path.write_text(data.model_dump_json(indent=4))
|
445
445
|
logger.info(f"Wrote data output to `{data_path}`")
|
446
446
|
for nav_layer in data.navigator_layer or []:
|
447
|
-
nav_path = output_dir/f"navigator-{nav_layer['domain']}.json"
|
447
|
+
nav_path = output_dir/f"navigator-{nav_layer['domain']}----{args.report_id}.json"
|
448
448
|
nav_path.write_text(json.dumps(nav_layer, indent=4))
|
449
449
|
logger.info(f"Wrote navigator output to `{nav_path}`")
|
450
450
|
except argparse.ArgumentError as e:
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{txt2stix-1.0.2 → txt2stix-1.0.4}/includes/lookups/mitre_attack_enterprise_aliases_v16_0.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|