From fdd5bce6aa95bc5aa8411de196d4c8f2a23eea89 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Fri, 2 Jul 2021 14:32:11 +0200 Subject: [PATCH] virustotal module and reworked threading of pre-checkers --- .gitignore | 1 + config/msf_cve-db.txt | 9 +++ emba.sh | 43 ++++++++++-- helpers/print.sh | 1 + modules/P02_firmware_bin_file_check.sh | 2 + modules/P03_firmware_virustotal_check.sh | 78 ++++++++++++++++++++++ modules/P05_firmware_bin_extractor.sh | 3 + modules/P07_firmware_bin_base_analyzer.sh | 2 + modules/S09_firmware_base_version_check.sh | 28 ++++---- 9 files changed, 149 insertions(+), 18 deletions(-) create mode 100755 modules/P03_firmware_virustotal_check.sh diff --git a/.gitignore b/.gitignore index 16b2f142..ee6e8161 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ log*/ dir-combined.yara external/ !external/.keep +config/vt_api_key.txt diff --git a/config/msf_cve-db.txt b/config/msf_cve-db.txt index 968da633..7d562a69 100644 --- a/config/msf_cve-db.txt +++ b/config/msf_cve-db.txt @@ -200,6 +200,7 @@ /usr/share/metasploit-framework/modules/auxiliary/scanner/http/wildfly_traversal.rb:CVE-2014-7816 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/intel_amt_digest_bypass.rb:CVE-2017-5689 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/wordpress_login_enum.rb:CVE-2009-2335 +/usr/share/metasploit-framework/modules/auxiliary/scanner/http/gavazzi_em_login_loot.rb:CVE-2017-5146 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/hp_imc_som_file_download.rb:CVE-2013-4826 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/http_login.rb:CVE-1999-0502#Weakpassword /usr/share/metasploit-framework/modules/auxiliary/scanner/http/es_file_explorer_open_port.rb:CVE-2019-6447 @@ -229,6 +230,7 @@ /usr/share/metasploit-framework/modules/auxiliary/scanner/http/dir_webdav_unicode_bypass.rb:CVE-2009-1122 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/cisco_nac_manager_traversal.rb:CVE-2011-3305 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/jenkins_command.rb:CVE-2015-8103,#seelinkandvalidate,https://highon.coffee/blog/jenkins-api-unauthenticated-rce-exploit/statesthisisanotherissue +/usr/share/metasploit-framework/modules/auxiliary/scanner/http/emby_ssrf_scanner.rb:CVE-2020-26948 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/novell_file_reporter_fsfui_fileaccess.rb:CVE-2012-4958 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/tplink_traversal_noauth.rb:CVE-2012-5687 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/canon_wireless.rb:CVE-2013-4614 @@ -242,6 +244,7 @@ /usr/share/metasploit-framework/modules/auxiliary/scanner/http/kodi_traversal.rb:CVE-2017-5982 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/bmc_trackit_passwd_reset.rb:CVE-2014-8270 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/epmp1000_get_chart_cmd_exec.rb:CVE-2017-5255 +/usr/share/metasploit-framework/modules/auxiliary/scanner/http/emby_version_ssrf.rb:CVE-2020-26948 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/apache_mod_cgi_bash_env.rb:CVE-2014-6271 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/apache_mod_cgi_bash_env.rb:CVE-2014-6278 /usr/share/metasploit-framework/modules/auxiliary/scanner/http/apache_mod_cgi_bash_env.rb:res=req("echo#{marker}",datastoreCVE) @@ -599,6 +602,7 @@ /usr/share/metasploit-framework/modules/exploits/unix/http/lifesize_room.rb:CVE-2011-2763 /usr/share/metasploit-framework/modules/exploits/unix/http/ctek_skyrouter.rb:CVE-2011-5010 /usr/share/metasploit-framework/modules/exploits/unix/http/schneider_electric_net55xx_encoder.rb:CVE-2019-6814 +/usr/share/metasploit-framework/modules/exploits/unix/http/cacti_filter_sqli_rce.rb:CVE-2020-14295 /usr/share/metasploit-framework/modules/exploits/unix/http/tnftp_savefile.rb:CVE-2014-8517 /usr/share/metasploit-framework/modules/exploits/unix/http/epmp1000_get_chart_cmd_shell.rb:CVE-2017-5255 /usr/share/metasploit-framework/modules/exploits/unix/http/quest_kace_systems_management_rce.rb:CVE-2018-11138 @@ -793,6 +797,7 @@ /usr/share/metasploit-framework/modules/exploits/linux/http/trueonline_p660hn_v2_rce.rb:CVE-2017-18371 /usr/share/metasploit-framework/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb:CVE-2012-0299 /usr/share/metasploit-framework/modules/exploits/linux/http/pulse_secure_cmd_exec.rb:CVE-2019-11539 +/usr/share/metasploit-framework/modules/exploits/linux/http/ipfire_pakfire_exec.rb:CVE-2021-33393 /usr/share/metasploit-framework/modules/exploits/linux/http/trendmicro_websecurity_exec.rb:CVE-2020-8604 /usr/share/metasploit-framework/modules/exploits/linux/http/trendmicro_websecurity_exec.rb:CVE-2020-8605 /usr/share/metasploit-framework/modules/exploits/linux/http/trendmicro_websecurity_exec.rb:CVE-2020-8606 @@ -883,6 +888,8 @@ /usr/share/metasploit-framework/modules/exploits/linux/http/axis_srv_parhand_rce.rb:CVE-2018-10662 /usr/share/metasploit-framework/modules/exploits/linux/http/jenkins_cli_deserialization.rb:CVE-2017-1000353 /usr/share/metasploit-framework/modules/exploits/linux/http/dlink_dcs931l_upload.rb:CVE-2015-2049 +/usr/share/metasploit-framework/modules/exploits/linux/http/cisco_hyperflex_hx_data_platform_cmd_exec.rb:CVE-2021-1497,#HyperFlexHXDataPlatformInstaller +/usr/share/metasploit-framework/modules/exploits/linux/http/cisco_hyperflex_hx_data_platform_cmd_exec.rb:CVE-2021-1498,#HyperFlexHXDataPlatform /usr/share/metasploit-framework/modules/exploits/linux/http/cayin_cms_ntp.rb:CVE-2020-7357 /usr/share/metasploit-framework/modules/exploits/linux/http/nuuo_nvrmini_unauth_rce.rb:CVE-2016-5674 /usr/share/metasploit-framework/modules/exploits/linux/http/nagios_xi_chained_rce_2_electric_boogaloo.rb:CVE-2018-8733 @@ -890,6 +897,7 @@ /usr/share/metasploit-framework/modules/exploits/linux/http/nagios_xi_chained_rce_2_electric_boogaloo.rb:CVE-2018-8735 /usr/share/metasploit-framework/modules/exploits/linux/http/nagios_xi_chained_rce_2_electric_boogaloo.rb:CVE-2018-8736 /usr/share/metasploit-framework/modules/exploits/linux/http/geutebruck_testaction_exec.rb:CVE-2020-16205 +/usr/share/metasploit-framework/modules/exploits/linux/http/suitecrm_log_file_rce.rb:CVE-2020-28328,#FirstCVE /usr/share/metasploit-framework/modules/exploits/linux/http/zabbix_sqli.rb:CVE-2013-5743 /usr/share/metasploit-framework/modules/exploits/linux/http/symantec_web_gateway_lfi.rb:CVE-2012-0297 /usr/share/metasploit-framework/modules/exploits/linux/http/pineapp_test_li_conn_exec.rb:CVE-2013-6829 @@ -1905,6 +1913,7 @@ /usr/share/metasploit-framework/modules/exploits/windows/http/hp_pcm_snac_update_domain.rb:CVE-2013-4811 /usr/share/metasploit-framework/modules/exploits/windows/http/hp_mpa_job_acct.rb:CVE-2011-4166 /usr/share/metasploit-framework/modules/exploits/windows/http/disksorter_bof.rb:CVE-2017-7230 +/usr/share/metasploit-framework/modules/exploits/windows/http/sharepoint_unsafe_control.rb:CVE-2021-31181 /usr/share/metasploit-framework/modules/exploits/windows/http/fdm_auth_header.rb:CVE-2009-0183 /usr/share/metasploit-framework/modules/exploits/windows/http/oats_weblogic_console.rb:#CVE-2007-2699 /usr/share/metasploit-framework/modules/exploits/windows/http/tomcat_cgi_cmdlineargs.rb:CVE-2019-0232 diff --git a/emba.sh b/emba.sh index 171123c6..a7e22e42 100755 --- a/emba.sh +++ b/emba.sh @@ -69,13 +69,14 @@ sort_modules() MODULES=( "${SORTED_MODULES[@]}" ) } -# $1: module group letter [P, S, R, F] +# $1: module group letter [P, S, F] # $2: 0=single thread 1=multithread # $3: HTML=1 - generate html file run_modules() { MODULE_GROUP="$1" printf -v THREADING_SET '%d\n' "$2" 2>/dev/null + THREADING_MOD_GROUP="$THREADING_SET" local SELECT_PRE_MODULES_COUNT=0 @@ -88,11 +89,21 @@ run_modules() if [[ ${#SELECT_MODULES[@]} -eq 0 ]] || [[ $SELECT_PRE_MODULES_COUNT -eq 0 ]]; then local MODULES mapfile -t MODULES < <(find "$MOD_DIR" -name "${MODULE_GROUP^^}""*_*.sh" | sort -V 2> /dev/null) - if [[ $THREADING_SET -eq 1 ]] ; then + print_output "[*] module grouop: ${MODULE_GROUP^^}" + if [[ $THREADING_SET -eq 1 && "${MODULE_GROUP^^}" != "P" ]] ; then sort_modules fi for MODULE_FILE in "${MODULES[@]}" ; do if ( file "$MODULE_FILE" | grep -q "shell script" ) && ! [[ "$MODULE_FILE" =~ \ |\' ]] ; then + if [[ "${MODULE_GROUP^^}" == "P" ]]; then + # we are able to enable/disable threading on module basis in the the pre-checker modules with the header: + # export PRE_THREAD_ENA=1/0 + # shellcheck source=/dev/null + source "$MODULE_FILE" + if [[ $PRE_THREAD_ENA -eq 0 ]] ; then + THREADING_SET=0 + fi + fi MODULE_BN=$(basename "$MODULE_FILE") MODULE_MAIN=${MODULE_BN%.*} module_start_log "$MODULE_MAIN" @@ -105,6 +116,9 @@ run_modules() fi reset_module_count fi + if [[ "${MODULE_GROUP^^}" == "P" ]]; then + THREADING_SET="$THREADING_MOD_GROUP" + fi done else for SELECT_NUM in "${SELECT_MODULES[@]}" ; do @@ -132,6 +146,16 @@ run_modules() fi for MODULE_FILE in "${MODULES[@]}" ; do if ( file "$MODULE_FILE" | grep -q "shell script" ) && ! [[ "$MODULE_FILE" =~ \ |\' ]] ; then + if [[ "${MODULE_GROUP^^}" == "P" ]]; then + # we are able to enable/disable threading on module basis in the the pre-checker modules with the header: + # export PRE_THREAD_ENA=1/0 + # shellcheck source=/dev/null + source "$MODULE_FILE" + if [[ $PRE_THREAD_ENA -eq 0 ]] ; then + THREADING_SET=0 + fi + fi + MODULE_BN=$(basename "$MODULE_FILE") MODULE_MAIN=${MODULE_BN%.*} module_start_log "$MODULE_MAIN" @@ -144,6 +168,9 @@ run_modules() fi reset_module_count fi + if [[ "${MODULE_GROUP^^}" == "P" ]]; then + THREADING_SET="$THREADING_MOD_GROUP" + fi done fi done @@ -171,6 +198,7 @@ main() export LOG_GREP=0 export MOD_RUNNING=0 # for tracking how many modules currently running export ONLY_DEP=0 # test only dependency + export ONLINE_CHECKS=0 # checks with internet connection needed (e.g. upload of firmware to virustotal) export PHP_CHECK=1 export PRE_CHECK=0 # test and extract binary files with binwalk # afterwards do a default emba scan @@ -200,6 +228,7 @@ main() if [[ -f "$CONFIG_DIR"/msf_cve-db.txt ]]; then export MSF_DB_PATH="$CONFIG_DIR"/msf_cve-db.txt fi + export VT_API_KEY_FILE="$CONFIG_DIR"/vt_api_key.txt # virustotal API key for P03 module echo @@ -217,7 +246,7 @@ main() export EMBA_COMMAND EMBA_COMMAND="$(dirname "$0")""/emba.sh ""$*" - while getopts a:A:cdDe:Ef:Fghik:l:m:N:p:stxX:Y:WzZ: OPT ; do + while getopts a:A:cdDe:Ef:Fghik:l:m:N:op:stxX:Y:WzZ: OPT ; do case $OPT in a) export ARCH="$OPTARG" @@ -274,6 +303,9 @@ main() N) export FW_NOTES="$OPTARG" ;; + o) + export ONLINE_CHECKS=1 + ;; p) export PROFILE="$OPTARG" ;; @@ -458,7 +490,7 @@ main() OPTIND=1 ARGS="" - while getopts a:A:cdDe:Ef:Fghik:l:m:N:p:stX:Y:WxzZ: OPT ; do + while getopts a:A:cdDe:Ef:Fghik:l:m:N:op:stX:Y:WxzZ: OPT ; do case $OPT in D|f|i|l) ;; @@ -506,7 +538,8 @@ main() ## IMPORTANT NOTE: Threading is handled withing the pre-checking modules, therefore overwriting $THREADED as 0 ## as there are internal dependencies it is easier to handle it in the modules - run_modules "P" "0" "0" + #run_modules "P" "0" "0" + run_modules "P" "$THREADED" "0" # if we running threaded we ware going to wait for the slow guys here if [[ $THREADED -eq 1 ]]; then diff --git a/helpers/print.sh b/helpers/print.sh index 9c3fb045..a8e23998 100755 --- a/helpers/print.sh +++ b/helpers/print.sh @@ -431,6 +431,7 @@ print_help() echo -e "$CYAN""-k [./config]""$NC"" Kernel config path" echo -e "$CYAN""-x""$NC"" Enable deep extraction - try to extract every file two times with binwalk (WARNING: Uses a lot of disk space)" echo -e "$CYAN""-t""$NC"" Activate multi threading (destroys regular console output)" + echo -e "$CYAN""-o""$NC"" Activate online checks (e.g. upload and test with VirusTotal)" echo -e "\\nModify output" echo -e "$CYAN""-s""$NC"" Prints only relative paths" echo -e "$CYAN""-z""$NC"" Adds ANSI color codes to log" diff --git a/modules/P02_firmware_bin_file_check.sh b/modules/P02_firmware_bin_file_check.sh index 0a648ea6..7ce6c6c5 100755 --- a/modules/P02_firmware_bin_file_check.sh +++ b/modules/P02_firmware_bin_file_check.sh @@ -14,6 +14,8 @@ # Author(s): Michael Messner, Pascal Eckmann # Description: Gives some very basic information about the provided firmware binary. +# Pre-chcker Threading mode - if set to 1, these modules will run in threaded mode +export PRE_THREAD_ENA=1 P02_firmware_bin_file_check() { module_log_init "${FUNCNAME[0]}" diff --git a/modules/P03_firmware_virustotal_check.sh b/modules/P03_firmware_virustotal_check.sh new file mode 100755 index 00000000..c474fb0c --- /dev/null +++ b/modules/P03_firmware_virustotal_check.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +# emba - EMBEDDED LINUX ANALYZER +# +# Copyright 2020-2021 Siemens Energy AG +# Copyright 2020-2021 Siemens AG +# +# emba comes with ABSOLUTELY NO WARRANTY. This is free software, and you are +# welcome to redistribute it under the terms of the GNU General Public License. +# See LICENSE file for usage of this software. +# +# emba is licensed under GPLv3 +# +# Author(s): Michael Messner, Pascal Eckmann + +# Description: Uploads the firmware to virustotal +# Important: This module needs a VT API key in the config file ./config/vt_api_key.txt +# This key is avilable via your VT profile +# Pre-chcker Threading mode - if set to 1, these modules will run in threaded mode +export PRE_THREAD_ENA=1 + +P03_firmware_virustotal_check() { + module_log_init "${FUNCNAME[0]}" + module_title "Binary firmware VirusTotal analyzer" + + if [[ -f "$VT_API_KEY_FILE" && "$ONLINE_CHECKS" -eq 1 ]]; then + VT_API_KEY=$(cat "$VT_API_KEY_FILE") + # upload our firmware file to VT: + print_output "[*] Upload to VirusTotal in progress ..." + VT_UPLOAD_ID=$(curl -s --request POST --url "https://www.virustotal.com/api/v3/files" --header "x-apikey: $VT_API_KEY" --form "file=@$FIRMWARE_PATH" | jq -r '.data.id') + + if [[ "$VT_UPLOAD_ID" == "null" ]]; then + print_output "[-] Upload to VirusTotal failed ..." + else + print_output "[*] Upload to VirusTotal finished ..." + print_output "[*] Uploaded firmware to VirusTotal with ID: $ORANGE$VT_UPLOAD_ID$NC" + VT_ANALYSIS_RESP="init" + while [[ "$VT_ANALYSIS_RESP" != "completed" ]]; do + VT_ANALYSIS_RESP=$(curl -m 10 -s --request GET --url "https://www.virustotal.com/api/v3/analyses/$VT_UPLOAD_ID" --header "x-apikey: $VT_API_KEY" | jq -r '.data.attributes.status') + if [[ "$VT_ANALYSIS_RESP" != "completed" && "$VT_ANALYSIS_RESP" == "queued" ]]; then + echo "." | tr -d "\n" 2>/dev/null + else + print_output "[*] Analysis of file $ORANGE$FIRMWARE_PATH$NC is $VT_ANALYSIS_RESP." + fi + sleep 2 + done + + VT_ANALYSIS_RESP=$(curl -s --request GET --url "https://www.virustotal.com/api/v3/analyses/$VT_UPLOAD_ID" --header "x-apikey: $VT_API_KEY" >> "$TMP_DIR"/vt_response.json) + + if [[ $(wc -l "$TMP_DIR"/vt_response.json | awk '{print $1}') -gt 1 ]]; then + print_output "" + print_output "[*] Firmware metadata reported by VirusTotal:" + jq -r '.meta' "$TMP_DIR"/vt_response.json | tee -a "$LOG_FILE" + VT_SUSP=$(jq -r '.data.attributes.stats.suspicious' "$TMP_DIR"/vt_response.json) + VT_MAL=$(jq -r '.data.attributes.stats.malicious' "$TMP_DIR"/vt_response.json) + + print_output "" + if [[ "$VT_SUSP" -gt 0 || "$VT_MAL" -gt 0 ]]; then + print_output "[+] Infection via malicious code detected!" + else + print_output "[-] No infection via malicious code detected." + fi + + print_output "" + print_output "[*] VirusTotal test overview:" + jq -r '.data.attributes' "$TMP_DIR"/vt_response.json | tee -a "$LOG_FILE" + print_output "" + NEG_LOG=1 + fi + fi + + else + print_output "[-] No Virustotal API key file found in $ORANGE$VT_API_KEY$NC or online checks disabled." + NEG_LOG=0 + fi + + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" +} diff --git a/modules/P05_firmware_bin_extractor.sh b/modules/P05_firmware_bin_extractor.sh index 0669ef8e..8db72a89 100755 --- a/modules/P05_firmware_bin_extractor.sh +++ b/modules/P05_firmware_bin_extractor.sh @@ -15,6 +15,9 @@ # Description: Analyzes firmware with binwalk, checks entropy and extracts firmware in the log directory. # If binwalk fails to extract the firmware, it will be extracted with FACT-extractor. +# Pre-chcker Threading mode - if set to 1, these modules will run in threaded mode +export PRE_THREAD_ENA=0 + P05_firmware_bin_extractor() { module_log_init "${FUNCNAME[0]}" diff --git a/modules/P07_firmware_bin_base_analyzer.sh b/modules/P07_firmware_bin_base_analyzer.sh index 8f6e6179..6dac3ee7 100755 --- a/modules/P07_firmware_bin_base_analyzer.sh +++ b/modules/P07_firmware_bin_base_analyzer.sh @@ -15,6 +15,8 @@ # Description: Identifies the operating system. Currently, it tries to identify VxWorks, eCos, Adonis, Siprotec, uC/OS and Linux. # If no Linux operating system is found, then it also tries to identify the target architecture (currently with binwalk only). +# Pre-chcker Threading mode - if set to 1, these modules will run in threaded mode +export PRE_THREAD_ENA=1 P07_firmware_bin_base_analyzer() { diff --git a/modules/S09_firmware_base_version_check.sh b/modules/S09_firmware_base_version_check.sh index 421d6912..b04dc6a6 100755 --- a/modules/S09_firmware_base_version_check.sh +++ b/modules/S09_firmware_base_version_check.sh @@ -58,6 +58,7 @@ S09_firmware_base_version_check() { echo "." | tr -d "\n" if [[ $FIRMWARE -eq 0 || -f $FIRMWARE_PATH ]]; then + #print_output "[*] original firmware path searched" VERSION_FINDER=$(find "$FIRMWARE_PATH" -xdev -type f -print0 2>/dev/null | xargs -0 strings | grep -o -a -E "$VERSION_IDENTIFIER" | head -1 2>/dev/null) if [[ -n $VERSION_FINDER ]]; then @@ -83,23 +84,24 @@ S09_firmware_base_version_check() { echo "." | tr -d "\n" else + #print_output "[*] RTOS: $RTOS" if [[ $RTOS -eq 1 ]]; then continue - fi - - mapfile -t STRICT_BINS < <(find "$OUTPUT_DIR" -xdev -executable -type f -name "$BIN_NAME" -exec md5sum {} \; 2>/dev/null | sort -u -k1,1 | cut -d\ -f3) - for BIN in "${STRICT_BINS[@]}"; do - # as the STRICT_BINS array could also include executable scripts we have to check for ELF files now: - if file "$BIN" | grep -q ELF ; then - VERSION_FINDER=$(strings "$BIN" | grep -E "$VERSION_IDENTIFIER" | sort -u) - if [[ -n $VERSION_FINDER ]]; then - echo "" - print_output "[+] Version information found ${RED}$BIN_NAME $VERSION_FINDER${NC}${GREEN} in binary $ORANGE$(print_path "$BIN")$GREEN (static - strict)." + else + mapfile -t STRICT_BINS < <(find "$OUTPUT_DIR" -xdev -executable -type f -name "$BIN_NAME" -exec md5sum {} \; 2>/dev/null | sort -u -k1,1 | cut -d\ -f3) + for BIN in "${STRICT_BINS[@]}"; do + # as the STRICT_BINS array could also include executable scripts we have to check for ELF files now: + if file "$BIN" | grep -q ELF ; then + VERSION_FINDER=$(strings "$BIN" | grep -E "$VERSION_IDENTIFIER" | sort -u) + if [[ -n $VERSION_FINDER ]]; then + echo "" + print_output "[+] Version information found ${RED}$BIN_NAME $VERSION_FINDER${NC}${GREEN} in binary $ORANGE$(print_path "$BIN")$GREEN (static - strict)." continue + fi fi - fi - done - echo "." | tr -d "\n" + done + echo "." | tr -d "\n" + fi fi if [[ "${#WAIT_PIDS_S09[@]}" -gt "$MAX_THREADS_S09" ]]; then