From 843c68c7c0b3e76cf036263738d976dbbe01356b Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Fri, 2 Dec 2022 14:54:15 +0100 Subject: [PATCH 01/21] clenaup --- docker-compose.yml | 2 +- emba.sh | 6 ++++++ helpers/helpers_emba_helpers.sh | 7 +++++++ installer/helpers.sh | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 9dacdd2ab..9fab052fc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -39,12 +39,12 @@ services: - ${FIRMWARE}/:/firmware:ro - ${LOG}/:/logs - ${EMBA}/:/emba:ro + - ${EMBA}/external/linux_kernel_sources/:/external/linux_kernel_sources:ro - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro - /dev:/dev - /lib/modules:/lib/modules:ro - /boot:/boot:ro - # - /home/m1k3/github-repos/EMBA-emulation-binaries:/external/EMBA_Live_bins/:ro environment: - USER devices: diff --git a/emba.sh b/emba.sh index 9633496b8..a1547ea31 100755 --- a/emba.sh +++ b/emba.sh @@ -653,6 +653,12 @@ main() # create log directory, if not exists and needed subdirectories create_log_dir + if [[ $IN_DOCKER -eq 0 ]]; then + kernel_downloader & + K_DOWN_PID="$!" + print_output "[*] Started kernel downloader thread with PID $K_DOWN_PID" "no_log" + fi + if [[ $IN_DOCKER -eq 0 ]]; then echo "$LOG_DIR" > "$TMP_DIR"/orig_logdir fi diff --git a/helpers/helpers_emba_helpers.sh b/helpers/helpers_emba_helpers.sh index 7e7144630..1719f9a5f 100755 --- a/helpers/helpers_emba_helpers.sh +++ b/helpers/helpers_emba_helpers.sh @@ -136,6 +136,13 @@ cleaner() { restore_permissions fi + if [[ "$IN_DOCKER" -eq 0 ]] && [[ -v K_DOWN_PID ]]; then + if ps -p "$K_DOWN_PID"; then + # kernel downloader is running in a thread on the host and needs to be stopped now + print_output "[*] Stopping kernel downloader thread with PID $K_DOWN_PID" "no_log" + kill "$K_DOWN_PID" || true + fi + fi if [[ "$IN_DOCKER" -eq 0 ]] && pgrep -f "find ./external/trickest" &> /dev/null 2>&1; then pkill -f "find ./external/trickest" 2>/dev/null || true fi diff --git a/installer/helpers.sh b/installer/helpers.sh index 1e353897a..9a916514d 100755 --- a/installer/helpers.sh +++ b/installer/helpers.sh @@ -176,7 +176,7 @@ print_file_info() echo -e "Description: ""${2:-}" fi # echo "$(wget "${3}" --spider --server-response -O -)" - CONTENT_LENGTH=$(wget "${3:-}" --no-check-certificate --spider --server-response --output-file=./.wget.log 2>&1 | sed -ne '/.ontent-.ength/{s/.*: //;p}' | sed '$!d') + CONTENT_LENGTH=$(wget "${3:-}" --no-check-certificate --spider --server-response --output-file=./.wget.log 2>&1 | sed -ne '/.ontent-.ength/{s/.*: //;p}' | sed '$!d' || true) if [[ -n "$CONTENT_LENGTH" ]]; then FILE_SIZE=$(("$CONTENT_LENGTH")) else From a3eb2641a79c90fa354be67445cd31d4e3f36e87 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Fri, 2 Dec 2022 15:02:00 +0100 Subject: [PATCH 02/21] s26 module, downloader --- helpers/helpers_emba_internet_access.sh | 82 ++++ modules/S26_kernel_vuln_verifier.sh | 533 ++++++++++++++++++++++++ 2 files changed, 615 insertions(+) create mode 100755 helpers/helpers_emba_internet_access.sh create mode 100755 modules/S26_kernel_vuln_verifier.sh diff --git a/helpers/helpers_emba_internet_access.sh b/helpers/helpers_emba_internet_access.sh new file mode 100755 index 000000000..874f4c091 --- /dev/null +++ b/helpers/helpers_emba_internet_access.sh @@ -0,0 +1,82 @@ +#!/bin/bash -p + +# EMBA - EMBEDDED LINUX ANALYZER +# +# Copyright 2020-2022 Siemens Energy 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 + +# Description: Multiple useful helpers used to access online resources + +kernel_downloader() { + LOG_FILE_KERNEL="$CSV_DIR"/s24_kernel_bin_identifier.csv + KERNEL_ARCH_PATH="$EXT_DIR"/linux_kernel_sources/ + + if ! [[ -d "$KERNEL_ARCH_PATH" ]]; then + mkdir "$KERNEL_ARCH_PATH" + fi + + # we wait until the s24 module is finished and hopefully shows us a kernel version + while ! [[ -f "$LOG_DIR"/"$MAIN_LOG_FILE" ]]; do + sleep 1 + done + if [[ -f "$LOG_DIR"/"$MAIN_LOG_FILE" ]]; then + while [[ $(grep -c S24_kernel_bin_identifier "$LOG_DIR"/"$MAIN_LOG_FILE") -lt 2 ]]; do + sleep 1 + done + fi + # now we should have a csv log with a kernel version: + if ! [[ -f "$LOG_FILE_KERNEL" ]]; then + print_output "[-] No Kernel version identified ..." "no_log" + return + fi + local K_VERSIONS=() + local K_VERSION="" + + mapfile -t K_VERSIONS < <(cut -d\; -f2 "$LOG_FILE_KERNEL" | tail -n +2 | sort -u | grep -E "[0-9]+(\.[0-9]+)+?" || true) + + for K_VERSION in "${K_VERSIONS[@]}"; do + print_output "[*] Checking download of kernel version $ORANGE$K_VERSION$NC" "no_log" + local K_VER_DOWNLOAD="" + local K_VER_1st="" + local K_VER_2nd="" + local K_VER_3rd="" + + K_VER_1st=$(echo "$K_VERSION" | cut -d. -f1) + K_VER_2nd=$(echo "$K_VERSION" | cut -d. -f2) + K_VER_3rd=$(echo "$K_VERSION" | cut -d. -f3) + if [[ "$K_VER_1st" -lt 3 ]]; then + K_VER_DOWNLOAD="$K_VER_1st"".""$K_VER_2nd" + elif [[ "$K_VER_1st" -eq 3 && "$K_VER_2nd" -eq 0 ]]; then + K_VER_DOWNLOAD="$K_VER_1st"".""$K_VER_2nd" + else + K_VER_DOWNLOAD="$K_VER_1st"".x" + fi + if [[ "$K_VER_3rd" -eq 0 ]]; then + # for download we need to modify versions like 3.1.0 to 3.1 + K_VERSION="$K_VER_1st"".""$K_VER_2nd" + fi + + if ! [[ -f "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz ]]; then + print_output "[*] Kernel download for version $ORANGE$K_VERSION$NC" "no_log" + wget https://mirrors.edge.kernel.org/pub/linux/kernel/v"$K_VER_DOWNLOAD"/linux-"$K_VERSION".tar.gz -O "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz || true + fi + + if ! [[ -f "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz ]]; then + print_output "[-] Kernel sources not available ..." "no_log" + continue + fi + if ! file "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz | grep -q "gzip compressed data"; then + print_output "[-] Kernel sources not available ..." "no_log" + continue + fi + print_output "[*] Kernel source for version $ORANGE$K_VERSION$NC stored in $ORANGE$KERNEL_ARCH_PATH$NC" "no_log" + done +} + diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh new file mode 100755 index 000000000..848c94c48 --- /dev/null +++ b/modules/S26_kernel_vuln_verifier.sh @@ -0,0 +1,533 @@ +#!/bin/bash -p + +# EMBA - EMBEDDED LINUX ANALYZER +# +# Copyright 2020-2022 Siemens Energy 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 + +# Description: After the s24 module was able to identify the kernel, the downloader +# helper function "kernel_downloader" has downloaded the kernel sources +# This module checks if we have symbols and/or the kernel config extracted, +# identifies vulnerabilities via the version number and tries to verify the +# CVEs + +S26_kernel_vuln_verifier() +{ + module_log_init "${FUNCNAME[0]}" + module_title "Kernel vulnerability identification and verification" + pre_module_reporter "${FUNCNAME[0]}" + + KERNEL_CONFIG="NA" + HOME_DIR="$(pwd)" + # KERNEL_ARCH_PATH is the directory where we store all the kernels + KERNEL_ARCH_PATH="$EXT_DIR""/linux_kernel_sources" + S24_CSV_LOG="$CSV_DIR""/s24_kernel_bin_identifier.csv" + WAIT_PIDS_S26=() + NEG_LOG=0 + + # we wait until the s24 module is finished and hopefully shows us a kernel version + while ! [[ -f "$LOG_DIR"/"$MAIN_LOG_FILE" ]]; do + sleep 1 + done + if [[ -f "$LOG_DIR"/"$MAIN_LOG_FILE" ]]; then + while [[ $(grep -c S24_kernel_bin_identifier "$LOG_DIR"/"$MAIN_LOG_FILE") -lt 2 ]]; do + sleep 1 + done + fi + # now we should have a csv log with a kernel version: + if ! [[ -f "$S24_CSV_LOG" ]] || [[ "$(wc -l "$S24_CSV_LOG" | awk '{print $1}')" -lt 2 ]]; then + print_output "[-] No Kernel version file identified ..." + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi + + get_csv_data_s24 "$S24_CSV_LOG" + + if ! [[ -f "$KERNEL_ELF_PATH" ]]; then + print_output "[-] Warning: Kernel ELF file not found" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi + if ! [[ -v K_VERSION ]]; then + print_output "[-] Missing kernel version .. exit now" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi + + CVE_DETAILS_PATH="$LOG_PATH_MODULE""/kernel-$K_VERSION-vulns.json" + + if ! [[ -f $PATH_CVE_SEARCH ]]; then + print_output "[-] CVE search binary search.py not found." + print_output "[-] Run the installer or install it from here: https://github.com/cve-search/cve-search." + print_output "[-] Installation instructions can be found on github.io: https://cve-search.github.io/cve-search/getting_started/installation.html#installation" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi + + check_cve_search + + if [[ "$CVE_SEARCH" -eq 0 ]]; then + print_output "[*] Waiting for the cve-search environment ..." + sleep 120 + check_cve_search + + if [[ "$CVE_SEARCH" -eq 0 ]]; then + print_output "[*] Waiting for the cve-search environment ..." + sleep 120 + check_cve_search + fi + fi + if [[ "$CVE_SEARCH" -ne 1 ]]; then + print_cve_search_failure + return + fi + + if [[ -f "$KERNEL_ELF_PATH" ]]; then + extract_kernel_arch "$KERNEL_ELF_PATH" + fi + + WAIT_CNT=0 + while ! [[ -f "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" ]]; do + print_output "[*] Waiting for kernel sources ..." "no_log" + ((WAIT_CNT+=1)) + sleep 5 + done + + print_output "[*] Kernel archive for version $ORANGE$K_VERSION$NC available" + + KERNEL_DIR="$LOG_PATH_MODULE/linux-$K_VERSION" + if [[ -d "$KERNEL_DIR" ]]; then + rm -rf "$KERNEL_DIR" + fi + if ! [[ -d "$KERNEL_DIR" ]] && [[ "$(file "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz")" == *"gzip compressed data"* ]]; then + print_output "[*] Kernel extract for version $ORANGE$K_VERSION$NC" + tar -xzf "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" -C "$LOG_PATH_MODULE" + fi + + get_cve_kernel_data + + if ! [[ -f "$CVE_DETAILS_PATH" ]]; then + print_output "[-] No CVE details generated ... return" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi + + print_output "[*] Create CVE vulnerabilities array for kernel version $ORANGE$K_VERSION$NC ..." + mapfile -t ALL_KVULNS < <(jq -rc '"\(.id):\(.cvss):\(.cvss3):\(.summary)"' "$CVE_DETAILS_PATH") + print_output "[+] Extracted $ORANGE${#ALL_KVULNS[@]}$GREEN vulnerabilities based on kernel version only" + + if [[ -f "$KERNEL_CONFIG" ]] && [[ -d "$KERNEL_DIR" ]]; then + compile_kernel "$KERNEL_CONFIG" "$KERNEL_DIR" "$ORIG_K_ARCH" + fi + + print_ln + print_output "[*] Create kernel symbols ..." + readelf -s "$KERNEL_ELF_PATH" | grep "FUNC\|OBJECT" | sed 's/.*FUNC//' | sed 's/.*OBJECT//' | awk '{print $4}' | \ + sed 's/\[\.\.\.\]//' > "$LOG_PATH_MODULE"/symbols.txt + SYMBOLS_CNT=$(wc -l "$LOG_PATH_MODULE"/symbols.txt | awk '{print $1}') + print_output "[*] Extracted $SYMBOLS_CNT symbols from kernel" + + if [[ -d "$LOG_DIR""/firmware" ]]; then + print_output "[*] Create kernel modules symbols array ..." + find "$LOG_DIR/firmware" -name "*.ko" -exec readelf -a {} \; | grep FUNC | sed 's/.*FUNC//' | \ + awk '{print $4}' | sed 's/\[\.\.\.\]//' >> "$LOG_PATH_MODULE"/symbols.txt + fi + + uniq "$LOG_PATH_MODULE"/symbols.txt > "$LOG_PATH_MODULE"/symbols_uniq.txt + SYMBOLS_CNT=$(wc -l "$LOG_PATH_MODULE"/symbols_uniq.txt | awk '{print $1}') + print_output "[*] Extracted $ORANGE$SYMBOLS_CNT$NC unique symbols" + + if [[ "$SYMBOLS_CNT" -eq 0 ]]; then + print_output "[-] No symbols found ... exit" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi + + print_output "[*] Splitting symbols file for processing" + split -l 100 "$LOG_PATH_MODULE"/symbols_uniq.txt "$LOG_PATH_MODULE"/symbols_uniq.split. + sed -i 's/^/EXPORT_SYMBOL\(/' "$LOG_PATH_MODULE"/symbols_uniq.split.* + sed -i 's/$/\)/' "$LOG_PATH_MODULE"/symbols_uniq.split.* + + split -l 100 "$LOG_PATH_MODULE"/symbols_uniq.txt "$LOG_PATH_MODULE"/symbols_uniq.split_gpl. + sed -i 's/^/EXPORT_SYMBOL_GPL\(/' "$LOG_PATH_MODULE"/symbols_uniq.split_gpl.* + sed -i 's/$/\)/' "$LOG_PATH_MODULE"/symbols_uniq.split_gpl.* + + CNT_PATHS_UNK=0 + CNT_PATHS_FOUND=0 + CNT_PATHS_NOT_FOUND=0 + VULN_CNT=1 + CNT_PATHS_FOUND_WRONG_ARCH=0 + local NEG_LOG=1 + + print_ln + print_output "[*] Checking vulnerabilities" + print_ln + + for VULN in "${ALL_KVULNS[@]}"; do + print_output "[*] Testing vulnerability $ORANGE$VULN_CNT$NC / $ORANGE${#ALL_KVULNS[@]}$NC" + + K_PATHS=() + K_PATHS_FILES_TMP=() + K_PATH="undocumented source path" + + CVE=$(echo "$VULN" | cut -d: -f1) + CVSS2="$(echo "$VULN" | cut -d: -f2)" + CVSS3="$(echo "$VULN" | cut -d: -f3)" + SUMMARY="$(echo "$VULN" | cut -d: -f4-)" + mapfile -t K_PATHS < <(echo "$SUMMARY" | tr ' ' '\n' | grep ".*\.[chS]$" | sed -r 's/CVE-[0-9]+-[0-9]+:[0-9].*://' \ + | sed -r 's/CVE-[0-9]+-[0-9]+:null.*://' | sed 's/^(//' | sed 's/)$//' | sed 's/,$//' | sed 's/\.$//' | cut -d: -f1 || true) + + for K_PATH in "${K_PATHS[@]}"; do + if ! [[ "$K_PATH" == *"/"* ]]; then + print_output "[*] Found file name $ORANGE$K_PATH$NC for $ORANGE$CVE$NC without path details ... looking for candidates now" + mapfile -t K_PATHS_FILES_TMP < <(find "$KERNEL_DIR" -name "$K_PATH" | sed "s&$KERNEL_DIR\/&&") + fi + K_PATHS+=("${K_PATHS_FILES_TMP[@]}") + done + + if [[ "${#K_PATHS[@]}" -gt 0 ]]; then + for K_PATH in "${K_PATHS[@]}"; do + if [[ -f "$KERNEL_DIR/$K_PATH" ]]; then + # check if arch is in path -> if so we check if our architecture is also in the path + # if we find our architecture then we can proceed with symbol_verifier + if [[ "$K_PATH" == "arch/"* ]]; then + if [[ "$K_PATH" == "arch/$ORIG_K_ARCH/"* ]]; then + ((CNT_PATHS_FOUND+=1)) + symbol_verifier "$CVE" "$K_VERSION" "$K_PATH" "$CVSS2/$CVSS3" & + WAIT_PIDS_S26+=( "$!" ) + compile_verifier "$CVE" "$K_VERSION" "$K_PATH" "$CVSS2/$CVSS3" & + WAIT_PIDS_S26+=( "$!" ) + else + print_output "[-] Vulnerable path for different architecture found for $ORANGE$K_PATH$NC - not further processing $ORANGE$CVE$NC" + ((CNT_PATHS_FOUND_WRONG_ARCH+=1)) + fi + else + ((CNT_PATHS_FOUND+=1)) + symbol_verifier "$CVE" "$K_VERSION" "$K_PATH" "$CVSS2/$CVSS3" & + WAIT_PIDS_S26+=( "$!" ) + compile_verifier "$CVE" "$K_VERSION" "$K_PATH" "$CVSS2/$CVSS3" & + WAIT_PIDS_S26+=( "$!" ) + fi + else + print_output "[-] $ORANGE$CVE$NC - $ORANGE$K_PATH$NC - source file not found" + ((CNT_PATHS_NOT_FOUND+=1)) + fi + max_pids_protection 20 "${WAIT_PIDS_S26[@]}" + done + else + print_output "[-] $CVE - $K_PATH" + ((CNT_PATHS_UNK+=1)) + fi + ((VULN_CNT+=1)) + done + + wait_for_pid "${WAIT_PIDS_S26[@]}" + + final_log_kernel_vulns + + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" +} + +get_cve_kernel_data() { + print_output "[*] Extract CVE data for kernel version $ORANGE$K_VERSION$NC" + "$PATH_CVE_SEARCH" -p linux_kernel:"$K_VERSION" -o json > "$CVE_DETAILS_PATH" +} + +extract_kernel_arch() { + KERNEL_ELF_PATH="${1:-}" + ORIG_K_ARCH=$(file "$KERNEL_ELF_PATH" | cut -d, -f2) + + # for ARM -> ARM aarch64 to ARM64 + ORIG_K_ARCH=${ORIG_K_ARCH/ARM\ aarch64/arm64} + # for MIPS64 -> MIPS64 to MIPS + ORIG_K_ARCH=${ORIG_K_ARCH/MIPS64/MIPS} + + ORIG_K_ARCH=$(echo "$ORIG_K_ARCH" | tr -d ' ' | tr "[:upper:]" "[:lower:]") + print_output "[+] Found kernel architecture $ORANGE$ORIG_K_ARCH$NC" +} + +symbol_verifier() { + local CVE="${1:-}" + local K_VERSION="${2:-}" + local K_PATH="${3:-}" + local CVSS="${4:-}" + local VULN_FOUND=0 + + for CHUNK_FILE in "$LOG_PATH_MODULE"/symbols_uniq.split.* ; do + # echo "testing chunk file $CHUNK_FILE" + if grep -q -f "$CHUNK_FILE" "$KERNEL_DIR/$K_PATH" ; then + # echo "verified chunk file $CHUNK_FILE" + print_output "[+] $CVE ($CVSS) - $K_PATH verified - exported symbol$NC" + echo "$CVE ($CVSS) - $K_VERSION - exported symbol verified - $K_PATH" >> "$LOG_PATH_MODULE""/${CVE}_symbol_verified.txt" + VULN_FOUND=1 + break + fi + done + + if [[ "$VULN_FOUND" -eq 1 ]]; then + # if we have already a match for this path we can skip the 2nd check + return + fi + + for CHUNK_FILE in "$LOG_PATH_MODULE"/symbols_uniq.split_gpl.* ; do + # echo "testing chunk file $CHUNK_FILE" + if grep -q -f "$CHUNK_FILE" "$KERNEL_DIR/$K_PATH" ; then + # print_output "[*] verified chunk file $CHUNK_FILE (GPL)" + print_output "[+] $CVE ($CVSS) - $K_PATH verified - exported symbol (gpl)$NC" + echo "$CVE ($CVSS) - $K_VERSION - exported symbol verified (gpl) - $K_PATH" >> "$LOG_PATH_MODULE""/${CVE}_symbol_verified.txt" + VULN_FOUND=1 + break + fi + done +} + +compile_verifier() { + local CVE_="${1:-}" + local K_VERSION="${2:-}" + local K_PATH="${3:-}" + local CVSS="${4:-}" + local VULN_FOUND=0 + if ! [[ -f "$LOG_PATH_MODULE"/kernel-compile.files ]]; then + return + fi + + if grep -q "$K_PATH" "$LOG_PATH_MODULE"/kernel-compile.files ; then + print_output "[+] $CVE_ ($CVSS) - $K_PATH verified - compiled path" + echo "$CVE_ ($CVSS) - $K_VERSION - compiled path verified - $K_PATH" >> "$LOG_PATH_MODULE""/${CVE_}_compiled_verified.txt" + fi +} + +compile_kernel() { + local KERNEL_CONFIG_FILE="${1:-}" + local KERNEL_DIR="${2:-}" + local KARCH="${3:-}" + if ! [[ -f "$KERNEL_CONFIG_FILE" ]]; then + return + fi + if ! [[ -d "$KERNEL_DIR" ]]; then + return + fi + + KARCH=$(echo "$KARCH" | tr '[:upper:]' '[:lower:]') + # todo handle further architecture values + + print_bar + cd "$KERNEL_DIR" || exit + print_output "[*] Create default kernel config" + LANG=en make ARCH="$KARCH" defconfig + cp "$KERNEL_CONFIG_FILE" .config + print_ln + print_output "[*] Update kernel config with the configuration of the firmware" + # https://stackoverflow.com/questions/4178526/what-does-make-oldconfig-do-exactly-in-the-linux-kernel-makefile + LANG=en make ARCH="$KARCH" olddefconfig + print_ln + print_output "[*] Starting dry run ..." + LANG=en make ARCH="$KARCH" target=all -Bndi | tee -a "$LOG_PATH_MODULE"/kernel-compile.output + print_ln + print_output "[*] Finished dry run ..." + cd "$HOME_DIR" || exit + if [[ -f "$LOG_PATH_MODULE"/kernel-compile.output ]]; then + tr ' ' '\n' < "$LOG_PATH_MODULE"/kernel-compile.output | grep ".*\.[chS]" | tr -d '"' | tr -d ')' \ + | tr -d '(' | sed 's/^\.\///' | sed '/^\/.*/d' | tr -d ';' | sed 's/^>//' | sed 's/^-o//' | tr -d \' \ + | sed 's/--defines=//' | sed 's/\.$//' | sort -u > "$LOG_PATH_MODULE"/kernel-compile.files + COMPILE_SOURCE_FILES=$(wc -l "$LOG_PATH_MODULE"/kernel-compile.files | awk '{print $1}') + print_output "[+] Found $ORANGE$COMPILE_SOURCE_FILES$GREEN used source files during compilation" + else + print_output "[-] Found ${RED}NO$NC used source files during compilation" + fi + print_bar +} + +final_log_kernel_vulns() { + rm -r "$LOG_PATH_MODULE"/symbols_uniq.split.* + rm -r "$LOG_PATH_MODULE"/symbols_uniq.split_gpl.* + + local CVE="" + local VULN="" + + print_ln + print_output "[*] Generating final kernel report ..." + echo "Kernel version;Architecture;CVE;CVSSv2;CVSSv3;Verified with symbols;Verified with compile files" >> "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv + + for VULN in "${ALL_KVULNS[@]}"; do + local CVE_SYMBOL_FOUND=0 + local CVE_COMPILE_FOUND=0 + CVE=$(echo "$VULN" | cut -d: -f1) + CVSS2="$(echo "$VULN" | cut -d: -f2)" + CVSS3="$(echo "$VULN" | cut -d: -f3)" + CVE_SYMBOL_FOUND=$(find "$LOG_PATH_MODULE" -name "${CVE}_symbol_verified.txt" | wc -l) + CVE_COMPILE_FOUND=$(find "$LOG_PATH_MODULE" -name "${CVE}_compiled_verified.txt" | wc -l) + echo "$K_VERSION;$ORIG_K_ARCH;$CVE;$CVSS2;$CVSS3;$CVE_SYMBOL_FOUND;$CVE_COMPILE_FOUND" >> "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv + done + + SYM_USAGE_VERIFIED=$(cat "$LOG_PATH_MODULE"/CVE-*symbol_* | wc -l 2>/dev/null) + VULN_PATHS_VERIFIED_SYMBOLS=$(cat "$LOG_PATH_MODULE"/CVE-*symbol_verified.txt 2>/dev/null | grep "exported symbol" | sed 's/.*verified - //' | sed 's/.*verified (GPL) - //' | sort -u | wc -l || true) + VULN_PATHS_VERIFIED_COMPILED=$(cat "$LOG_PATH_MODULE"/CVE-*compiled_verified.txt 2>/dev/null | grep "compiled path verified" | sed 's/.*verified - //' | sort -u | wc -l || true) + CVE_VERIFIED_SYMBOLS=$(cat "$LOG_PATH_MODULE"/CVE-*symbol_verified.txt 2>/dev/null | grep "exported symbol" | cut -d\ -f1 | sort -u | wc -l || true) + CVE_VERIFIED_COMPILED=$(cat "$LOG_PATH_MODULE"/CVE-*compiled_verified.txt 2>/dev/null| grep "compiled path verified" | cut -d\ -f1 | sort -u | wc -l || true) + CVE_VERIFIED_ONE=$(cut -d\; -f6-7 "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv | grep -c "1" || true) + CVE_VERIFIED_OVERLAP=$(grep -c ";1;1" "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv || true) + mapfile -t CVE_VERIFIED_OVERLAP_CRITICAL < <(grep ";1;1$" "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv | grep ";9.[0-9];\|;10;" || true) + mapfile -t CVE_VERIFIED_ONE_CRITICAL < <(grep ";1;\|;1$" "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv | grep ";9.[0-9];\|;10;" || true) + + print_ln + print_bar + print_output "[+] Identified $ORANGE${#ALL_KVULNS[@]}$GREEN unverified CVE vulnerabilities for kernel version $ORANGE$K_VERSION$NC" + print_output "[*] Detected architecture $ORANGE$ORIG_K_ARCH$NC" + print_output "[*] Extracted $ORANGE$SYMBOLS_CNT$NC unique symbols from kernel and modules" + print_output "[*] Extracted $ORANGE$COMPILE_SOURCE_FILES$NC used source files during compilation" + print_output "[*] Found $ORANGE$CNT_PATHS_UNK$NC advisories with missing vulnerable path details" + print_output "[*] Found $ORANGE$CNT_PATHS_NOT_FOUND$NC path details in CVE advisories but no real kernel path found in vanilla kernel source" + print_output "[*] Found $ORANGE$CNT_PATHS_FOUND$NC path details in CVE advisories with real kernel path" + print_output "[*] Found $ORANGE$CNT_PATHS_FOUND_WRONG_ARCH$NC path details in CVE advisories with real kernel path but wrong architecture" + print_output "[*] $ORANGE$SYM_USAGE_VERIFIED$NC symbol usage verified" + print_output "[*] $ORANGE$VULN_PATHS_VERIFIED_SYMBOLS$NC vulnerable paths verified via symbols" + print_output "[*] $ORANGE$VULN_PATHS_VERIFIED_COMPILED$NC vulnerable paths verified via compiled paths" + print_ln + + if [[ "$CVE_VERIFIED_SYMBOLS" -gt 0 ]]; then + print_output "[+] Verified CVEs: $ORANGE$CVE_VERIFIED_SYMBOLS$GREEN (exported symbols)" + fi + if [[ "$CVE_VERIFIED_SYMBOLS" -gt 0 ]]; then + print_output "[+] Verified CVEs: $ORANGE$CVE_VERIFIED_COMPILED$GREEN (compiled paths)" + fi + if [[ "$CVE_VERIFIED_ONE" -gt 0 ]]; then + print_output "[+] Verified CVEs: $ORANGE$CVE_VERIFIED_ONE$GREEN (one mechanism success)" + fi + if [[ "$CVE_VERIFIED_OVERLAP" -gt 0 ]]; then + print_output "[+] Verified CVEs: $ORANGE$CVE_VERIFIED_OVERLAP$GREEN (both mechanisms overlap)" + fi + + if [[ "${#CVE_VERIFIED_ONE_CRITICAL[@]}" -gt 0 ]]; then + print_ln + print_output "[+] Verified CRITICAL CVEs: $ORANGE${#CVE_VERIFIED_ONE_CRITICAL[@]}$GREEN (one mechanisms success)" + for CVE_VERIFIED_ONE_CRITICAL_ in "${CVE_VERIFIED_ONE_CRITICAL[@]}"; do + CVE_CRITICAL=$(echo "$CVE_VERIFIED_ONE_CRITICAL_" | cut -d\; -f3) + CVSS2_CRITICAL=$(echo "$CVE_VERIFIED_ONE_CRITICAL_" | cut -d\; -f4) + CVSS3_CRITICAL=$(echo "$CVE_VERIFIED_ONE_CRITICAL_" | cut -d\; -f5) + identify_exploits "$CVE_CRITICAL" + print_output "$(indent "$(orange "$ORANGE$CVE_CRITICAL$GREEN - $ORANGE$CVSS2_CRITICAL$GREEN / $ORANGE$CVSS3_CRITICAL$GREEN - Exploit/PoC: $ORANGE$EXPLOIT_DETECTED / $POC_DETECTED$NC")")" + done + fi + + if [[ "${#CVE_VERIFIED_OVERLAP_CRITICAL[@]}" -gt 0 ]]; then + print_ln + print_output "[+] Verified CRITICAL CVEs: $ORANGE${#CVE_VERIFIED_OVERLAP_CRITICAL[@]}$GREEN (both mechanisms overlap)" + for CVE_VERIFIED_OVERLAP_CRITICAL_ in "${CVE_VERIFIED_OVERLAP_CRITICAL[@]}"; do + CVE_CRITICAL=$(echo "$CVE_VERIFIED_OVERLAP_CRITICAL_" | cut -d\; -f3) + CVSS2_CRITICAL=$(echo "$CVE_VERIFIED_OVERLAP_CRITICAL_" | cut -d\; -f4) + CVSS3_CRITICAL=$(echo "$CVE_VERIFIED_OVERLAP_CRITICAL_" | cut -d\; -f5) + identify_exploits "$CVE_CRITICAL" + print_output "$(indent "$(orange "$ORANGE$CVE_CRITICAL$GREEN - $ORANGE$CVSS2_CRITICAL$GREEN / $ORANGE$CVSS3_CRITICAL$GREEN - Exploit/PoC: $ORANGE$EXPLOIT_DETECTED / $POC_DETECTED$NC")")" + done + fi + print_bar +} + +identify_exploits() { + local CVE_VALUE="${1:-}" + EXPLOIT_DETECTED="no" + POC_DETECTED="no" + + local MSF_DB_PATH="$CONFIG_DIR/msf_cve-db.txt" + local KNOWN_EXP_CSV="$EXT_DIR/known_exploited_vulnerabilities.csv" + + if command -v cve_searchsploit >/dev/null; then + if cve_searchsploit "$CVE_VALUE" 2>/dev/null | grep -q "Exploit DB Id:"; then + EXPLOIT_DETECTED="yes" + fi + fi + if [[ -f "$MSF_DB_PATH" ]]; then + if grep -q -E "$CVE_VALUE"$ "$MSF_DB_PATH"; then + EXPLOIT_DETECTED="yes" + fi + fi + if [[ -f "$KNOWN_EXP_CSV" ]]; then + if grep -q \""${CVE_VALUE}"\", "$KNOWN_EXP_CSV"; then + EXPLOIT_DETECTED="yes" + fi + fi + if [[ -f "$TRICKEST_DB_PATH" ]]; then + if grep -q -E "$CVE_VALUE\.md" "$TRICKEST_DB_PATH"; then + POC_DETECTED="yes" + fi + fi +} + +get_csv_data_s24() { + local S24_CSV_LOG="${1:-}" + + if ! [[ -f "$S24_CSV_LOG" ]];then + print_output "[-] No EMBA log found ..." + return + fi + + local K_FOUND=0 + local KERNEL_DATA="" + local KERNEL_ELF_EMBA=() + export KERNEL_CONFIG_PATH="" + export KERNEL_ELF_PATH="" + export K_VERSION="" + + # currently we only support one kernel version + # if we detect multiple kernel versions we only process the first one after sorting + K_VERSION=$(cut -d\; -f2 "$S24_CSV_LOG" | tail -n +2 | grep -v "NA" | sort -u | head -1) + + print_output "[+] Identified kernel version: $ORANGE$K_VERSION$NC" + + mapfile -t KERNEL_ELF_EMBA < <(grep "$K_VERSION" "$S24_CSV_LOG" | cut -d\; -f4-7 | \ + grep -v "^NA" | grep -v "config extracted" | sort -u | sort -r -n -t\; -k4) + + for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do + if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f3)" == "NA" ]]; then + KERNEL_CONFIG_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f3) + #KERNEL_CONFIG_PATH="${KERNEL_CONFIG/\/logs\//"$EMBA_LOG_PATH"}" + print_output "[+] Found kernel configuration file: $ORANGE$KERNEL_CONFIG$NC" + KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) + # we use the first entry with a kernel config detected + K_FOUND=1 + break + fi + done + + if [[ "$K_FOUND" -ne 1 ]]; then + print_output "[-] No kernel configuration file found" + fi + if [[ "$K_FOUND" -ne 1 ]]; then + for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do + # now we check for init entries + if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f2)" == "NA" ]]; then + KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) + # we use the first entry with a kernel init detected + K_FOUND=1 + break + fi + done + fi + + if [[ "$K_FOUND" -ne 1 ]]; then + for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do + # this means we have not kernel configuration found + # and no init entry -> we just use the first valid elf file + if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f1)" == "NA" ]]; then + KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) + # we use the first entry as final resort + K_FOUND=1 + break + fi + done + fi + + if [[ "$K_FOUND" -ne 1 ]]; then + print_output "[-] No valid kernel information found ..." + fi +} + + From 0faac664e46986c9fa34bc9bb80b4668e97e9f74 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Sun, 4 Dec 2022 13:01:31 +0100 Subject: [PATCH 03/21] true it --- modules/S26_kernel_vuln_verifier.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index 848c94c48..5c59a8f6e 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -483,7 +483,7 @@ get_csv_data_s24() { print_output "[+] Identified kernel version: $ORANGE$K_VERSION$NC" mapfile -t KERNEL_ELF_EMBA < <(grep "$K_VERSION" "$S24_CSV_LOG" | cut -d\; -f4-7 | \ - grep -v "^NA" | grep -v "config extracted" | sort -u | sort -r -n -t\; -k4) + grep -v "^NA" | grep -v "config extracted" | sort -u | sort -r -n -t\; -k4 || true) for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f3)" == "NA" ]]; then From 6ba18a8832f3045c7f4c094f70c607aba419218c Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Fri, 16 Dec 2022 20:47:46 +0100 Subject: [PATCH 04/21] cleanup --- modules/S26_kernel_vuln_verifier.sh | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index 5c59a8f6e..50384c685 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -48,6 +48,7 @@ S26_kernel_vuln_verifier() return fi + # extract kernel version get_csv_data_s24 "$S24_CSV_LOG" if ! [[ -f "$KERNEL_ELF_PATH" ]]; then @@ -97,6 +98,11 @@ S26_kernel_vuln_verifier() while ! [[ -f "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" ]]; do print_output "[*] Waiting for kernel sources ..." "no_log" ((WAIT_CNT+=1)) + if [[ "$WAIT_CNT" -gt 60 ]]; then + print_output "[-] No kernel source file available ... exit module now" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi sleep 5 done @@ -128,14 +134,14 @@ S26_kernel_vuln_verifier() fi print_ln - print_output "[*] Create kernel symbols ..." + print_output "[*] Identify kernel symbols ..." readelf -s "$KERNEL_ELF_PATH" | grep "FUNC\|OBJECT" | sed 's/.*FUNC//' | sed 's/.*OBJECT//' | awk '{print $4}' | \ sed 's/\[\.\.\.\]//' > "$LOG_PATH_MODULE"/symbols.txt SYMBOLS_CNT=$(wc -l "$LOG_PATH_MODULE"/symbols.txt | awk '{print $1}') print_output "[*] Extracted $SYMBOLS_CNT symbols from kernel" if [[ -d "$LOG_DIR""/firmware" ]]; then - print_output "[*] Create kernel modules symbols array ..." + print_output "[*] Identify kernel modules symbols ..." find "$LOG_DIR/firmware" -name "*.ko" -exec readelf -a {} \; | grep FUNC | sed 's/.*FUNC//' | \ awk '{print $4}' | sed 's/\[\.\.\.\]//' >> "$LOG_PATH_MODULE"/symbols.txt fi @@ -167,7 +173,7 @@ S26_kernel_vuln_verifier() local NEG_LOG=1 print_ln - print_output "[*] Checking vulnerabilities" + print_output "[*] Checking vulnerabilities for kernel version $ORANGE$K_VERSION$NC" print_ln for VULN in "${ALL_KVULNS[@]}"; do @@ -181,10 +187,14 @@ S26_kernel_vuln_verifier() CVSS2="$(echo "$VULN" | cut -d: -f2)" CVSS3="$(echo "$VULN" | cut -d: -f3)" SUMMARY="$(echo "$VULN" | cut -d: -f4-)" + + # extract kernel source paths from summary -> we use these paths to check if they are used by our + # symbols or during kernel compilation mapfile -t K_PATHS < <(echo "$SUMMARY" | tr ' ' '\n' | grep ".*\.[chS]$" | sed -r 's/CVE-[0-9]+-[0-9]+:[0-9].*://' \ | sed -r 's/CVE-[0-9]+-[0-9]+:null.*://' | sed 's/^(//' | sed 's/)$//' | sed 's/,$//' | sed 's/\.$//' | cut -d: -f1 || true) for K_PATH in "${K_PATHS[@]}"; do + # we have only a filename without path -> we search for possible candidate files in the kernel sources if ! [[ "$K_PATH" == *"/"* ]]; then print_output "[*] Found file name $ORANGE$K_PATH$NC for $ORANGE$CVE$NC without path details ... looking for candidates now" mapfile -t K_PATHS_FILES_TMP < <(find "$KERNEL_DIR" -name "$K_PATH" | sed "s&$KERNEL_DIR\/&&") @@ -205,6 +215,7 @@ S26_kernel_vuln_verifier() compile_verifier "$CVE" "$K_VERSION" "$K_PATH" "$CVSS2/$CVSS3" & WAIT_PIDS_S26+=( "$!" ) else + # this vulnerability is for a different architecture -> we can skip it for our kernel print_output "[-] Vulnerable path for different architecture found for $ORANGE$K_PATH$NC - not further processing $ORANGE$CVE$NC" ((CNT_PATHS_FOUND_WRONG_ARCH+=1)) fi @@ -216,6 +227,7 @@ S26_kernel_vuln_verifier() WAIT_PIDS_S26+=( "$!" ) fi else + # no source file in our kernel sources -> no vulns print_output "[-] $ORANGE$CVE$NC - $ORANGE$K_PATH$NC - source file not found" ((CNT_PATHS_NOT_FOUND+=1)) fi @@ -273,6 +285,7 @@ symbol_verifier() { if [[ "$VULN_FOUND" -eq 1 ]]; then # if we have already a match for this path we can skip the 2nd check + # this is only for speed up the process a bit return fi @@ -305,6 +318,7 @@ compile_verifier() { } compile_kernel() { + # this is based on the great work shown here https://arxiv.org/pdf/2209.05217.pdf local KERNEL_CONFIG_FILE="${1:-}" local KERNEL_DIR="${2:-}" local KARCH="${3:-}" @@ -320,11 +334,11 @@ compile_kernel() { print_bar cd "$KERNEL_DIR" || exit - print_output "[*] Create default kernel config" + print_output "[*] Create default kernel config for $ORANGE$K_ARCH$NC architecture" LANG=en make ARCH="$KARCH" defconfig cp "$KERNEL_CONFIG_FILE" .config print_ln - print_output "[*] Update kernel config with the configuration of the firmware" + print_output "[*] Update kernel config with the identified configuration of the firmware" # https://stackoverflow.com/questions/4178526/what-does-make-oldconfig-do-exactly-in-the-linux-kernel-makefile LANG=en make ARCH="$KARCH" olddefconfig print_ln From 200a64446580f6facdd1e2ddb2411bbefec8d473 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Sat, 17 Dec 2022 14:18:14 +0100 Subject: [PATCH 05/21] cleanup --- modules/S26_kernel_vuln_verifier.sh | 45 +++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index 50384c685..5d898aa11 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -128,6 +128,7 @@ S26_kernel_vuln_verifier() print_output "[*] Create CVE vulnerabilities array for kernel version $ORANGE$K_VERSION$NC ..." mapfile -t ALL_KVULNS < <(jq -rc '"\(.id):\(.cvss):\(.cvss3):\(.summary)"' "$CVE_DETAILS_PATH") print_output "[+] Extracted $ORANGE${#ALL_KVULNS[@]}$GREEN vulnerabilities based on kernel version only" + print_output "[*] Starting in depth testing of these vulnerabilities ..." if [[ -f "$KERNEL_CONFIG" ]] && [[ -d "$KERNEL_DIR" ]]; then compile_kernel "$KERNEL_CONFIG" "$KERNEL_DIR" "$ORIG_K_ARCH" @@ -165,11 +166,11 @@ S26_kernel_vuln_verifier() sed -i 's/^/EXPORT_SYMBOL_GPL\(/' "$LOG_PATH_MODULE"/symbols_uniq.split_gpl.* sed -i 's/$/\)/' "$LOG_PATH_MODULE"/symbols_uniq.split_gpl.* - CNT_PATHS_UNK=0 - CNT_PATHS_FOUND=0 - CNT_PATHS_NOT_FOUND=0 - VULN_CNT=1 - CNT_PATHS_FOUND_WRONG_ARCH=0 + export CNT_PATHS_UNK=0 + export CNT_PATHS_FOUND=0 + export CNT_PATHS_NOT_FOUND=0 + export VULN_CNT=1 + export CNT_PATHS_FOUND_WRONG_ARCH=0 local NEG_LOG=1 print_ln @@ -177,13 +178,13 @@ S26_kernel_vuln_verifier() print_ln for VULN in "${ALL_KVULNS[@]}"; do - print_output "[*] Testing vulnerability $ORANGE$VULN_CNT$NC / $ORANGE${#ALL_KVULNS[@]}$NC" - K_PATHS=() K_PATHS_FILES_TMP=() K_PATH="undocumented source path" CVE=$(echo "$VULN" | cut -d: -f1) + print_output "[*] Testing vulnerability $ORANGE$VULN_CNT$NC / $ORANGE${#ALL_KVULNS[@]}$NC / $ORANGE$CVE$NC" + CVSS2="$(echo "$VULN" | cut -d: -f2)" CVSS3="$(echo "$VULN" | cut -d: -f3)" SUMMARY="$(echo "$VULN" | cut -d: -f4-)" @@ -322,6 +323,8 @@ compile_kernel() { local KERNEL_CONFIG_FILE="${1:-}" local KERNEL_DIR="${2:-}" local KARCH="${3:-}" + export COMPILE_SOURCE_FILES=0 + if ! [[ -f "$KERNEL_CONFIG_FILE" ]]; then return fi @@ -334,7 +337,7 @@ compile_kernel() { print_bar cd "$KERNEL_DIR" || exit - print_output "[*] Create default kernel config for $ORANGE$K_ARCH$NC architecture" + print_output "[*] Create default kernel config for $ORANGE$KARCH$NC architecture" LANG=en make ARCH="$KARCH" defconfig cp "$KERNEL_CONFIG_FILE" .config print_ln @@ -363,16 +366,30 @@ final_log_kernel_vulns() { rm -r "$LOG_PATH_MODULE"/symbols_uniq.split.* rm -r "$LOG_PATH_MODULE"/symbols_uniq.split_gpl.* - local CVE="" local VULN="" + local SYM_USAGE_VERIFIED=0 + local VULN_PATHS_VERIFIED_SYMBOLS=0 + local VULN_PATHS_VERIFIED_COMPILED=0 + local CVE_VERIFIED_SYMBOLS=0 + local CVE_VERIFIED_COMPILED=0 + local CVE_VERIFIED_ONE=0 + local CVE_VERIFIED_OVERLAP=0 + local CVE_VERIFIED_OVERLAP_CRITICAL=() + local CVE_VERIFIED_ONE_CRITICAL=() print_ln print_output "[*] Generating final kernel report ..." echo "Kernel version;Architecture;CVE;CVSSv2;CVSSv3;Verified with symbols;Verified with compile files" >> "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv for VULN in "${ALL_KVULNS[@]}"; do + local CVE="" + local CVSS2="" + local CVSS3="" local CVE_SYMBOL_FOUND=0 local CVE_COMPILE_FOUND=0 + local CVE_SYMBOL_FOUND=0 + local CVE_COMPILE_FOUND=0 + CVE=$(echo "$VULN" | cut -d: -f1) CVSS2="$(echo "$VULN" | cut -d: -f2)" CVSS3="$(echo "$VULN" | cut -d: -f3)" @@ -473,6 +490,16 @@ identify_exploits() { POC_DETECTED="yes" fi fi + if [[ -f "$CONF_DIR/Snyk_PoC_results.csv" ]]; then + if grep -q -E "^$CVE_VALUE;" "$CONF_DIR/Snyk_PoC_results.csv"; then + POC_DETECTED="yes" + fi + fi + if [[ -f "$CONF_DIR/PS_PoC_results.csv" ]]; then + if grep -q -E "^$CVE_VALUE;" "$CONF_DIR/PS_PoC_results.csv"; then + POC_DETECTED="yes" + fi + fi } get_csv_data_s24() { From 308ab7a85d081b85e80f3d0fcc6dacfe3c7e3620 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Sat, 24 Dec 2022 13:39:21 +0100 Subject: [PATCH 06/21] multiple kernel handling --- emba.sh | 2 + helpers/helpers_emba_helpers.sh | 2 +- helpers/helpers_emba_internet_access.sh | 16 +- modules/S26_kernel_vuln_verifier.sh | 448 ++++++++++++------------ 4 files changed, 240 insertions(+), 228 deletions(-) diff --git a/emba.sh b/emba.sh index 671f1d64c..eb35e4891 100755 --- a/emba.sh +++ b/emba.sh @@ -656,6 +656,8 @@ main() create_log_dir fi + # kernel downloader runs on the host and waits for an identified kernel version. Afterwards + # it tries to download the kernel sources for further analysis if [[ $IN_DOCKER -eq 0 ]]; then kernel_downloader & K_DOWN_PID="$!" diff --git a/helpers/helpers_emba_helpers.sh b/helpers/helpers_emba_helpers.sh index d71a1c710..e48717a60 100755 --- a/helpers/helpers_emba_helpers.sh +++ b/helpers/helpers_emba_helpers.sh @@ -137,7 +137,7 @@ cleaner() { fi if [[ "$IN_DOCKER" -eq 0 ]] && [[ -v K_DOWN_PID ]]; then - if ps -p "$K_DOWN_PID"; then + if ps -p "$K_DOWN_PID" > /dev/null; then # kernel downloader is running in a thread on the host and needs to be stopped now print_output "[*] Stopping kernel downloader thread with PID $K_DOWN_PID" "no_log" kill "$K_DOWN_PID" || true diff --git a/helpers/helpers_emba_internet_access.sh b/helpers/helpers_emba_internet_access.sh index 874f4c091..3178e6cec 100755 --- a/helpers/helpers_emba_internet_access.sh +++ b/helpers/helpers_emba_internet_access.sh @@ -14,6 +14,10 @@ # Description: Multiple useful helpers used to access online resources + +# kernel downloader waits for s24 results. If we were able to identify a kernel version, +# a kernel config or at least kernel symbols we can use these information to verify the +# vulnerabilities kernel_downloader() { LOG_FILE_KERNEL="$CSV_DIR"/s24_kernel_bin_identifier.csv KERNEL_ARCH_PATH="$EXT_DIR"/linux_kernel_sources/ @@ -23,14 +27,8 @@ kernel_downloader() { fi # we wait until the s24 module is finished and hopefully shows us a kernel version - while ! [[ -f "$LOG_DIR"/"$MAIN_LOG_FILE" ]]; do - sleep 1 - done - if [[ -f "$LOG_DIR"/"$MAIN_LOG_FILE" ]]; then - while [[ $(grep -c S24_kernel_bin_identifier "$LOG_DIR"/"$MAIN_LOG_FILE") -lt 2 ]]; do - sleep 1 - done - fi + module_wait "S24_kernel_bin_identifier" + # now we should have a csv log with a kernel version: if ! [[ -f "$LOG_FILE_KERNEL" ]]; then print_output "[-] No Kernel version identified ..." "no_log" @@ -66,6 +64,8 @@ kernel_downloader() { if ! [[ -f "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz ]]; then print_output "[*] Kernel download for version $ORANGE$K_VERSION$NC" "no_log" wget https://mirrors.edge.kernel.org/pub/linux/kernel/v"$K_VER_DOWNLOAD"/linux-"$K_VERSION".tar.gz -O "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz || true + else + print_output "[*] Kernel sources of version $ORANGE$K_VERSION$NC already available" "no_log" fi if ! [[ -f "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz ]]; then diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index 5d898aa11..659ba8c94 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -12,7 +12,7 @@ # # Author(s): Michael Messner -# Description: After the s24 module was able to identify the kernel, the downloader +# Description: After module s24 was able to identify the kernel, the downloader # helper function "kernel_downloader" has downloaded the kernel sources # This module checks if we have symbols and/or the kernel config extracted, # identifies vulnerabilities via the version number and tries to verify the @@ -33,17 +33,11 @@ S26_kernel_vuln_verifier() NEG_LOG=0 # we wait until the s24 module is finished and hopefully shows us a kernel version - while ! [[ -f "$LOG_DIR"/"$MAIN_LOG_FILE" ]]; do - sleep 1 - done - if [[ -f "$LOG_DIR"/"$MAIN_LOG_FILE" ]]; then - while [[ $(grep -c S24_kernel_bin_identifier "$LOG_DIR"/"$MAIN_LOG_FILE") -lt 2 ]]; do - sleep 1 - done - fi + module_wait "S24_kernel_bin_identifier" + # now we should have a csv log with a kernel version: if ! [[ -f "$S24_CSV_LOG" ]] || [[ "$(wc -l "$S24_CSV_LOG" | awk '{print $1}')" -lt 2 ]]; then - print_output "[-] No Kernel version file identified ..." + print_output "[-] No Kernel version file (s24 results) identified ..." module_end_log "${FUNCNAME[0]}" "$NEG_LOG" return fi @@ -51,194 +45,247 @@ S26_kernel_vuln_verifier() # extract kernel version get_csv_data_s24 "$S24_CSV_LOG" - if ! [[ -f "$KERNEL_ELF_PATH" ]]; then - print_output "[-] Warning: Kernel ELF file not found" - module_end_log "${FUNCNAME[0]}" "$NEG_LOG" - return - fi - if ! [[ -v K_VERSION ]]; then - print_output "[-] Missing kernel version .. exit now" - module_end_log "${FUNCNAME[0]}" "$NEG_LOG" - return - fi + local KERNEL_DATA="" + local KERNEL_ELF_EMBA=() + export KERNEL_CONFIG_PATH="" + export KERNEL_ELF_PATH="" - CVE_DETAILS_PATH="$LOG_PATH_MODULE""/kernel-$K_VERSION-vulns.json" + for K_VERSION in "${K_VERSIONS[@]}"; do + local K_FOUND=0 + print_output "[+] Identified kernel version: $ORANGE$K_VERSION$NC" - if ! [[ -f $PATH_CVE_SEARCH ]]; then - print_output "[-] CVE search binary search.py not found." - print_output "[-] Run the installer or install it from here: https://github.com/cve-search/cve-search." - print_output "[-] Installation instructions can be found on github.io: https://cve-search.github.io/cve-search/getting_started/installation.html#installation" - module_end_log "${FUNCNAME[0]}" "$NEG_LOG" - return - fi + mapfile -t KERNEL_ELF_EMBA < <(grep "$K_VERSION" "$S24_CSV_LOG" | cut -d\; -f4-7 | \ + grep -v "^NA" | grep -v "config extracted" | sort -u | sort -r -n -t\; -k4 || true) + + # we check for a kernel configuration + for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do + if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f3)" == "NA" ]]; then + KERNEL_CONFIG_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f3) + print_output "[+] Found kernel configuration file: $ORANGE$KERNEL_CONFIG$NC" + # we use the first entry with a kernel config detected + KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) + K_FOUND=1 + break + fi + done + + if [[ "$K_FOUND" -ne 1 ]]; then + print_output "[-] No kernel configuration file found for kernel $ORANGE$K_VERSION$NC." + fi + + if [[ "$K_FOUND" -ne 1 ]]; then + for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do + # now we check for init entries + if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f2)" == "NA" ]]; then + KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) + # we use the first entry with a kernel init detected + K_FOUND=1 + break + fi + done + fi + + if [[ "$K_FOUND" -ne 1 ]]; then + for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do + # this means we have not kernel configuration found + # and no init entry -> we just use the first valid elf file + if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f1)" == "NA" ]]; then + KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) + # we use the first entry as final resort + K_FOUND=1 + break + fi + done + fi + + if [[ "$K_FOUND" -ne 1 ]]; then + print_output "[-] No valid kernel information found for kernel $ORANGE$K_VERSION$NC." + continue + fi - check_cve_search + if ! [[ -f "$KERNEL_ELF_PATH" ]]; then + print_output "[-] Warning: Kernel ELF file not found" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + continue + fi + if ! [[ -v K_VERSION ]]; then + print_output "[-] Missing kernel version .. exit now" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + continue + fi + + CVE_DETAILS_PATH="$LOG_PATH_MODULE""/kernel-$K_VERSION-vulns.json" + + if ! [[ -f $PATH_CVE_SEARCH ]]; then + print_output "[-] CVE search binary search.py not found." + print_output "[-] Run the installer or install it from here: https://github.com/cve-search/cve-search." + print_output "[-] Installation instructions can be found on github.io: https://cve-search.github.io/cve-search/getting_started/installation.html#installation" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi - if [[ "$CVE_SEARCH" -eq 0 ]]; then - print_output "[*] Waiting for the cve-search environment ..." - sleep 120 check_cve_search if [[ "$CVE_SEARCH" -eq 0 ]]; then print_output "[*] Waiting for the cve-search environment ..." sleep 120 check_cve_search - fi - fi - if [[ "$CVE_SEARCH" -ne 1 ]]; then - print_cve_search_failure - return - fi - if [[ -f "$KERNEL_ELF_PATH" ]]; then - extract_kernel_arch "$KERNEL_ELF_PATH" - fi - - WAIT_CNT=0 - while ! [[ -f "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" ]]; do - print_output "[*] Waiting for kernel sources ..." "no_log" - ((WAIT_CNT+=1)) - if [[ "$WAIT_CNT" -gt 60 ]]; then - print_output "[-] No kernel source file available ... exit module now" - module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + if [[ "$CVE_SEARCH" -eq 0 ]]; then + print_output "[*] Waiting for the cve-search environment ..." + sleep 120 + check_cve_search + fi + fi + if [[ "$CVE_SEARCH" -ne 1 ]]; then + print_cve_search_failure return fi - sleep 5 - done - print_output "[*] Kernel archive for version $ORANGE$K_VERSION$NC available" + if [[ -f "$KERNEL_ELF_PATH" ]]; then + extract_kernel_arch "$KERNEL_ELF_PATH" + fi - KERNEL_DIR="$LOG_PATH_MODULE/linux-$K_VERSION" - if [[ -d "$KERNEL_DIR" ]]; then - rm -rf "$KERNEL_DIR" - fi - if ! [[ -d "$KERNEL_DIR" ]] && [[ "$(file "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz")" == *"gzip compressed data"* ]]; then - print_output "[*] Kernel extract for version $ORANGE$K_VERSION$NC" - tar -xzf "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" -C "$LOG_PATH_MODULE" - fi + WAIT_CNT=0 + while ! [[ -f "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" ]]; do + print_output "[*] Waiting for kernel sources ..." "no_log" + ((WAIT_CNT+=1)) + if [[ "$WAIT_CNT" -gt 60 ]]; then + print_output "[-] No kernel source file available ... exit module now" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi + sleep 5 + done - get_cve_kernel_data + print_output "[*] Kernel sources for version $ORANGE$K_VERSION$NC available" - if ! [[ -f "$CVE_DETAILS_PATH" ]]; then - print_output "[-] No CVE details generated ... return" - module_end_log "${FUNCNAME[0]}" "$NEG_LOG" - return - fi + KERNEL_DIR="$LOG_PATH_MODULE/linux-$K_VERSION" + if [[ -d "$KERNEL_DIR" ]]; then + rm -rf "$KERNEL_DIR" + fi + if ! [[ -d "$KERNEL_DIR" ]] && [[ "$(file "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz")" == *"gzip compressed data"* ]]; then + print_output "[*] Kernel extract for version $ORANGE$K_VERSION$NC" + tar -xzf "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" -C "$LOG_PATH_MODULE" + fi - print_output "[*] Create CVE vulnerabilities array for kernel version $ORANGE$K_VERSION$NC ..." - mapfile -t ALL_KVULNS < <(jq -rc '"\(.id):\(.cvss):\(.cvss3):\(.summary)"' "$CVE_DETAILS_PATH") - print_output "[+] Extracted $ORANGE${#ALL_KVULNS[@]}$GREEN vulnerabilities based on kernel version only" - print_output "[*] Starting in depth testing of these vulnerabilities ..." + # we get a file with the results in $CVE_DETAILS_PATH + get_cve_kernel_data "$K_VERSION" - if [[ -f "$KERNEL_CONFIG" ]] && [[ -d "$KERNEL_DIR" ]]; then - compile_kernel "$KERNEL_CONFIG" "$KERNEL_DIR" "$ORIG_K_ARCH" - fi + if ! [[ -f "$CVE_DETAILS_PATH" ]]; then + print_output "[-] No CVE details generated ... return" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi - print_ln - print_output "[*] Identify kernel symbols ..." - readelf -s "$KERNEL_ELF_PATH" | grep "FUNC\|OBJECT" | sed 's/.*FUNC//' | sed 's/.*OBJECT//' | awk '{print $4}' | \ - sed 's/\[\.\.\.\]//' > "$LOG_PATH_MODULE"/symbols.txt - SYMBOLS_CNT=$(wc -l "$LOG_PATH_MODULE"/symbols.txt | awk '{print $1}') - print_output "[*] Extracted $SYMBOLS_CNT symbols from kernel" - - if [[ -d "$LOG_DIR""/firmware" ]]; then - print_output "[*] Identify kernel modules symbols ..." - find "$LOG_DIR/firmware" -name "*.ko" -exec readelf -a {} \; | grep FUNC | sed 's/.*FUNC//' | \ - awk '{print $4}' | sed 's/\[\.\.\.\]//' >> "$LOG_PATH_MODULE"/symbols.txt - fi + print_output "[*] Create CVE vulnerabilities array for kernel version $ORANGE$K_VERSION$NC ..." + mapfile -t ALL_KVULNS < <(jq -rc '"\(.id):\(.cvss):\(.cvss3):\(.summary)"' "$CVE_DETAILS_PATH") + print_output "[+] Extracted $ORANGE${#ALL_KVULNS[@]}$GREEN vulnerabilities based on kernel version only" + print_output "[*] Starting in depth testing of these vulnerabilities ..." + + if [[ -f "$KERNEL_CONFIG" ]] && [[ -d "$KERNEL_DIR" ]]; then + compile_kernel "$KERNEL_CONFIG" "$KERNEL_DIR" "$ORIG_K_ARCH" + fi - uniq "$LOG_PATH_MODULE"/symbols.txt > "$LOG_PATH_MODULE"/symbols_uniq.txt - SYMBOLS_CNT=$(wc -l "$LOG_PATH_MODULE"/symbols_uniq.txt | awk '{print $1}') - print_output "[*] Extracted $ORANGE$SYMBOLS_CNT$NC unique symbols" + print_ln + print_output "[*] Identify kernel symbols ..." + readelf -s "$KERNEL_ELF_PATH" | grep "FUNC\|OBJECT" | sed 's/.*FUNC//' | sed 's/.*OBJECT//' | awk '{print $4}' | \ + sed 's/\[\.\.\.\]//' > "$LOG_PATH_MODULE"/symbols.txt + SYMBOLS_CNT=$(wc -l "$LOG_PATH_MODULE"/symbols.txt | awk '{print $1}') + print_output "[*] Extracted $SYMBOLS_CNT symbols from kernel" + + if [[ -d "$LOG_DIR""/firmware" ]]; then + print_output "[*] Identify kernel modules symbols ..." + find "$LOG_DIR/firmware" -name "*.ko" -exec readelf -a {} \; | grep FUNC | sed 's/.*FUNC//' | \ + awk '{print $4}' | sed 's/\[\.\.\.\]//' >> "$LOG_PATH_MODULE"/symbols.txt + fi - if [[ "$SYMBOLS_CNT" -eq 0 ]]; then - print_output "[-] No symbols found ... exit" - module_end_log "${FUNCNAME[0]}" "$NEG_LOG" - return - fi + uniq "$LOG_PATH_MODULE"/symbols.txt > "$LOG_PATH_MODULE"/symbols_uniq.txt + SYMBOLS_CNT=$(wc -l "$LOG_PATH_MODULE"/symbols_uniq.txt | awk '{print $1}') + print_output "[*] Extracted $ORANGE$SYMBOLS_CNT$NC unique symbols" - print_output "[*] Splitting symbols file for processing" - split -l 100 "$LOG_PATH_MODULE"/symbols_uniq.txt "$LOG_PATH_MODULE"/symbols_uniq.split. - sed -i 's/^/EXPORT_SYMBOL\(/' "$LOG_PATH_MODULE"/symbols_uniq.split.* - sed -i 's/$/\)/' "$LOG_PATH_MODULE"/symbols_uniq.split.* + if [[ "$SYMBOLS_CNT" -eq 0 ]]; then + print_output "[-] No symbols found ... exit" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi - split -l 100 "$LOG_PATH_MODULE"/symbols_uniq.txt "$LOG_PATH_MODULE"/symbols_uniq.split_gpl. - sed -i 's/^/EXPORT_SYMBOL_GPL\(/' "$LOG_PATH_MODULE"/symbols_uniq.split_gpl.* - sed -i 's/$/\)/' "$LOG_PATH_MODULE"/symbols_uniq.split_gpl.* + split_symbols_file - export CNT_PATHS_UNK=0 - export CNT_PATHS_FOUND=0 - export CNT_PATHS_NOT_FOUND=0 - export VULN_CNT=1 - export CNT_PATHS_FOUND_WRONG_ARCH=0 - local NEG_LOG=1 + export CNT_PATHS_UNK=0 + export CNT_PATHS_FOUND=0 + export CNT_PATHS_NOT_FOUND=0 + export VULN_CNT=1 + export CNT_PATHS_FOUND_WRONG_ARCH=0 + local NEG_LOG=1 - print_ln - print_output "[*] Checking vulnerabilities for kernel version $ORANGE$K_VERSION$NC" - print_ln + print_ln + print_output "[*] Checking vulnerabilities for kernel version $ORANGE$K_VERSION$NC" + print_ln - for VULN in "${ALL_KVULNS[@]}"; do - K_PATHS=() - K_PATHS_FILES_TMP=() - K_PATH="undocumented source path" + for VULN in "${ALL_KVULNS[@]}"; do + K_PATHS=() + K_PATHS_FILES_TMP=() + K_PATH="undocumented source path" - CVE=$(echo "$VULN" | cut -d: -f1) - print_output "[*] Testing vulnerability $ORANGE$VULN_CNT$NC / $ORANGE${#ALL_KVULNS[@]}$NC / $ORANGE$CVE$NC" + CVE=$(echo "$VULN" | cut -d: -f1) + print_output "[*] Testing vulnerability $ORANGE$VULN_CNT$NC / $ORANGE${#ALL_KVULNS[@]}$NC / $ORANGE$CVE$NC" - CVSS2="$(echo "$VULN" | cut -d: -f2)" - CVSS3="$(echo "$VULN" | cut -d: -f3)" - SUMMARY="$(echo "$VULN" | cut -d: -f4-)" - - # extract kernel source paths from summary -> we use these paths to check if they are used by our - # symbols or during kernel compilation - mapfile -t K_PATHS < <(echo "$SUMMARY" | tr ' ' '\n' | grep ".*\.[chS]$" | sed -r 's/CVE-[0-9]+-[0-9]+:[0-9].*://' \ - | sed -r 's/CVE-[0-9]+-[0-9]+:null.*://' | sed 's/^(//' | sed 's/)$//' | sed 's/,$//' | sed 's/\.$//' | cut -d: -f1 || true) - - for K_PATH in "${K_PATHS[@]}"; do - # we have only a filename without path -> we search for possible candidate files in the kernel sources - if ! [[ "$K_PATH" == *"/"* ]]; then - print_output "[*] Found file name $ORANGE$K_PATH$NC for $ORANGE$CVE$NC without path details ... looking for candidates now" - mapfile -t K_PATHS_FILES_TMP < <(find "$KERNEL_DIR" -name "$K_PATH" | sed "s&$KERNEL_DIR\/&&") - fi - K_PATHS+=("${K_PATHS_FILES_TMP[@]}") - done + CVSS2="$(echo "$VULN" | cut -d: -f2)" + CVSS3="$(echo "$VULN" | cut -d: -f3)" + SUMMARY="$(echo "$VULN" | cut -d: -f4-)" + + # extract kernel source paths from summary -> we use these paths to check if they are used by our + # symbols or during kernel compilation + mapfile -t K_PATHS < <(echo "$SUMMARY" | tr ' ' '\n' | grep ".*\.[chS]$" | sed -r 's/CVE-[0-9]+-[0-9]+:[0-9].*://' \ + | sed -r 's/CVE-[0-9]+-[0-9]+:null.*://' | sed 's/^(//' | sed 's/)$//' | sed 's/,$//' | sed 's/\.$//' | cut -d: -f1 || true) - if [[ "${#K_PATHS[@]}" -gt 0 ]]; then for K_PATH in "${K_PATHS[@]}"; do - if [[ -f "$KERNEL_DIR/$K_PATH" ]]; then - # check if arch is in path -> if so we check if our architecture is also in the path - # if we find our architecture then we can proceed with symbol_verifier - if [[ "$K_PATH" == "arch/"* ]]; then - if [[ "$K_PATH" == "arch/$ORIG_K_ARCH/"* ]]; then + # we have only a filename without path -> we search for possible candidate files in the kernel sources + if ! [[ "$K_PATH" == *"/"* ]]; then + print_output "[*] Found file name $ORANGE$K_PATH$NC for $ORANGE$CVE$NC without path details ... looking for candidates now" + mapfile -t K_PATHS_FILES_TMP < <(find "$KERNEL_DIR" -name "$K_PATH" | sed "s&$KERNEL_DIR\/&&") + fi + K_PATHS+=("${K_PATHS_FILES_TMP[@]}") + done + + if [[ "${#K_PATHS[@]}" -gt 0 ]]; then + for K_PATH in "${K_PATHS[@]}"; do + if [[ -f "$KERNEL_DIR/$K_PATH" ]]; then + # check if arch is in path -> if so we check if our architecture is also in the path + # if we find our architecture then we can proceed with symbol_verifier + if [[ "$K_PATH" == "arch/"* ]]; then + if [[ "$K_PATH" == "arch/$ORIG_K_ARCH/"* ]]; then + ((CNT_PATHS_FOUND+=1)) + symbol_verifier "$CVE" "$K_VERSION" "$K_PATH" "$CVSS2/$CVSS3" & + WAIT_PIDS_S26+=( "$!" ) + compile_verifier "$CVE" "$K_VERSION" "$K_PATH" "$CVSS2/$CVSS3" & + WAIT_PIDS_S26+=( "$!" ) + else + # this vulnerability is for a different architecture -> we can skip it for our kernel + print_output "[-] Vulnerable path for different architecture found for $ORANGE$K_PATH$NC - not further processing $ORANGE$CVE$NC" + ((CNT_PATHS_FOUND_WRONG_ARCH+=1)) + fi + else ((CNT_PATHS_FOUND+=1)) symbol_verifier "$CVE" "$K_VERSION" "$K_PATH" "$CVSS2/$CVSS3" & WAIT_PIDS_S26+=( "$!" ) compile_verifier "$CVE" "$K_VERSION" "$K_PATH" "$CVSS2/$CVSS3" & WAIT_PIDS_S26+=( "$!" ) - else - # this vulnerability is for a different architecture -> we can skip it for our kernel - print_output "[-] Vulnerable path for different architecture found for $ORANGE$K_PATH$NC - not further processing $ORANGE$CVE$NC" - ((CNT_PATHS_FOUND_WRONG_ARCH+=1)) fi else - ((CNT_PATHS_FOUND+=1)) - symbol_verifier "$CVE" "$K_VERSION" "$K_PATH" "$CVSS2/$CVSS3" & - WAIT_PIDS_S26+=( "$!" ) - compile_verifier "$CVE" "$K_VERSION" "$K_PATH" "$CVSS2/$CVSS3" & - WAIT_PIDS_S26+=( "$!" ) + # no source file in our kernel sources -> no vulns + print_output "[-] $ORANGE$CVE$NC - $ORANGE$K_PATH$NC - source file not found" + ((CNT_PATHS_NOT_FOUND+=1)) fi - else - # no source file in our kernel sources -> no vulns - print_output "[-] $ORANGE$CVE$NC - $ORANGE$K_PATH$NC - source file not found" - ((CNT_PATHS_NOT_FOUND+=1)) - fi - max_pids_protection 20 "${WAIT_PIDS_S26[@]}" - done - else - print_output "[-] $CVE - $K_PATH" - ((CNT_PATHS_UNK+=1)) - fi - ((VULN_CNT+=1)) + max_pids_protection 20 "${WAIT_PIDS_S26[@]}" + done + else + print_output "[-] $CVE - $K_PATH" + ((CNT_PATHS_UNK+=1)) + fi + ((VULN_CNT+=1)) + done done wait_for_pid "${WAIT_PIDS_S26[@]}" @@ -248,9 +295,21 @@ S26_kernel_vuln_verifier() module_end_log "${FUNCNAME[0]}" "$NEG_LOG" } +split_symbols_file() { + print_output "[*] Splitting symbols file for processing" + split -l 100 "$LOG_PATH_MODULE"/symbols_uniq.txt "$LOG_PATH_MODULE"/symbols_uniq.split. + sed -i 's/^/EXPORT_SYMBOL\(/' "$LOG_PATH_MODULE"/symbols_uniq.split.* + sed -i 's/$/\)/' "$LOG_PATH_MODULE"/symbols_uniq.split.* + + split -l 100 "$LOG_PATH_MODULE"/symbols_uniq.txt "$LOG_PATH_MODULE"/symbols_uniq.split_gpl. + sed -i 's/^/EXPORT_SYMBOL_GPL\(/' "$LOG_PATH_MODULE"/symbols_uniq.split_gpl.* + sed -i 's/$/\)/' "$LOG_PATH_MODULE"/symbols_uniq.split_gpl.* +} + get_cve_kernel_data() { - print_output "[*] Extract CVE data for kernel version $ORANGE$K_VERSION$NC" - "$PATH_CVE_SEARCH" -p linux_kernel:"$K_VERSION" -o json > "$CVE_DETAILS_PATH" + local K_VERSION_="${1:-}" + print_output "[*] Extract CVE data for kernel version $ORANGE$K_VERSION_$NC" + "$PATH_CVE_SEARCH" -p "linux_kernel:""$K_VERSION_"":" -o json > "$CVE_DETAILS_PATH" } extract_kernel_arch() { @@ -381,6 +440,8 @@ final_log_kernel_vulns() { print_output "[*] Generating final kernel report ..." echo "Kernel version;Architecture;CVE;CVSSv2;CVSSv3;Verified with symbols;Verified with compile files" >> "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv + # we walk through the original version based kernel vulnerabilities and report the results + # from symbols and kernel configuration for VULN in "${ALL_KVULNS[@]}"; do local CVE="" local CVSS2="" @@ -398,7 +459,7 @@ final_log_kernel_vulns() { echo "$K_VERSION;$ORIG_K_ARCH;$CVE;$CVSS2;$CVSS3;$CVE_SYMBOL_FOUND;$CVE_COMPILE_FOUND" >> "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv done - SYM_USAGE_VERIFIED=$(cat "$LOG_PATH_MODULE"/CVE-*symbol_* | wc -l 2>/dev/null) + SYM_USAGE_VERIFIED=$(wc -l "$LOG_PATH_MODULE"/CVE-*symbol_* | tail -1 | awk '{print $1}' 2>/dev/null) VULN_PATHS_VERIFIED_SYMBOLS=$(cat "$LOG_PATH_MODULE"/CVE-*symbol_verified.txt 2>/dev/null | grep "exported symbol" | sed 's/.*verified - //' | sed 's/.*verified (GPL) - //' | sort -u | wc -l || true) VULN_PATHS_VERIFIED_COMPILED=$(cat "$LOG_PATH_MODULE"/CVE-*compiled_verified.txt 2>/dev/null | grep "compiled path verified" | sed 's/.*verified - //' | sort -u | wc -l || true) CVE_VERIFIED_SYMBOLS=$(cat "$LOG_PATH_MODULE"/CVE-*symbol_verified.txt 2>/dev/null | grep "exported symbol" | cut -d\ -f1 | sort -u | wc -l || true) @@ -413,7 +474,9 @@ final_log_kernel_vulns() { print_output "[+] Identified $ORANGE${#ALL_KVULNS[@]}$GREEN unverified CVE vulnerabilities for kernel version $ORANGE$K_VERSION$NC" print_output "[*] Detected architecture $ORANGE$ORIG_K_ARCH$NC" print_output "[*] Extracted $ORANGE$SYMBOLS_CNT$NC unique symbols from kernel and modules" - print_output "[*] Extracted $ORANGE$COMPILE_SOURCE_FILES$NC used source files during compilation" + if [[ "$COMPILE_SOURCE_FILES" -gt 0 ]]; then + print_output "[*] Extracted $ORANGE$COMPILE_SOURCE_FILES$NC used source files during compilation" + fi print_output "[*] Found $ORANGE$CNT_PATHS_UNK$NC advisories with missing vulnerable path details" print_output "[*] Found $ORANGE$CNT_PATHS_NOT_FOUND$NC path details in CVE advisories but no real kernel path found in vanilla kernel source" print_output "[*] Found $ORANGE$CNT_PATHS_FOUND$NC path details in CVE advisories with real kernel path" @@ -510,65 +573,12 @@ get_csv_data_s24() { return fi - local K_FOUND=0 - local KERNEL_DATA="" - local KERNEL_ELF_EMBA=() - export KERNEL_CONFIG_PATH="" - export KERNEL_ELF_PATH="" - export K_VERSION="" + export K_VERSIONS=() # currently we only support one kernel version # if we detect multiple kernel versions we only process the first one after sorting - K_VERSION=$(cut -d\; -f2 "$S24_CSV_LOG" | tail -n +2 | grep -v "NA" | sort -u | head -1) - - print_output "[+] Identified kernel version: $ORANGE$K_VERSION$NC" - - mapfile -t KERNEL_ELF_EMBA < <(grep "$K_VERSION" "$S24_CSV_LOG" | cut -d\; -f4-7 | \ - grep -v "^NA" | grep -v "config extracted" | sort -u | sort -r -n -t\; -k4 || true) - - for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do - if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f3)" == "NA" ]]; then - KERNEL_CONFIG_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f3) - #KERNEL_CONFIG_PATH="${KERNEL_CONFIG/\/logs\//"$EMBA_LOG_PATH"}" - print_output "[+] Found kernel configuration file: $ORANGE$KERNEL_CONFIG$NC" - KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) - # we use the first entry with a kernel config detected - K_FOUND=1 - break - fi - done - - if [[ "$K_FOUND" -ne 1 ]]; then - print_output "[-] No kernel configuration file found" - fi - if [[ "$K_FOUND" -ne 1 ]]; then - for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do - # now we check for init entries - if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f2)" == "NA" ]]; then - KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) - # we use the first entry with a kernel init detected - K_FOUND=1 - break - fi - done - fi - - if [[ "$K_FOUND" -ne 1 ]]; then - for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do - # this means we have not kernel configuration found - # and no init entry -> we just use the first valid elf file - if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f1)" == "NA" ]]; then - KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) - # we use the first entry as final resort - K_FOUND=1 - break - fi - done - fi - - if [[ "$K_FOUND" -ne 1 ]]; then - print_output "[-] No valid kernel information found ..." - fi + mapfile -t K_VERSIONS < <(cut -d\; -f2 "$S24_CSV_LOG" | tail -n +2 | grep -v "NA" | sort -u) + } From 8102f547d457fbff707e3b5b77ba612db9669540 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Tue, 27 Dec 2022 17:16:43 +0100 Subject: [PATCH 07/21] updates for kernel verifier --- helpers/helpers_emba_internet_access.sh | 9 +- modules/F20_vul_aggregator.sh | 41 +++++++- modules/S26_kernel_vuln_verifier.sh | 124 ++++++++++++++---------- 3 files changed, 121 insertions(+), 53 deletions(-) diff --git a/helpers/helpers_emba_internet_access.sh b/helpers/helpers_emba_internet_access.sh index 3178e6cec..8d3c980f5 100755 --- a/helpers/helpers_emba_internet_access.sh +++ b/helpers/helpers_emba_internet_access.sh @@ -27,7 +27,14 @@ kernel_downloader() { fi # we wait until the s24 module is finished and hopefully shows us a kernel version - module_wait "S24_kernel_bin_identifier" + while ! [[ -f "$LOG_DIR"/"$MAIN_LOG_FILE" ]]; do + sleep 1 + done + if [[ -f "$LOG_DIR"/"$MAIN_LOG_FILE" ]]; then + while [[ $(grep -c S24_kernel_bin_identifier "$LOG_DIR"/"$MAIN_LOG_FILE") -lt 2 ]]; do + sleep 1 + done + fi # now we should have a csv log with a kernel version: if ! [[ -f "$LOG_FILE_KERNEL" ]]; then diff --git a/modules/F20_vul_aggregator.sh b/modules/F20_vul_aggregator.sh index 568eb525e..7fbb328b9 100755 --- a/modules/F20_vul_aggregator.sh +++ b/modules/F20_vul_aggregator.sh @@ -57,10 +57,14 @@ F20_vul_aggregator() { local S08_LOG="$CSV_DIR"/s08_package_mgmt_extractor.csv local S09_LOG="$CSV_DIR"/s09_firmware_base_version_check.csv local S25_LOG="$CSV_DIR"/s25_kernel_check.csv + local S26_LOG="$LOG_DIR""/s26_kernel_vuln_verifier/" local S116_LOG="$CSV_DIR"/s116_qemu_version_detection.csv local L15_LOG="$CSV_DIR"/l15_emulated_checks_nmap.csv local L25_LOG="$CSV_DIR"/l25_web_checks.csv local L35_LOG="$CSV_DIR"/l35_metasploit_check.csv + if [[ -d "$S26_LOG" ]]; then + mapfile -t S26_LOGS_ARR < <(find "$S26_LOG" -name "cve_results_kernel_*.csv") + fi local CVE_MINIMAL_LOG="$LOG_PATH_MODULE"/CVE_minimal.txt local EXPLOIT_OVERVIEW_LOG="$LOG_PATH_MODULE"/exploits-overview.txt @@ -85,6 +89,10 @@ F20_vul_aggregator() { fi fi + if [[ -v S26_LOGS_ARR ]]; then + get_kernel_verified "${S26_LOGS_ARR[@]}" + fi + get_uefi_details "$S02_LOG" get_firmware_details "$S06_LOG" get_package_details "$S08_LOG" @@ -162,7 +170,10 @@ aggregate_versions() { export VERSIONS_AGGREGATED=() VERSIONS_KERNEL=() - if [[ ${#VERSIONS_STAT_CHECK[@]} -gt 0 || ${#VERSIONS_EMULATOR[@]} -gt 0 || ${#KERNEL_CVE_EXPLOITS[@]} -gt 0 || ${#VERSIONS_SYS_EMULATOR[@]} || ${#VERSIONS_S06_FW_DETAILS[@]} -gt 0 || ${#VERSIONS_SYS_EMULATOR_WEB[@]} -gt 0 || "${#CVE_S02_DETAILS[@]}" -gt 0 || "${#CVE_L35_DETAILS[@]}" -gt 0 ]]; then + if [[ ${#VERSIONS_STAT_CHECK[@]} -gt 0 || ${#VERSIONS_EMULATOR[@]} -gt 0 || ${#KERNEL_CVE_EXPLOITS[@]} -gt 0 || ${#VERSIONS_SYS_EMULATOR[@]} -gt 0 || \ + ${#VERSIONS_S06_FW_DETAILS[@]} -gt 0 || ${#VERSIONS_SYS_EMULATOR_WEB[@]} -gt 0 || "${#CVE_S02_DETAILS[@]}" -gt 0 || "${#CVE_L35_DETAILS[@]}" -gt 0 || \ + ${#KERNEL_CVE_VERIFIED[@]} -gt 0 ]]; then + print_output "[*] Software inventory initial overview:" write_anchor "softwareinventoryinitialoverview" for VERSION in "${VERSIONS_S06_FW_DETAILS[@]}"; do @@ -214,6 +225,19 @@ aggregate_versions() { #print_output "[+] Added modfied Kernel Version details (${ORANGE}kernel$GREEN): ""$ORANGE$VERSION$NC" done + for VERSION in "${KERNEL_CVE_VERIFIED_VERSION[@]}"; do + if [ -z "$VERSION" ]; then + continue + fi + VERSION="$(echo "$VERSION" | cut -d\; -f1) | sed 's/^/kernel:/')" + print_output "[+] Found Version details with verified vulnerability details (${ORANGE}kernel$GREEN): ""$ORANGE$VERSION$NC" + # we ensure that we search for the correct kernel version by adding a : at the end of the search string + VERSION=${VERSION/%/:} + VERSIONS_KERNEL+=( "$VERSION" ) + #print_output "[+] Added modfied Kernel Version details (${ORANGE}kernel$GREEN): ""$ORANGE$VERSION$NC" + done + + for CVE_ENTRY in "${CVE_S02_DETAILS[@]}"; do if [ -z "$CVE_ENTRY" ]; then continue @@ -1068,6 +1092,21 @@ get_kernel_check() { fi } +get_kernel_verified() { + local S26_LOGS_ARR=("$@") + local KERNEL_CVE_VERIFIEDX=() + KERNEL_CVE_VERIFIED=() + KERNEL_CVE_VERIFIED_VERSION=() + for S26_LOG in "${S26_LOGS_ARR[@]}"; do + if [[ -f "$S26_LOG" ]]; then + print_output "[*] Collect verified kernel details of module $(basename "$S26_LOG")." + readarray -t KERNEL_CVE_VERIFIEDX < <(tail -n +2 "$S26_LOG" | sort -u || true) + fi + KERNEL_CVE_VERIFIED+=("$KERNEL_CVE_VERIFIEDX") + done + mapfile -t KERNEL_CVE_VERIFIED_VERSION < <(find "$S26_LOG" -name "cve_results_kernel_*.csv" -exec cut -d\; -f1 {} \; | grep -v "Kernel version" | sort -u) +} + get_usermode_emulator() { local S116_LOG="${1:-}" VERSIONS_EMULATOR=() diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index 659ba8c94..a682110d7 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -24,7 +24,6 @@ S26_kernel_vuln_verifier() module_title "Kernel vulnerability identification and verification" pre_module_reporter "${FUNCNAME[0]}" - KERNEL_CONFIG="NA" HOME_DIR="$(pwd)" # KERNEL_ARCH_PATH is the directory where we store all the kernels KERNEL_ARCH_PATH="$EXT_DIR""/linux_kernel_sources" @@ -32,6 +31,12 @@ S26_kernel_vuln_verifier() WAIT_PIDS_S26=() NEG_LOG=0 + if ! [[ -d "$KERNEL_ARCH_PATH" ]]; then + print_output "[-] Missing directory for kernel sources ... exit module now" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi + # we wait until the s24 module is finished and hopefully shows us a kernel version module_wait "S24_kernel_bin_identifier" @@ -47,7 +52,7 @@ S26_kernel_vuln_verifier() local KERNEL_DATA="" local KERNEL_ELF_EMBA=() - export KERNEL_CONFIG_PATH="" + export KERNEL_CONFIG_PATH="NA" export KERNEL_ELF_PATH="" for K_VERSION in "${K_VERSIONS[@]}"; do @@ -55,22 +60,27 @@ S26_kernel_vuln_verifier() print_output "[+] Identified kernel version: $ORANGE$K_VERSION$NC" mapfile -t KERNEL_ELF_EMBA < <(grep "$K_VERSION" "$S24_CSV_LOG" | cut -d\; -f4-7 | \ - grep -v "^NA" | grep -v "config extracted" | sort -u | sort -r -n -t\; -k4 || true) + grep -v "config extracted" | sort -u | sort -r -n -t\; -k4 || true) # we check for a kernel configuration for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do - if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f3)" == "NA" ]]; then + if [[ "$(echo "$KERNEL_DATA" | cut -d\; -f3)" == "/"* ]]; then + # field 3 is the kernel config file KERNEL_CONFIG_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f3) - print_output "[+] Found kernel configuration file: $ORANGE$KERNEL_CONFIG$NC" + print_output "[+] Found kernel configuration file: $ORANGE$KERNEL_CONFIG_PATH$NC" # we use the first entry with a kernel config detected - KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) - K_FOUND=1 - break + if [[ "$(echo "$KERNEL_DATA" | cut -d\; -f1)" == "/"* ]]; then + # field 1 is the matching kernel elf file - sometimes we have a config but no elf file + KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) + print_output "[+] Found kernel elf file: $ORANGE$KERNEL_ELF_PATH$NC" + K_FOUND=1 + break + fi fi done if [[ "$K_FOUND" -ne 1 ]]; then - print_output "[-] No kernel configuration file found for kernel $ORANGE$K_VERSION$NC." + print_output "[-] No kernel configuration file with matching elf file found for kernel $ORANGE$K_VERSION$NC." fi if [[ "$K_FOUND" -ne 1 ]]; then @@ -79,6 +89,7 @@ S26_kernel_vuln_verifier() if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f2)" == "NA" ]]; then KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) # we use the first entry with a kernel init detected + print_output "[+] Found kernel elf file with init entry: $ORANGE$KERNEL_ELF_PATH$NC" K_FOUND=1 break fi @@ -91,6 +102,7 @@ S26_kernel_vuln_verifier() # and no init entry -> we just use the first valid elf file if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f1)" == "NA" ]]; then KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) + print_output "[+] Found kernel elf file: $ORANGE$KERNEL_ELF_PATH$NC" # we use the first entry as final resort K_FOUND=1 break @@ -165,7 +177,7 @@ S26_kernel_vuln_verifier() rm -rf "$KERNEL_DIR" fi if ! [[ -d "$KERNEL_DIR" ]] && [[ "$(file "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz")" == *"gzip compressed data"* ]]; then - print_output "[*] Kernel extract for version $ORANGE$K_VERSION$NC" + print_output "[*] Kernel version $ORANGE$K_VERSION$NC extraction ... " tar -xzf "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" -C "$LOG_PATH_MODULE" fi @@ -180,20 +192,21 @@ S26_kernel_vuln_verifier() print_output "[*] Create CVE vulnerabilities array for kernel version $ORANGE$K_VERSION$NC ..." mapfile -t ALL_KVULNS < <(jq -rc '"\(.id):\(.cvss):\(.cvss3):\(.summary)"' "$CVE_DETAILS_PATH") - print_output "[+] Extracted $ORANGE${#ALL_KVULNS[@]}$GREEN vulnerabilities based on kernel version only" - print_output "[*] Starting in depth testing of these vulnerabilities ..." + print_ln + print_output "[+] Extracted $ORANGE${#ALL_KVULNS[@]}$GREEN vulnerabilities based on kernel version only" "" "$CVE_DETAILS_PATH" - if [[ -f "$KERNEL_CONFIG" ]] && [[ -d "$KERNEL_DIR" ]]; then - compile_kernel "$KERNEL_CONFIG" "$KERNEL_DIR" "$ORIG_K_ARCH" + if [[ -f "$KERNEL_CONFIG_PATH" ]] && [[ -d "$KERNEL_DIR" ]]; then + compile_kernel "$KERNEL_CONFIG_PATH" "$KERNEL_DIR" "$ORIG_K_ARCH" fi print_ln - print_output "[*] Identify kernel symbols ..." + sub_module_title "Identify kernel symbols ..." readelf -s "$KERNEL_ELF_PATH" | grep "FUNC\|OBJECT" | sed 's/.*FUNC//' | sed 's/.*OBJECT//' | awk '{print $4}' | \ sed 's/\[\.\.\.\]//' > "$LOG_PATH_MODULE"/symbols.txt SYMBOLS_CNT=$(wc -l "$LOG_PATH_MODULE"/symbols.txt | awk '{print $1}') print_output "[*] Extracted $SYMBOLS_CNT symbols from kernel" + if [[ -d "$LOG_DIR""/firmware" ]]; then print_output "[*] Identify kernel modules symbols ..." find "$LOG_DIR/firmware" -name "*.ko" -exec readelf -a {} \; | grep FUNC | sed 's/.*FUNC//' | \ @@ -212,21 +225,23 @@ S26_kernel_vuln_verifier() split_symbols_file + sub_module_title "Linux kernel vulnerability verification" + export CNT_PATHS_UNK=0 export CNT_PATHS_FOUND=0 export CNT_PATHS_NOT_FOUND=0 export VULN_CNT=1 export CNT_PATHS_FOUND_WRONG_ARCH=0 - local NEG_LOG=1 print_ln print_output "[*] Checking vulnerabilities for kernel version $ORANGE$K_VERSION$NC" print_ln for VULN in "${ALL_KVULNS[@]}"; do + NEG_LOG=1 K_PATHS=() K_PATHS_FILES_TMP=() - K_PATH="undocumented source path" + K_PATH="missing vulnerability path from advisory" CVE=$(echo "$VULN" | cut -d: -f1) print_output "[*] Testing vulnerability $ORANGE$VULN_CNT$NC / $ORANGE${#ALL_KVULNS[@]}$NC / $ORANGE$CVE$NC" @@ -275,7 +290,7 @@ S26_kernel_vuln_verifier() fi else # no source file in our kernel sources -> no vulns - print_output "[-] $ORANGE$CVE$NC - $ORANGE$K_PATH$NC - source file not found" + print_output "[-] $ORANGE$CVE$NC - $ORANGE$K_PATH$NC - vulnerable source file not found in kernel sources" ((CNT_PATHS_NOT_FOUND+=1)) fi max_pids_protection 20 "${WAIT_PIDS_S26[@]}" @@ -307,6 +322,7 @@ split_symbols_file() { } get_cve_kernel_data() { + sub_module_title "Version based vulnerability detection" local K_VERSION_="${1:-}" print_output "[*] Extract CVE data for kernel version $ORANGE$K_VERSION_$NC" "$PATH_CVE_SEARCH" -p "linux_kernel:""$K_VERSION_"":" -o json > "$CVE_DETAILS_PATH" @@ -322,7 +338,7 @@ extract_kernel_arch() { ORIG_K_ARCH=${ORIG_K_ARCH/MIPS64/MIPS} ORIG_K_ARCH=$(echo "$ORIG_K_ARCH" | tr -d ' ' | tr "[:upper:]" "[:lower:]") - print_output "[+] Found kernel architecture $ORANGE$ORIG_K_ARCH$NC" + print_output "[+] Identified kernel architecture $ORANGE$ORIG_K_ARCH$NC" } symbol_verifier() { @@ -367,11 +383,11 @@ compile_verifier() { local K_PATH="${3:-}" local CVSS="${4:-}" local VULN_FOUND=0 - if ! [[ -f "$LOG_PATH_MODULE"/kernel-compile.files ]]; then + if ! [[ -f "$LOG_PATH_MODULE"/kernel-compile-files.log ]]; then return fi - if grep -q "$K_PATH" "$LOG_PATH_MODULE"/kernel-compile.files ; then + if grep -q "$K_PATH" "$LOG_PATH_MODULE"/kernel-compile-files.log ; then print_output "[+] $CVE_ ($CVSS) - $K_PATH verified - compiled path" echo "$CVE_ ($CVSS) - $K_VERSION - compiled path verified - $K_PATH" >> "$LOG_PATH_MODULE""/${CVE_}_compiled_verified.txt" fi @@ -390,40 +406,51 @@ compile_kernel() { if ! [[ -d "$KERNEL_DIR" ]]; then return fi + sub_module_title "Compile Linux kernel - dry run mode" KARCH=$(echo "$KARCH" | tr '[:upper:]' '[:lower:]') - # todo handle further architecture values + # todo check and adjust further architecture details - print_bar cd "$KERNEL_DIR" || exit print_output "[*] Create default kernel config for $ORANGE$KARCH$NC architecture" - LANG=en make ARCH="$KARCH" defconfig + LANG=en make ARCH="$KARCH" defconfig | tee -a "$LOG_PATH_MODULE"/kernel-compile-defconfig.log cp "$KERNEL_CONFIG_FILE" .config + print_output "[*] Finished creating default kernel config for $ORANGE$KARCH$NC architecture" "" "$LOG_PATH_MODULE/kernel-compile-defconfig.log" print_ln print_output "[*] Update kernel config with the identified configuration of the firmware" # https://stackoverflow.com/questions/4178526/what-does-make-oldconfig-do-exactly-in-the-linux-kernel-makefile - LANG=en make ARCH="$KARCH" olddefconfig + LANG=en make ARCH="$KARCH" olddefconfig | tee -a "$LOG_PATH_MODULE"/kernel-compile-olddefconfig.log + print_output "[*] Finished updating kernel config with the identified configuration of the firmware" "" "$LOG_PATH_MODULE/kernel-compile-olddefconfig.log" print_ln - print_output "[*] Starting dry run ..." - LANG=en make ARCH="$KARCH" target=all -Bndi | tee -a "$LOG_PATH_MODULE"/kernel-compile.output + print_output "[*] Starting kernel compile dry run ..." + LANG=en make ARCH="$KARCH" target=all -Bndi | tee -a "$LOG_PATH_MODULE"/kernel-compile.log print_ln - print_output "[*] Finished dry run ..." + print_output "[*] Finished kernel compile dry run ... generated used source files" "" "$LOG_PATH_MODULE/kernel-compile.log" cd "$HOME_DIR" || exit - if [[ -f "$LOG_PATH_MODULE"/kernel-compile.output ]]; then - tr ' ' '\n' < "$LOG_PATH_MODULE"/kernel-compile.output | grep ".*\.[chS]" | tr -d '"' | tr -d ')' \ + if [[ -f "$LOG_PATH_MODULE"/kernel-compile.log ]]; then + tr ' ' '\n' < "$LOG_PATH_MODULE"/kernel-compile.log | grep ".*\.[chS]" | tr -d '"' | tr -d ')' \ | tr -d '(' | sed 's/^\.\///' | sed '/^\/.*/d' | tr -d ';' | sed 's/^>//' | sed 's/^-o//' | tr -d \' \ - | sed 's/--defines=//' | sed 's/\.$//' | sort -u > "$LOG_PATH_MODULE"/kernel-compile.files - COMPILE_SOURCE_FILES=$(wc -l "$LOG_PATH_MODULE"/kernel-compile.files | awk '{print $1}') - print_output "[+] Found $ORANGE$COMPILE_SOURCE_FILES$GREEN used source files during compilation" + | sed 's/--defines=//' | sed 's/\.$//' | sort -u > "$LOG_PATH_MODULE"/kernel-compile-files.log + COMPILE_SOURCE_FILES=$(wc -l "$LOG_PATH_MODULE"/kernel-compile-files.log | awk '{print $1}') + print_ln + print_output "[+] Found $ORANGE$COMPILE_SOURCE_FILES$GREEN used source files during compilation" "" "$LOG_PATH_MODULE/kernel-compile-files.log" else print_output "[-] Found ${RED}NO$NC used source files during compilation" fi - print_bar } final_log_kernel_vulns() { - rm -r "$LOG_PATH_MODULE"/symbols_uniq.split.* - rm -r "$LOG_PATH_MODULE"/symbols_uniq.split_gpl.* + sub_module_title "Linux kernel verification results" + + if ! [[ -v ALL_KVULNS ]]; then + print_output "[-] No module results" + return + fi + + find "$LOG_PATH_MODULE" -name "symbols_uniq.split.*" -delete || true + find "$LOG_PATH_MODULE" -name "symbols_uniq.split_gpl.*" -delete || true + + NEG_LOG=1 local VULN="" local SYM_USAGE_VERIFIED=0 @@ -437,7 +464,7 @@ final_log_kernel_vulns() { local CVE_VERIFIED_ONE_CRITICAL=() print_ln - print_output "[*] Generating final kernel report ..." + print_output "[*] Generating final kernel report ..." "no_log" echo "Kernel version;Architecture;CVE;CVSSv2;CVSSv3;Verified with symbols;Verified with compile files" >> "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv # we walk through the original version based kernel vulnerabilities and report the results @@ -459,7 +486,7 @@ final_log_kernel_vulns() { echo "$K_VERSION;$ORIG_K_ARCH;$CVE;$CVSS2;$CVSS3;$CVE_SYMBOL_FOUND;$CVE_COMPILE_FOUND" >> "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv done - SYM_USAGE_VERIFIED=$(wc -l "$LOG_PATH_MODULE"/CVE-*symbol_* | tail -1 | awk '{print $1}' 2>/dev/null) + SYM_USAGE_VERIFIED=$(wc -l "$LOG_PATH_MODULE"/CVE-*symbol_* | tail -1 | awk '{print $1}' 2>/dev/null || true) VULN_PATHS_VERIFIED_SYMBOLS=$(cat "$LOG_PATH_MODULE"/CVE-*symbol_verified.txt 2>/dev/null | grep "exported symbol" | sed 's/.*verified - //' | sed 's/.*verified (GPL) - //' | sort -u | wc -l || true) VULN_PATHS_VERIFIED_COMPILED=$(cat "$LOG_PATH_MODULE"/CVE-*compiled_verified.txt 2>/dev/null | grep "compiled path verified" | sed 's/.*verified - //' | sort -u | wc -l || true) CVE_VERIFIED_SYMBOLS=$(cat "$LOG_PATH_MODULE"/CVE-*symbol_verified.txt 2>/dev/null | grep "exported symbol" | cut -d\ -f1 | sort -u | wc -l || true) @@ -469,12 +496,10 @@ final_log_kernel_vulns() { mapfile -t CVE_VERIFIED_OVERLAP_CRITICAL < <(grep ";1;1$" "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv | grep ";9.[0-9];\|;10;" || true) mapfile -t CVE_VERIFIED_ONE_CRITICAL < <(grep ";1;\|;1$" "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv | grep ";9.[0-9];\|;10;" || true) - print_ln - print_bar print_output "[+] Identified $ORANGE${#ALL_KVULNS[@]}$GREEN unverified CVE vulnerabilities for kernel version $ORANGE$K_VERSION$NC" print_output "[*] Detected architecture $ORANGE$ORIG_K_ARCH$NC" print_output "[*] Extracted $ORANGE$SYMBOLS_CNT$NC unique symbols from kernel and modules" - if [[ "$COMPILE_SOURCE_FILES" -gt 0 ]]; then + if [[ -v COMPILE_SOURCE_FILES ]]; then print_output "[*] Extracted $ORANGE$COMPILE_SOURCE_FILES$NC used source files during compilation" fi print_output "[*] Found $ORANGE$CNT_PATHS_UNK$NC advisories with missing vulnerable path details" @@ -489,7 +514,7 @@ final_log_kernel_vulns() { if [[ "$CVE_VERIFIED_SYMBOLS" -gt 0 ]]; then print_output "[+] Verified CVEs: $ORANGE$CVE_VERIFIED_SYMBOLS$GREEN (exported symbols)" fi - if [[ "$CVE_VERIFIED_SYMBOLS" -gt 0 ]]; then + if [[ "$CVE_VERIFIED_COMPILED" -gt 0 ]]; then print_output "[+] Verified CVEs: $ORANGE$CVE_VERIFIED_COMPILED$GREEN (compiled paths)" fi if [[ "$CVE_VERIFIED_ONE" -gt 0 ]]; then @@ -507,7 +532,7 @@ final_log_kernel_vulns() { CVSS2_CRITICAL=$(echo "$CVE_VERIFIED_ONE_CRITICAL_" | cut -d\; -f4) CVSS3_CRITICAL=$(echo "$CVE_VERIFIED_ONE_CRITICAL_" | cut -d\; -f5) identify_exploits "$CVE_CRITICAL" - print_output "$(indent "$(orange "$ORANGE$CVE_CRITICAL$GREEN - $ORANGE$CVSS2_CRITICAL$GREEN / $ORANGE$CVSS3_CRITICAL$GREEN - Exploit/PoC: $ORANGE$EXPLOIT_DETECTED / $POC_DETECTED$NC")")" + print_output "$(indent "$(orange "$ORANGE$CVE_CRITICAL$GREEN\t-\t$ORANGE$CVSS2_CRITICAL$GREEN / $ORANGE$CVSS3_CRITICAL$GREEN\t-\tExploit/PoC: $ORANGE$EXPLOIT_DETECTED / $POC_DETECTED$NC")")" done fi @@ -519,7 +544,7 @@ final_log_kernel_vulns() { CVSS2_CRITICAL=$(echo "$CVE_VERIFIED_OVERLAP_CRITICAL_" | cut -d\; -f4) CVSS3_CRITICAL=$(echo "$CVE_VERIFIED_OVERLAP_CRITICAL_" | cut -d\; -f5) identify_exploits "$CVE_CRITICAL" - print_output "$(indent "$(orange "$ORANGE$CVE_CRITICAL$GREEN - $ORANGE$CVSS2_CRITICAL$GREEN / $ORANGE$CVSS3_CRITICAL$GREEN - Exploit/PoC: $ORANGE$EXPLOIT_DETECTED / $POC_DETECTED$NC")")" + print_output "$(indent "$(orange "$ORANGE$CVE_CRITICAL$GREEN\t-\t$ORANGE$CVSS2_CRITICAL$GREEN / $ORANGE$CVSS3_CRITICAL$GREEN\t-\tExploit/PoC: $ORANGE$EXPLOIT_DETECTED / $POC_DETECTED$NC")")" done fi print_bar @@ -553,13 +578,13 @@ identify_exploits() { POC_DETECTED="yes" fi fi - if [[ -f "$CONF_DIR/Snyk_PoC_results.csv" ]]; then - if grep -q -E "^$CVE_VALUE;" "$CONF_DIR/Snyk_PoC_results.csv"; then + if [[ -f "$CONFIG_DIR/Snyk_PoC_results.csv" ]]; then + if grep -q -E "^$CVE_VALUE;" "$CONFIG_DIR/Snyk_PoC_results.csv"; then POC_DETECTED="yes" fi fi - if [[ -f "$CONF_DIR/PS_PoC_results.csv" ]]; then - if grep -q -E "^$CVE_VALUE;" "$CONF_DIR/PS_PoC_results.csv"; then + if [[ -f "$CONFIG_DIR/PS_PoC_results.csv" ]]; then + if grep -q -E "^$CVE_VALUE;" "$CONFIG_DIR/PS_PoC_results.csv"; then POC_DETECTED="yes" fi fi @@ -578,7 +603,4 @@ get_csv_data_s24() { # currently we only support one kernel version # if we detect multiple kernel versions we only process the first one after sorting mapfile -t K_VERSIONS < <(cut -d\; -f2 "$S24_CSV_LOG" | tail -n +2 | grep -v "NA" | sort -u) - } - - From 6f7487a750c01bc093171aff0c2058217edcd826 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Thu, 29 Dec 2022 18:48:05 +0100 Subject: [PATCH 08/21] working state --- .../F20_vul_aggregator-post.sh | 4 + modules/F20_vul_aggregator.sh | 74 +++++++++++++------ modules/F50_base_aggregator.sh | 2 +- modules/S03_firmware_bin_base_analyzer.sh | 2 +- modules/S20_shell_check.sh | 2 +- modules/S26_kernel_vuln_verifier.sh | 29 ++++++-- 6 files changed, 82 insertions(+), 31 deletions(-) diff --git a/config/report_templates/F20_vul_aggregator-post.sh b/config/report_templates/F20_vul_aggregator-post.sh index 412c5e490..17f547a18 100755 --- a/config/report_templates/F20_vul_aggregator-post.sh +++ b/config/report_templates/F20_vul_aggregator-post.sh @@ -12,6 +12,10 @@ print_output "$(indent "${ORANGE}S$NC - PoC code found on Snyk vulnerability dat write_link "https://security.snyk.io/vuln" print_output "$(indent "${ORANGE}X$NC - Vulnerability is known as exploited")" write_link "https://www.cisa.gov/known-exploited-vulnerabilities-catalog" +if [[ -f "$LOG_DIR"/s26_kernel_vuln_verifier.txt ]]; then + print_output "$(indent "${ORANGE}V$NC - Kernel vulnerability was verified from module s26")" + write_link "s26" +fi print_ln print_ln print_output "[*] Source notes:" diff --git a/modules/F20_vul_aggregator.sh b/modules/F20_vul_aggregator.sh index 7fbb328b9..08a1b523f 100755 --- a/modules/F20_vul_aggregator.sh +++ b/modules/F20_vul_aggregator.sh @@ -42,7 +42,9 @@ F20_vul_aggregator() { MSF_SEARCH=0 TRICKEST_SEARCH=0 CVE_SEARCHSPLOIT=0 + KERNEL_VERIFIED_VULN=0 local FOUND_CVE=0 + local S26_LOGS_ARR=() CVE_AGGREGATOR_LOG="f20_vul_aggregator.txt" if [[ -f "$CVE_WHITELIST" ]] && [[ $(grep -c -E "CVE-[0-9]+-[0-9]+" "$CVE_WHITELIST") -gt 0 ]]; then @@ -57,13 +59,13 @@ F20_vul_aggregator() { local S08_LOG="$CSV_DIR"/s08_package_mgmt_extractor.csv local S09_LOG="$CSV_DIR"/s09_firmware_base_version_check.csv local S25_LOG="$CSV_DIR"/s25_kernel_check.csv - local S26_LOG="$LOG_DIR""/s26_kernel_vuln_verifier/" + local S26_LOG_DIR="$LOG_DIR""/s26_kernel_vuln_verifier/" local S116_LOG="$CSV_DIR"/s116_qemu_version_detection.csv local L15_LOG="$CSV_DIR"/l15_emulated_checks_nmap.csv local L25_LOG="$CSV_DIR"/l25_web_checks.csv local L35_LOG="$CSV_DIR"/l35_metasploit_check.csv - if [[ -d "$S26_LOG" ]]; then - mapfile -t S26_LOGS_ARR < <(find "$S26_LOG" -name "cve_results_kernel_*.csv") + if [[ -d "$S26_LOG_DIR" ]]; then + mapfile -t S26_LOGS_ARR < <(find "$S26_LOG_DIR" -name "cve_results_kernel_*.csv") fi local CVE_MINIMAL_LOG="$LOG_PATH_MODULE"/CVE_minimal.txt @@ -138,7 +140,7 @@ F20_vul_aggregator() { SNYK_SEARCH=1 fi - write_csv_log "BINARY" "VERSION" "CVE identifier" "CVSS rating" "exploit db exploit available" "metasploit module" "trickest PoC" "Routersploit" "Snyk PoC" "Packetstormsecurity PoC" "local exploit" "remote exploit" "DoS exploit" "known exploited vuln" + write_csv_log "BINARY" "VERSION" "CVE identifier" "CVSS rating" "exploit db exploit available" "metasploit module" "trickest PoC" "Routersploit" "Snyk PoC" "Packetstormsecurity PoC" "local exploit" "remote exploit" "DoS exploit" "known exploited vuln" "kernel vulnerability verified" generate_cve_details_versions "${VERSIONS_AGGREGATED[@]}" generate_cve_details_cves "${CVES_AGGREGATED[@]}" @@ -225,19 +227,19 @@ aggregate_versions() { #print_output "[+] Added modfied Kernel Version details (${ORANGE}kernel$GREEN): ""$ORANGE$VERSION$NC" done + # details from module s26 for VERSION in "${KERNEL_CVE_VERIFIED_VERSION[@]}"; do if [ -z "$VERSION" ]; then continue fi - VERSION="$(echo "$VERSION" | cut -d\; -f1) | sed 's/^/kernel:/')" - print_output "[+] Found Version details with verified vulnerability details (${ORANGE}kernel$GREEN): ""$ORANGE$VERSION$NC" + VERSION="$(echo "$VERSION" | cut -d\; -f1 | sed 's/^/kernel:/')" + print_output "[+] Found Version details (${ORANGE}kernel - with verified vulnerability details$GREEN): ""$ORANGE$VERSION$NC" # we ensure that we search for the correct kernel version by adding a : at the end of the search string VERSION=${VERSION/%/:} VERSIONS_KERNEL+=( "$VERSION" ) #print_output "[+] Added modfied Kernel Version details (${ORANGE}kernel$GREEN): ""$ORANGE$VERSION$NC" done - for CVE_ENTRY in "${CVE_S02_DETAILS[@]}"; do if [ -z "$CVE_ENTRY" ]; then continue @@ -260,8 +262,6 @@ aggregate_versions() { print_output "[+] Found CVE details (${ORANGE}verified Metasploit exploits$GREEN): ""$ORANGE$CVE_ENTRY$NC" done - - print_ln VERSIONS_AGGREGATED=("${VERSIONS_EMULATOR[@]}" "${VERSIONS_KERNEL[@]}" "${VERSIONS_STAT_CHECK[@]}" "${VERSIONS_SYS_EMULATOR[@]}" "${VERSIONS_S06_FW_DETAILS[@]}" "${VERSIONS_S08_PACKAGE_DETAILS[@]}" "${VERSIONS_SYS_EMULATOR_WEB[@]}") @@ -402,7 +402,6 @@ generate_special_log() { print_ln fi - for EXPLOIT_ in "${EXPLOITS_AVAIL[@]}"; do # remove color codes: EXPLOIT_=$(echo "$EXPLOIT_" | sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g") @@ -455,7 +454,7 @@ generate_cve_details_cves() { WAIT_PIDS_F19+=( "$!" ) max_pids_protection "$MAX_MODS" "${WAIT_PIDS_F19[@]}" else - cve_db_lookup_version "$CVE_ENTRY" + cve_db_lookup_cve "$CVE_ENTRY" fi done @@ -579,6 +578,7 @@ cve_extractor() { local DOS=0 local CVEs_OUTPUT=() local CVE_OUTPUT="" + local S26_LOG_DIR="$LOG_DIR""/s26_kernel_vuln_verifier" if ! [[ "$VERSION_orig" == "CVE-"* ]]; then if [[ "$(echo "$VERSION_orig" | sed 's/:$//' | grep -o ":" | wc -l || true)" -eq 1 ]]; then @@ -613,6 +613,7 @@ cve_extractor() { elif ! [[ "$VSOURCE" =~ .*STAT.* ]]; then VSOURCE="$VSOURCE""/STAT" fi + # Todo: elif s26 check fi fi @@ -684,6 +685,7 @@ cve_extractor() { if [[ -f "$LOG_PATH_MODULE"/"$AGG_LOG_FILE" ]]; then for CVE_OUTPUT in "${CVEs_OUTPUT[@]}"; do local CVEv2_TMP=0 + local KERNEL_VERIFIED="no" CVE_VALUE=$(echo "$CVE_OUTPUT" | cut -d: -f1) # if we find a blacklist file we check if the current CVE value is in the blacklist @@ -735,6 +737,25 @@ cve_extractor() { EDB=1 fi done + + if [[ -d "$S26_LOG_DIR" ]]; then + # check if the current CVE is a verified kernel CVE from s26 module + if grep -q ";$CVE_VALUE;.*;.*;1;1" "$S26_LOG_DIR"/cve_results_kernel_*.csv; then + print_output "[+] ${ORANGE}INFO:$GREEN Vulnerability $ORANGE$CVE_VALUE$GREEN is a verified kernel vulnerability (${ORANGE}kernel symbols and kernel configuration${GREEN})!" + ((KERNEL_VERIFIED_VULN+=1)) + KERNEL_VERIFIED="yes" + fi + if grep -q ";$CVE_VALUE;.*;.*;1;0" "$S26_LOG_DIR"/cve_results_kernel_*.csv; then + print_output "[+] ${ORANGE}INFO:$GREEN Vulnerability $ORANGE$CVE_VALUE$GREEN is a verified kernel vulnerability (${ORANGE}kernel symbols${GREEN})!" + ((KERNEL_VERIFIED_VULN+=1)) + KERNEL_VERIFIED="yes" + fi + if grep -q ";$CVE_VALUE;.*;.*;0;1" "$S26_LOG_DIR"/cve_results_kernel_*.csv; then + print_output "[+] ${ORANGE}INFO:$GREEN Vulnerability $ORANGE$CVE_VALUE$GREEN is a verified kernel vulnerability (${ORANGE}kernel configuration${GREEN})!" + ((KERNEL_VERIFIED_VULN+=1)) + KERNEL_VERIFIED="yes" + fi + fi fi if [[ "$CVE_SEARCHSPLOIT" -eq 1 || "$MSF_SEARCH" -eq 1 || "$TRICKEST_SEARCH" -eq 1 || "$SNYK_SEARCH" -eq 1 || "$PS_SEARCH" -eq 1 ]] ; then @@ -978,37 +999,39 @@ cve_extractor() { CVEv2_TMP=1 fi + if [[ "$KERNEL_VERIFIED" == "yes" ]]; then CVE_VALUE="$CVE_VALUE"" (V)"; fi + # we do not deal with output formatting the usual way -> we use printf if (( $(echo "$CVSS_VALUE > 6.9" | bc -l) )); then # put a note in the output if we have switched to CVSSv2 if [[ "$CVEv2_TMP" -eq 1 ]]; then CVSS_VALUE="$CVSS_VALUE"" (v2)"; fi if [[ "$EXPLOIT" == *MSF* || "$EXPLOIT" == *EDB\ ID* || "$EXPLOIT" == *linux-exploit-suggester* || "$EXPLOIT" == *Routersploit* || \ "$EXPLOIT" == *Github* || "$EXPLOIT" == *PSS* || "$EXPLOIT" == *Snyk* || "$KNOWN_EXPLOITED" -eq 1 ]]; then - printf "${MAGENTA}\t%-20.20s: %-12.12s: %-17.17s: %-10.10s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" + printf "${MAGENTA}\t%-20.20s: %-12.12s: %-18.18s: %-10.10s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" else - printf "${RED}\t%-20.20s: %-12.12s: %-17.17s: %-10.10s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" + printf "${RED}\t%-20.20s: %-12.12s: %-18.18s: %-10.10s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" fi ((HIGH_CVE_COUNTER+=1)) elif (( $(echo "$CVSS_VALUE > 3.9" | bc -l) )); then if [[ "$CVEv2_TMP" -eq 1 ]]; then CVSS_VALUE="$CVSS_VALUE"" (v2)"; fi if [[ "$EXPLOIT" == *MSF* || "$EXPLOIT" == *EDB\ ID* || "$EXPLOIT" == *linux-exploit-suggester* || "$EXPLOIT" == *Routersploit* || \ "$EXPLOIT" == *Github* || "$EXPLOIT" == *PSS* || "$EXPLOIT" == *Snyk* || "$KNOWN_EXPLOITED" -eq 1 ]]; then - printf "${MAGENTA}\t%-20.20s: %-12.12s: %-17.17s: %-10.10s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" + printf "${MAGENTA}\t%-20.20s: %-12.12s: %-18.18s: %-10.10s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" else - printf "${ORANGE}\t%-20.20s: %-12.12s: %-17.17s: %-10.10s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" + printf "${ORANGE}\t%-20.20s: %-12.12s: %-18.18s: %-10.10s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" fi ((MEDIUM_CVE_COUNTER+=1)) else if [[ "$CVEv2_TMP" -eq 1 ]]; then CVSS_VALUE="$CVSS_VALUE"" (v2)"; fi if [[ "$EXPLOIT" == *MSF* || "$EXPLOIT" == *EDB\ ID* || "$EXPLOIT" == *linux-exploit-suggester* || "$EXPLOIT" == *Routersploit* || \ "$EXPLOIT" == *Github* || "$EXPLOIT" == *PSS* || "$EXPLOIT" == *Snyk* || "$KNOWN_EXPLOITED" -eq 1 ]]; then - printf "${MAGENTA}\t%-20.20s: %-12.12s: %-17.17s: %-10.10s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" + printf "${MAGENTA}\t%-20.20s: %-12.12s: %-18.18s: %-10.10s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" else - printf "${GREEN}\t%-20.20s: %-12.12s: %-17.17s: %-9.9s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" + printf "${GREEN}\t%-20.20s: %-12.12s: %-18.18s: %-9.9s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" fi ((LOW_CVE_COUNTER+=1)) fi - write_csv_log "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "${#EXPLOIT_AVAIL[@]}" "${#EXPLOIT_AVAIL_MSF[@]}" "${#EXPLOIT_AVAIL_TRICKEST[@]}" "${#EXPLOIT_AVAIL_ROUTERSPLOIT[@]}/${#EXPLOIT_AVAIL_ROUTERSPLOIT1[@]}" "${EXPLOIT_AVAIL_SNYK[@]}" "${EXPLOIT_AVAIL_PACKETSTORM[@]}" "$LOCAL" "$REMOTE" "$DOS" "${#KNOWN_EXPLOITED_VULNS[@]}" + write_csv_log "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "${#EXPLOIT_AVAIL[@]}" "${#EXPLOIT_AVAIL_MSF[@]}" "${#EXPLOIT_AVAIL_TRICKEST[@]}" "${#EXPLOIT_AVAIL_ROUTERSPLOIT[@]}/${#EXPLOIT_AVAIL_ROUTERSPLOIT1[@]}" "${EXPLOIT_AVAIL_SNYK[@]}" "${EXPLOIT_AVAIL_PACKETSTORM[@]}" "$LOCAL" "$REMOTE" "$DOS" "${#KNOWN_EXPLOITED_VULNS[@]}" "$KERNEL_VERIFIED" done fi @@ -1045,6 +1068,9 @@ cve_extractor() { fi CVEs="$CVE_COUNTER_VERSION" + if [[ "$KERNEL_VERIFIED_VULN" -gt 0 ]] && [[ "$BINARY" == *"kernel"* ]]; then + CVEs="$CVEs"" ($KERNEL_VERIFIED_VULN)" + fi EXPLOITS="$EXPLOIT_COUNTER_VERSION" if [[ "$CVE_COUNTER_VERSION" -gt 0 || "$EXPLOIT_COUNTER_VERSION" -gt 0 ]]; then @@ -1052,18 +1078,18 @@ cve_extractor() { echo "BINARY;VERSION;Number of CVEs;Number of EXPLOITS" >> "$LOG_PATH_MODULE"/F20_summary.csv fi if [[ "$EXPLOIT_COUNTER_VERSION" -gt 0 || "$KNOWN_EXPLOITED" -eq 1 ]]; then - printf "[${MAGENTA}+${NC}]${MAGENTA} Found version details: \t%-20.20s: %-15.15s: CVEs: %-5.5s: Exploits: %-5.5s: Source: %-15.15s${NC}\n" "$BINARY" "$VERSION" "$CVEs" "$EXPLOITS" "$VSOURCE" >> "$LOG_PATH_MODULE"/F20_summary.txt + printf "[${MAGENTA}+${NC}]${MAGENTA} Found version details: \t%-20.20s: %-15.15s: CVEs: %-10.10s: Exploits: %-5.5s: Source: %-15.15s${NC}\n" "$BINARY" "$VERSION" "$CVEs" "$EXPLOITS" "$VSOURCE" >> "$LOG_PATH_MODULE"/F20_summary.txt echo "$BINARY;$VERSION;$CVEs;$EXPLOITS" >> "$LOG_PATH_MODULE"/F20_summary.csv else - printf "[${ORANGE}+${NC}]${ORANGE} Found version details: \t%-20.20s: %-15.15s: CVEs: %-5.5s: Exploits: %-5.5s: Source: %-15.15s${NC}\n" "$BINARY" "$VERSION" "$CVEs" "$EXPLOITS" "$VSOURCE" >> "$LOG_PATH_MODULE"/F20_summary.txt + printf "[${ORANGE}+${NC}]${ORANGE} Found version details: \t%-20.20s: %-15.15s: CVEs: %-10.10s: Exploits: %-5.5s: Source: %-15.15s${NC}\n" "$BINARY" "$VERSION" "$CVEs" "$EXPLOITS" "$VSOURCE" >> "$LOG_PATH_MODULE"/F20_summary.txt echo "$BINARY;$VERSION;$CVEs;$EXPLOITS" >> "$LOG_PATH_MODULE"/F20_summary.csv fi elif [[ "$CVEs" -eq 0 && "$EXPLOITS" -eq 0 ]]; then - printf "[${GREEN}+${NC}]${GREEN} Found version details: \t%-20.20s: %-15.15s: CVEs: %-5.5s: Exploits: %-5.5s: Source: %-15.15s${NC}\n" "$BINARY" "$VERSION" "$CVEs" "$EXPLOITS" "$VSOURCE" >> "$LOG_PATH_MODULE"/F20_summary.txt + printf "[${GREEN}+${NC}]${GREEN} Found version details: \t%-20.20s: %-15.15s: CVEs: %-10.10s: Exploits: %-5.5s: Source: %-15.15s${NC}\n" "$BINARY" "$VERSION" "$CVEs" "$EXPLOITS" "$VSOURCE" >> "$LOG_PATH_MODULE"/F20_summary.txt echo "$BINARY;$VERSION;$CVEs;$EXPLOITS" >> "$LOG_PATH_MODULE"/F20_summary.csv else # this should never happen ... - printf "[+] Found version details: \t%-20.20s: %-15.15s: CVEs: %-5.5s: Exploits: %-5.5s: Source: %-15.15s\n" "$BINARY" "$VERSION" "$CVEs" "$EXPLOITS" "$VSOURCE" >> "$LOG_PATH_MODULE"/F20_summary.txt + printf "[+] Found version details: \t%-20.20s: %-15.15s: CVEs: %-5.5s: Exploits: %-10.10s: Source: %-15.15s\n" "$BINARY" "$VERSION" "$CVEs" "$EXPLOITS" "$VSOURCE" >> "$LOG_PATH_MODULE"/F20_summary.txt echo "$BINARY;$VERSION;$CVEs;$EXPLOITS" >> "$LOG_PATH_MODULE"/F20_summary.csv fi } @@ -1095,6 +1121,8 @@ get_kernel_check() { get_kernel_verified() { local S26_LOGS_ARR=("$@") local KERNEL_CVE_VERIFIEDX=() + local S26_LOG_DIR="$LOG_DIR""/s26_kernel_vuln_verifier/" + KERNEL_CVE_VERIFIED=() KERNEL_CVE_VERIFIED_VERSION=() for S26_LOG in "${S26_LOGS_ARR[@]}"; do @@ -1104,7 +1132,7 @@ get_kernel_verified() { fi KERNEL_CVE_VERIFIED+=("$KERNEL_CVE_VERIFIEDX") done - mapfile -t KERNEL_CVE_VERIFIED_VERSION < <(find "$S26_LOG" -name "cve_results_kernel_*.csv" -exec cut -d\; -f1 {} \; | grep -v "Kernel version" | sort -u) + mapfile -t KERNEL_CVE_VERIFIED_VERSION < <(find "$S26_LOG_DIR" -name "cve_results_kernel_*.csv" -exec cut -d\; -f1 {} \; | grep -v "Kernel version" | sort -u) } get_usermode_emulator() { diff --git a/modules/F50_base_aggregator.sh b/modules/F50_base_aggregator.sh index eb97bbc0a..25d4d5f53 100755 --- a/modules/F50_base_aggregator.sh +++ b/modules/F50_base_aggregator.sh @@ -602,7 +602,7 @@ output_cve_exploits() { local BINARY_="" if [[ "${S30_VUL_COUNTER:-0}" -gt 0 || "${CVE_COUNTER:-0}" -gt 0 || "${EXPLOIT_COUNTER:-0}" -gt 0 || -v VERSIONS_AGGREGATED[@] ]]; then - if [[ "${CVE_COUNTER:-0}" -gt 0 || "${EXPLOIT_COUNTER:-0}" -gt 0 || -v VERSIONS_AGGREGATED[@] ]]; then + if [[ "${CVE_COUNTER:-0}" -gt 0 || "${EXPLOIT_COUNTER:-0}" -gt 0 || -v VERSIONS_AGGREGATED[@] ]] && [[ -f "$LOG_DIR/f20_vul_aggregator/F20_summary.txt" ]]; then print_output "[*] Identified the following software inventory, vulnerabilities and exploits:" write_link "f20#collectcveandexploitdetails" diff --git a/modules/S03_firmware_bin_base_analyzer.sh b/modules/S03_firmware_bin_base_analyzer.sh index 72066e397..10303e5fe 100755 --- a/modules/S03_firmware_bin_base_analyzer.sh +++ b/modules/S03_firmware_bin_base_analyzer.sh @@ -77,7 +77,7 @@ os_identification() { write_log "[*] Initial OS guessing:" write_csv_log "Guessed OS" "confidential rating" "verified" "Linux root filesystems found" - OS_SEARCHER=("Linux" "FreeBSD" "VxWorks\|Wind" "FreeRTOS" "ADONIS" "eCos" "uC/OS" "SIPROTEC" "QNX" "CPU\ [34][12][0-9]-[0-9]" "CP443" "Sinamics" "UEFI" "HelenOS") + OS_SEARCHER=("Linux" "FreeBSD" "VxWorks\|Wind" "FreeRTOS" "ADONIS" "eCos" "uC/OS" "SIPROTEC" "QNX" "CPU\ [34][12][0-9]-[0-9]" "CP443" "Sinamics" "UEFI" "HelenOS" "Windows\ CE") print_dot declare -A OS_COUNTER=() local WAIT_PIDS_S03_1=() diff --git a/modules/S20_shell_check.sh b/modules/S20_shell_check.sh index 22b7f583b..19e64a70c 100755 --- a/modules/S20_shell_check.sh +++ b/modules/S20_shell_check.sh @@ -104,7 +104,7 @@ S20_shell_check() sub_module_title "Summary of shell issues (semgrep)" if [[ "$S20_SEMGREP_VULNS" -gt 0 ]]; then print_output "[+] Found ""$ORANGE""$S20_SEMGREP_ISSUES"" issues""$GREEN"" (""$ORANGE""$S20_SEMGREP_VULNS"" vulnerabilites${GREEN}) in ""$ORANGE""$S20_SEMGREP_SCRIPTS""$GREEN"" shell scripts""$NC" "" "$SHELL_LOG" - else + elif [[ "$S20_SEMGREP_ISSUES" -gt 0 ]]; then print_output "[+] Found ""$ORANGE""$S20_SEMGREP_ISSUES"" issues""$GREEN"" in ""$ORANGE""$S20_SEMGREP_SCRIPTS""$GREEN"" shell scripts""$NC" "" "$SHELL_LOG" fi # highlight security findings in semgrep log: diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index a682110d7..9ac5e8b93 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -52,6 +52,7 @@ S26_kernel_vuln_verifier() local KERNEL_DATA="" local KERNEL_ELF_EMBA=() + local ALL_KVULNS=() export KERNEL_CONFIG_PATH="NA" export KERNEL_ELF_PATH="" @@ -98,7 +99,7 @@ S26_kernel_vuln_verifier() if [[ "$K_FOUND" -ne 1 ]]; then for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do - # this means we have not kernel configuration found + # this means we have no kernel configuration found # and no init entry -> we just use the first valid elf file if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f1)" == "NA" ]]; then KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) @@ -158,6 +159,7 @@ S26_kernel_vuln_verifier() extract_kernel_arch "$KERNEL_ELF_PATH" fi + # we need to wait for the downloaded linux kernel sources from the host WAIT_CNT=0 while ! [[ -f "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" ]]; do print_output "[*] Waiting for kernel sources ..." "no_log" @@ -170,6 +172,20 @@ S26_kernel_vuln_verifier() sleep 5 done + # now we have a file with the kernel sources ... we do not know if this file is complete. + # Probably it is just downloaded partly and we need to wait a bit longer + WAIT_CNT=0 + print_output "[*] Testing kernel sources ..." "no_log" + while ! gunzip -t "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" > /dev/null; do + print_output "[*] Testing kernel sources ..." "no_log" + if [[ "$WAIT_CNT" -gt 60 ]]; then + print_output "[-] No valid kernel source file available ... exit module now" + module_end_log "${FUNCNAME[0]}" "$NEG_LOG" + return + fi + sleep 5 + done + print_output "[*] Kernel sources for version $ORANGE$K_VERSION$NC available" KERNEL_DIR="$LOG_PATH_MODULE/linux-$K_VERSION" @@ -181,7 +197,7 @@ S26_kernel_vuln_verifier() tar -xzf "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" -C "$LOG_PATH_MODULE" fi - # we get a file with the results in $CVE_DETAILS_PATH + # we get a json result file with the results in $CVE_DETAILS_PATH get_cve_kernel_data "$K_VERSION" if ! [[ -f "$CVE_DETAILS_PATH" ]]; then @@ -301,11 +317,11 @@ S26_kernel_vuln_verifier() fi ((VULN_CNT+=1)) done - done - wait_for_pid "${WAIT_PIDS_S26[@]}" + wait_for_pid "${WAIT_PIDS_S26[@]}" - final_log_kernel_vulns + final_log_kernel_vulns "$K_VERSION" "${ALL_KVULNS[@]}" + done module_end_log "${FUNCNAME[0]}" "$NEG_LOG" } @@ -441,6 +457,9 @@ compile_kernel() { final_log_kernel_vulns() { sub_module_title "Linux kernel verification results" + local K_VERSION="${1:-}" + shift + local ALL_KVULNS=("$@") if ! [[ -v ALL_KVULNS ]]; then print_output "[-] No module results" From a54581e55457691acb154e04ad85f1468b64ef6d Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Thu, 29 Dec 2022 19:43:28 +0100 Subject: [PATCH 09/21] another cleanup round --- modules/F20_vul_aggregator.sh | 34 ++++++++++++++++++----------- modules/S26_kernel_vuln_verifier.sh | 8 +++++-- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/modules/F20_vul_aggregator.sh b/modules/F20_vul_aggregator.sh index 08a1b523f..f23bf35d5 100755 --- a/modules/F20_vul_aggregator.sh +++ b/modules/F20_vul_aggregator.sh @@ -613,7 +613,6 @@ cve_extractor() { elif ! [[ "$VSOURCE" =~ .*STAT.* ]]; then VSOURCE="$VSOURCE""/STAT" fi - # Todo: elif s26 check fi fi @@ -1096,7 +1095,8 @@ cve_extractor() { get_firmware_base_version_check() { local S09_LOG="${1:-}" - VERSIONS_STAT_CHECK=() + export VERSIONS_STAT_CHECK=() + if [[ -f "$S09_LOG" ]]; then print_output "[*] Collect version details of module $(basename "$S09_LOG")." # if we have already kernel information: @@ -1110,7 +1110,8 @@ get_firmware_base_version_check() { get_kernel_check() { local S25_LOG="${1:-}" - KERNEL_CVE_EXPLOITS=() + export KERNEL_CVE_EXPLOITS=() + if [[ -f "$S25_LOG" ]]; then print_output "[*] Collect version details of module $(basename "$S25_LOG")." readarray -t KERNEL_CVE_EXPLOITS < <(cut -d\; -f1-3 "$S25_LOG" | grep -v "CVE identifier" | sort -u || true) @@ -1122,22 +1123,23 @@ get_kernel_verified() { local S26_LOGS_ARR=("$@") local KERNEL_CVE_VERIFIEDX=() local S26_LOG_DIR="$LOG_DIR""/s26_kernel_vuln_verifier/" + export KERNEL_CVE_VERIFIED=() + export KERNEL_CVE_VERIFIED_VERSION=() - KERNEL_CVE_VERIFIED=() - KERNEL_CVE_VERIFIED_VERSION=() for S26_LOG in "${S26_LOGS_ARR[@]}"; do if [[ -f "$S26_LOG" ]]; then print_output "[*] Collect verified kernel details of module $(basename "$S26_LOG")." readarray -t KERNEL_CVE_VERIFIEDX < <(tail -n +2 "$S26_LOG" | sort -u || true) fi - KERNEL_CVE_VERIFIED+=("$KERNEL_CVE_VERIFIEDX") + KERNEL_CVE_VERIFIED+=("${KERNEL_CVE_VERIFIEDX[@]}") done mapfile -t KERNEL_CVE_VERIFIED_VERSION < <(find "$S26_LOG_DIR" -name "cve_results_kernel_*.csv" -exec cut -d\; -f1 {} \; | grep -v "Kernel version" | sort -u) } get_usermode_emulator() { local S116_LOG="${1:-}" - VERSIONS_EMULATOR=() + export VERSIONS_EMULATOR=() + if [[ -f "$S116_LOG" ]]; then print_output "[*] Collect version details of module $(basename "$S116_LOG")." readarray -t VERSIONS_EMULATOR < <(cut -d\; -f4 "$S116_LOG" | grep -v "csv_rule" | sort -u || true) @@ -1146,7 +1148,8 @@ get_usermode_emulator() { get_systemmode_emulator() { local L15_LOG="${1:-}" - VERSIONS_SYS_EMULATOR=() + export VERSIONS_SYS_EMULATOR=() + if [[ -f "$L15_LOG" ]]; then print_output "[*] Collect version details of module $(basename "$L15_LOG")." readarray -t VERSIONS_SYS_EMULATOR < <(cut -d\; -f4 "$L15_LOG" | grep -v "csv_rule" | sort -u || true) @@ -1155,7 +1158,8 @@ get_systemmode_emulator() { get_systemmode_webchecks() { local L25_LOG="${1:-}" - VERSIONS_SYS_EMULATOR_WEB=() + export VERSIONS_SYS_EMULATOR_WEB=() + if [[ -f "$L25_LOG" ]]; then print_output "[*] Collect version details of module $(basename "$L25_LOG")." readarray -t VERSIONS_SYS_EMULATOR_WEB < <(cut -d\; -f4 "$L25_LOG" | grep -v "csv_rule" | sort -u || true) @@ -1164,7 +1168,8 @@ get_systemmode_webchecks() { get_msf_verified() { local L35_LOG="${1:-}" - CVE_L35_DETAILS=() + export CVE_L35_DETAILS=() + if [[ -f "$L35_LOG" ]]; then print_output "[*] Collect CVE details of module $(basename "$L35_LOG")." readarray -t CVE_L35_DETAILS < <(cut -d\; -f3 "$L35_LOG" | grep -v "^CVE$" | grep -v "NA" | sort -u || true) @@ -1173,7 +1178,8 @@ get_msf_verified() { get_uefi_details() { local S02_LOG="${1:-}" - CVE_S02_DETAILS=() + export CVE_S02_DETAILS=() + if [[ -f "$S02_LOG" ]]; then print_output "[*] Collect CVE details of module $(basename "$S02_LOG")." readarray -t CVE_S02_DETAILS < <(cut -d\; -f3 "$S02_LOG" | grep -v "CVE identifier" | sort -u || true) @@ -1182,7 +1188,8 @@ get_uefi_details() { get_firmware_details() { local S06_LOG="${1:-}" - VERSIONS_S06_FW_DETAILS=() + export VERSIONS_S06_FW_DETAILS=() + if [[ -f "$S06_LOG" ]]; then print_output "[*] Collect version details of module $(basename "$S06_LOG")." readarray -t VERSIONS_S06_FW_DETAILS < <(cut -d\; -f4 "$S06_LOG" | grep -v "csv_rule" | sort -u || true) @@ -1191,7 +1198,8 @@ get_firmware_details() { get_package_details() { local S08_LOG="${1:-}" - VERSIONS_S08_PACKAGE_DETAILS=() + export VERSIONS_S08_PACKAGE_DETAILS=() + if [[ -f "$S08_LOG" ]]; then print_output "[*] Collect version details of module $(basename "$S08_LOG")." readarray -t VERSIONS_S08_PACKAGE_DETAILS < <(cut -d\; -f3,5 "$S08_LOG" | grep -v "package\;stripped version" | sort -u | tr ';' ':'|| true) diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index 9ac5e8b93..53c4ffb46 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -506,9 +506,13 @@ final_log_kernel_vulns() { done SYM_USAGE_VERIFIED=$(wc -l "$LOG_PATH_MODULE"/CVE-*symbol_* | tail -1 | awk '{print $1}' 2>/dev/null || true) + # nosemgrep VULN_PATHS_VERIFIED_SYMBOLS=$(cat "$LOG_PATH_MODULE"/CVE-*symbol_verified.txt 2>/dev/null | grep "exported symbol" | sed 's/.*verified - //' | sed 's/.*verified (GPL) - //' | sort -u | wc -l || true) + # nosemgrep VULN_PATHS_VERIFIED_COMPILED=$(cat "$LOG_PATH_MODULE"/CVE-*compiled_verified.txt 2>/dev/null | grep "compiled path verified" | sed 's/.*verified - //' | sort -u | wc -l || true) + # nosemgrep CVE_VERIFIED_SYMBOLS=$(cat "$LOG_PATH_MODULE"/CVE-*symbol_verified.txt 2>/dev/null | grep "exported symbol" | cut -d\ -f1 | sort -u | wc -l || true) + # nosemgrep CVE_VERIFIED_COMPILED=$(cat "$LOG_PATH_MODULE"/CVE-*compiled_verified.txt 2>/dev/null| grep "compiled path verified" | cut -d\ -f1 | sort -u | wc -l || true) CVE_VERIFIED_ONE=$(cut -d\; -f6-7 "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv | grep -c "1" || true) CVE_VERIFIED_OVERLAP=$(grep -c ";1;1" "$LOG_PATH_MODULE"/cve_results_kernel_"$K_VERSION".csv || true) @@ -537,7 +541,7 @@ final_log_kernel_vulns() { print_output "[+] Verified CVEs: $ORANGE$CVE_VERIFIED_COMPILED$GREEN (compiled paths)" fi if [[ "$CVE_VERIFIED_ONE" -gt 0 ]]; then - print_output "[+] Verified CVEs: $ORANGE$CVE_VERIFIED_ONE$GREEN (one mechanism success)" + print_output "[+] Verified CVEs: $ORANGE$CVE_VERIFIED_ONE$GREEN (one mechanism succeeded)" fi if [[ "$CVE_VERIFIED_OVERLAP" -gt 0 ]]; then print_output "[+] Verified CVEs: $ORANGE$CVE_VERIFIED_OVERLAP$GREEN (both mechanisms overlap)" @@ -545,7 +549,7 @@ final_log_kernel_vulns() { if [[ "${#CVE_VERIFIED_ONE_CRITICAL[@]}" -gt 0 ]]; then print_ln - print_output "[+] Verified CRITICAL CVEs: $ORANGE${#CVE_VERIFIED_ONE_CRITICAL[@]}$GREEN (one mechanisms success)" + print_output "[+] Verified CRITICAL CVEs: $ORANGE${#CVE_VERIFIED_ONE_CRITICAL[@]}$GREEN (one mechanism succeeded)" for CVE_VERIFIED_ONE_CRITICAL_ in "${CVE_VERIFIED_ONE_CRITICAL[@]}"; do CVE_CRITICAL=$(echo "$CVE_VERIFIED_ONE_CRITICAL_" | cut -d\; -f3) CVSS2_CRITICAL=$(echo "$CVE_VERIFIED_ONE_CRITICAL_" | cut -d\; -f4) From eebc165f039b5e763f136fb0aa01e42558da6f29 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Fri, 30 Dec 2022 10:38:29 +0100 Subject: [PATCH 10/21] f20 output --- modules/F20_vul_aggregator.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/F20_vul_aggregator.sh b/modules/F20_vul_aggregator.sh index f23bf35d5..d3a61009a 100755 --- a/modules/F20_vul_aggregator.sh +++ b/modules/F20_vul_aggregator.sh @@ -1026,7 +1026,7 @@ cve_extractor() { "$EXPLOIT" == *Github* || "$EXPLOIT" == *PSS* || "$EXPLOIT" == *Snyk* || "$KNOWN_EXPLOITED" -eq 1 ]]; then printf "${MAGENTA}\t%-20.20s: %-12.12s: %-18.18s: %-10.10s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" else - printf "${GREEN}\t%-20.20s: %-12.12s: %-18.18s: %-9.9s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" + printf "${GREEN}\t%-20.20s: %-12.12s: %-18.18s: %-10.10s: %-15.15s: %s${NC}\n" "$BINARY" "$VERSION" "$CVE_VALUE" "$CVSS_VALUE" "$VSOURCE" "$EXPLOIT" >> "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" fi ((LOW_CVE_COUNTER+=1)) fi From df6255dbf11d185b29a4eee5c3146f6799e9870a Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Tue, 3 Jan 2023 14:50:13 +0100 Subject: [PATCH 11/21] improvements --- emba.sh | 86 ++++++++++---------- helpers/helpers_emba_internet_access.sh | 24 +++++- modules/F20_vul_aggregator.sh | 61 +++++++++----- modules/F50_base_aggregator.sh | 6 +- modules/S24_kernel_bin_identifier.sh | 36 +++++--- modules/S25_kernel_check.sh | 3 +- modules/S26_kernel_vuln_verifier.sh | 104 ++++++++++++++---------- 7 files changed, 190 insertions(+), 130 deletions(-) diff --git a/emba.sh b/emba.sh index eb35e4891..87f271512 100755 --- a/emba.sh +++ b/emba.sh @@ -862,58 +862,56 @@ main() print_output "[*] EMBA sets up the docker environment.\\n" "no_log" - if [[ "$UPDATE" -eq 1 ]]; then - EMBA="$INVOCATION_PATH" FIRMWARE="$FIRMWARE_PATH" LOG="$LOG_DIR" docker pull embeddedanalyzer/emba + if ! docker images | grep -qE "emba[[:space:]]*latest"; then + if ! docker images | grep -qE "emba[[:space:]]*latest"; then + print_output "[*] Available docker images:" "no_log" + docker images | grep -E "emba[[:space:]]*latest" || true + print_output "[-] EMBA docker not ready!" "no_log" + exit 1 + fi fi - if ! docker images | grep -qE "emba[[:space:]]*latest"; then - print_output "[*] Available docker images:" "no_log" - docker images | grep -E "emba[[:space:]]*latest" || true - print_output "[-] EMBA docker not ready!" "no_log" - exit 1 - else - print_output "[*] EMBA initializes docker container.\\n" "no_log" + print_output "[*] EMBA initializes docker container.\\n" "no_log" - if [[ "$ONLY_DEP" -eq 0 ]]; then - # store some details that we do not have in the docker container: - echo "$FIRMWARE_PATH" >> "$TMP_DIR"/fw_name.log - echo "$LOG_DIR" >> "$TMP_DIR"/emba_log_dir.log - echo "$EMBA_COMMAND" >> "$TMP_DIR"/emba_command.log - fi + if [[ "$ONLY_DEP" -eq 0 ]]; then + # store some details that we do not have in the docker container: + echo "$FIRMWARE_PATH" >> "$TMP_DIR"/fw_name.log + echo "$LOG_DIR" >> "$TMP_DIR"/emba_log_dir.log + echo "$EMBA_COMMAND" >> "$TMP_DIR"/emba_command.log + fi - write_notification "EMBA starting docker container" + write_notification "EMBA starting docker container" - if [[ "$STRICT_MODE" -eq 1 ]]; then - set +e - fi - disable_strict_mode "$STRICT_MODE" 0 - EMBA="$INVOCATION_PATH" FIRMWARE="$FIRMWARE_PATH" LOG="$LOG_DIR" docker-compose run --rm emba -c './emba.sh -l /logs -f /firmware -i "$@"' _ "${ARGUMENTS[@]}" - D_RETURN=$? - enable_strict_mode "$STRICT_MODE" 0 - - if [[ $D_RETURN -eq 0 ]] ; then - if [[ $ONLY_DEP -eq 0 ]] ; then - print_output "[*] EMBA finished analysis in docker container.\\n" "no_log" - write_notification "EMBA finished analysis in default mode" - print_output "[*] Firmware tested: $ORANGE$FIRMWARE_PATH$NC" "no_log" - print_output "[*] Log directory: $ORANGE$LOG_DIR$NC" "no_log" - if [[ -f "$HTML_PATH"/index.html ]]; then - print_output "[*] Open the web-report with$ORANGE firefox $(abs_path "$HTML_PATH/index.html")$NC\\n" "main" - fi - cleaner 0 - else - # we do not need the log dir from dependency checker - if [[ -d "$LOG_DIR" ]]; then - rm -r "$LOG_DIR" - fi + if [[ "$STRICT_MODE" -eq 1 ]]; then + set +e + fi + disable_strict_mode "$STRICT_MODE" 0 + EMBA="$INVOCATION_PATH" FIRMWARE="$FIRMWARE_PATH" LOG="$LOG_DIR" docker-compose run --rm emba -c './emba.sh -l /logs -f /firmware -i "$@"' _ "${ARGUMENTS[@]}" + D_RETURN=$? + enable_strict_mode "$STRICT_MODE" 0 + + if [[ $D_RETURN -eq 0 ]] ; then + if [[ $ONLY_DEP -eq 0 ]] ; then + print_output "[*] EMBA finished analysis in docker container.\\n" "no_log" + write_notification "EMBA finished analysis in default mode" + print_output "[*] Firmware tested: $ORANGE$FIRMWARE_PATH$NC" "no_log" + print_output "[*] Log directory: $ORANGE$LOG_DIR$NC" "no_log" + if [[ -f "$HTML_PATH"/index.html ]]; then + print_output "[*] Open the web-report with$ORANGE firefox $(abs_path "$HTML_PATH/index.html")$NC\\n" "main" fi - exit 0 - else - print_output "[-] EMBA failed in docker mode!" "no_log" cleaner 0 - write_notification "EMBA failed analysis in default mode" - exit 1 + else + # we do not need the log dir from dependency checker + if [[ -d "$LOG_DIR" ]]; then + rm -r "$LOG_DIR" + fi fi + exit 0 + else + print_output "[-] EMBA failed in docker mode!" "no_log" + cleaner 0 + write_notification "EMBA failed analysis in default mode" + exit 1 fi fi diff --git a/helpers/helpers_emba_internet_access.sh b/helpers/helpers_emba_internet_access.sh index 8d3c980f5..b33c4c635 100755 --- a/helpers/helpers_emba_internet_access.sh +++ b/helpers/helpers_emba_internet_access.sh @@ -56,6 +56,8 @@ kernel_downloader() { K_VER_1st=$(echo "$K_VERSION" | cut -d. -f1) K_VER_2nd=$(echo "$K_VERSION" | cut -d. -f2) K_VER_3rd=$(echo "$K_VERSION" | cut -d. -f3) + + # prepare the path in the URL: if [[ "$K_VER_1st" -lt 3 ]]; then K_VER_DOWNLOAD="$K_VER_1st"".""$K_VER_2nd" elif [[ "$K_VER_1st" -eq 3 && "$K_VER_2nd" -eq 0 ]]; then @@ -63,14 +65,28 @@ kernel_downloader() { else K_VER_DOWNLOAD="$K_VER_1st"".x" fi - if [[ "$K_VER_3rd" -eq 0 ]]; then + + # prepare the download filename: + if [[ "$K_VERSION" == *".0" ]]; then # for download we need to modify versions like 3.1.0 to 3.1 - K_VERSION="$K_VER_1st"".""$K_VER_2nd" + K_VERSION=${K_VERSION%.0} fi - if ! [[ -f "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz ]]; then + # we check if the sources archive is already available and is a valid tgz file: + if ! [[ -f "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz ]] || ! gunzip -t "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" > /dev/null; then print_output "[*] Kernel download for version $ORANGE$K_VERSION$NC" "no_log" - wget https://mirrors.edge.kernel.org/pub/linux/kernel/v"$K_VER_DOWNLOAD"/linux-"$K_VERSION".tar.gz -O "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz || true + disable_strict_mode "$STRICT_MODE" 0 + wget https://mirrors.edge.kernel.org/pub/linux/kernel/v"$K_VER_DOWNLOAD"/linux-"$K_VERSION".tar.gz -O "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz + D_RETURN="$?" + enable_strict_mode "$STRICT_MODE" 0 + # if we have a non zero return something failed and we need to communicate this to the container modules (s26) which checks for + # the file "$TMP_DIR"/linux_download_failed and exits if this file is available + if [[ $D_RETURN -ne 0 ]] ; then + echo "failed" > "$TMP_DIR"/linux_download_failed + if [[ -f "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz ]]; then + rm "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz + fi + fi else print_output "[*] Kernel sources of version $ORANGE$K_VERSION$NC already available" "no_log" fi diff --git a/modules/F20_vul_aggregator.sh b/modules/F20_vul_aggregator.sh index d3a61009a..8199db009 100755 --- a/modules/F20_vul_aggregator.sh +++ b/modules/F20_vul_aggregator.sh @@ -12,7 +12,8 @@ # # Author(s): Michael Messner -# Description: Aggregates all found version numbers together from S06, S08, S09, S25, S115/S116 and L15. +# Description: Aggregates all found version numbers together from S06, S08, S09, S25, S26, +# S115/S116 and L15. # The versions are used for identification of known vulnerabilities cve-search, # finally it creates a list of exploits that are matching for the CVEs. @@ -42,17 +43,11 @@ F20_vul_aggregator() { MSF_SEARCH=0 TRICKEST_SEARCH=0 CVE_SEARCHSPLOIT=0 - KERNEL_VERIFIED_VULN=0 + local FOUND_CVE=0 local S26_LOGS_ARR=() CVE_AGGREGATOR_LOG="f20_vul_aggregator.txt" - if [[ -f "$CVE_WHITELIST" ]] && [[ $(grep -c -E "CVE-[0-9]+-[0-9]+" "$CVE_WHITELIST") -gt 0 ]]; then - print_output "[!] WARNING: CVE whitelisting activated" - fi - if [[ -f "$CVE_BLACKLIST" ]] && [[ $(grep -c -E "CVE-[0-9]+-[0-9]+" "$CVE_BLACKLIST") -gt 0 ]]; then - print_output "[!] WARNING: CVE blacklisting activated" - fi local S02_LOG="$CSV_DIR"/s02_uefi_fwhunt.csv local S06_LOG="$CSV_DIR"/s06_distribution_identification.csv @@ -64,6 +59,7 @@ F20_vul_aggregator() { local L15_LOG="$CSV_DIR"/l15_emulated_checks_nmap.csv local L25_LOG="$CSV_DIR"/l25_web_checks.csv local L35_LOG="$CSV_DIR"/l35_metasploit_check.csv + if [[ -d "$S26_LOG_DIR" ]]; then mapfile -t S26_LOGS_ARR < <(find "$S26_LOG_DIR" -name "cve_results_kernel_*.csv") fi @@ -71,10 +67,20 @@ F20_vul_aggregator() { local CVE_MINIMAL_LOG="$LOG_PATH_MODULE"/CVE_minimal.txt local EXPLOIT_OVERVIEW_LOG="$LOG_PATH_MODULE"/exploits-overview.txt + export KERNEL_CVE_VERIFIED=() + export KERNEL_CVE_VERIFIED_VERSION=() + if ! [[ -f "$KNOWN_EXP_CSV" ]]; then KNOWN_EXP_CSV="$EXT_DIR"/known_exploited_vulnerabilities.csv fi + if [[ -f "$CVE_WHITELIST" ]] && [[ $(grep -c -E "CVE-[0-9]+-[0-9]+" "$CVE_WHITELIST") -gt 0 ]]; then + print_output "[!] WARNING: CVE whitelisting activated" + fi + if [[ -f "$CVE_BLACKLIST" ]] && [[ $(grep -c -E "CVE-[0-9]+-[0-9]+" "$CVE_BLACKLIST") -gt 0 ]]; then + print_output "[!] WARNING: CVE blacklisting activated" + fi + if [[ -f $PATH_CVE_SEARCH ]]; then print_output "[*] Aggregate vulnerability details" @@ -142,8 +148,12 @@ F20_vul_aggregator() { write_csv_log "BINARY" "VERSION" "CVE identifier" "CVSS rating" "exploit db exploit available" "metasploit module" "trickest PoC" "Routersploit" "Snyk PoC" "Packetstormsecurity PoC" "local exploit" "remote exploit" "DoS exploit" "known exploited vuln" "kernel vulnerability verified" - generate_cve_details_versions "${VERSIONS_AGGREGATED[@]}" - generate_cve_details_cves "${CVES_AGGREGATED[@]}" + if [[ "${#VERSIONS_AGGREGATED[@]}" -gt 0 ]]; then + generate_cve_details_versions "${VERSIONS_AGGREGATED[@]}" + fi + if [[ "${#CVES_AGGREGATED[@]}" -gt 0 ]]; then + generate_cve_details_cves "${CVES_AGGREGATED[@]}" + fi generate_special_log "$CVE_MINIMAL_LOG" "$EXPLOIT_OVERVIEW_LOG" else @@ -337,7 +347,7 @@ generate_special_log() { local CVE_MINIMAL_LOG="${1:-}" local EXPLOIT_OVERVIEW_LOG="${2:-}" - if [[ $(grep -c "Found.*CVEs\ and" "$LOG_FILE" || true) -gt 0 ]]; then + if [[ $(grep -c "Found.*CVEs\ .*and" "$LOG_FILE" || true) -gt 0 ]]; then sub_module_title "Minimal report of exploits and CVE's." write_anchor "minimalreportofexploitsandcves" @@ -441,7 +451,7 @@ generate_special_log() { } generate_cve_details_cves() { - sub_module_title "Collect CVE and exploit details." + sub_module_title "Collect CVE and exploit details from CVEs." write_anchor "collectcveandexploitdetails_cves" local CVES_AGGREGATED=("$@") @@ -464,7 +474,7 @@ generate_cve_details_cves() { } generate_cve_details_versions() { - sub_module_title "Collect CVE and exploit details." + sub_module_title "Collect CVE and exploit details from versions." write_anchor "collectcveandexploitdetails" CVE_COUNTER=0 @@ -579,6 +589,7 @@ cve_extractor() { local CVEs_OUTPUT=() local CVE_OUTPUT="" local S26_LOG_DIR="$LOG_DIR""/s26_kernel_vuln_verifier" + local KERNEL_VERIFIED_VULN=0 if ! [[ "$VERSION_orig" == "CVE-"* ]]; then if [[ "$(echo "$VERSION_orig" | sed 's/:$//' | grep -o ":" | wc -l || true)" -eq 1 ]]; then @@ -737,19 +748,19 @@ cve_extractor() { fi done - if [[ -d "$S26_LOG_DIR" ]]; then + if [[ -f "$S26_LOG_DIR"/cve_results_kernel_"$VERSION".csv ]]; then # check if the current CVE is a verified kernel CVE from s26 module - if grep -q ";$CVE_VALUE;.*;.*;1;1" "$S26_LOG_DIR"/cve_results_kernel_*.csv; then + if grep -q ";$CVE_VALUE;.*;.*;1;1" "$S26_LOG_DIR"/cve_results_kernel_"$VERSION".csv; then print_output "[+] ${ORANGE}INFO:$GREEN Vulnerability $ORANGE$CVE_VALUE$GREEN is a verified kernel vulnerability (${ORANGE}kernel symbols and kernel configuration${GREEN})!" ((KERNEL_VERIFIED_VULN+=1)) KERNEL_VERIFIED="yes" fi - if grep -q ";$CVE_VALUE;.*;.*;1;0" "$S26_LOG_DIR"/cve_results_kernel_*.csv; then + if grep -q ";$CVE_VALUE;.*;.*;1;0" "$S26_LOG_DIR"/cve_results_kernel_"$VERSION".csv; then print_output "[+] ${ORANGE}INFO:$GREEN Vulnerability $ORANGE$CVE_VALUE$GREEN is a verified kernel vulnerability (${ORANGE}kernel symbols${GREEN})!" ((KERNEL_VERIFIED_VULN+=1)) KERNEL_VERIFIED="yes" fi - if grep -q ";$CVE_VALUE;.*;.*;0;1" "$S26_LOG_DIR"/cve_results_kernel_*.csv; then + if grep -q ";$CVE_VALUE;.*;.*;0;1" "$S26_LOG_DIR"/cve_results_kernel_"$VERSION".csv; then print_output "[+] ${ORANGE}INFO:$GREEN Vulnerability $ORANGE$CVE_VALUE$GREEN is a verified kernel vulnerability (${ORANGE}kernel configuration${GREEN})!" ((KERNEL_VERIFIED_VULN+=1)) KERNEL_VERIFIED="yes" @@ -998,6 +1009,7 @@ cve_extractor() { CVEv2_TMP=1 fi + # if this CVE is a kernel verified CVE we add a V to the CVE if [[ "$KERNEL_VERIFIED" == "yes" ]]; then CVE_VALUE="$CVE_VALUE"" (V)"; fi # we do not deal with output formatting the usual way -> we use printf @@ -1053,12 +1065,20 @@ cve_extractor() { if [[ "$EXPLOIT_COUNTER_VERSION" -gt 0 ]]; then print_ln grep -v "Statistics" "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" | tee -a "$LOG_FILE" || true - print_output "[+] Found $RED$BOLD$CVE_COUNTER_VERSION$NC$GREEN CVEs and $RED$BOLD$EXPLOIT_COUNTER_VERSION$NC$GREEN exploits (including POC's) in $ORANGE$BINARY$GREEN with version $ORANGE$VERSION$GREEN (source ${ORANGE}$VSOURCE$GREEN).${NC}" + if [[ "$KERNEL_VERIFIED_VULN" -gt 0 ]]; then + print_output "[+] Found $RED$BOLD$CVE_COUNTER_VERSION$GREEN CVEs ($RED$KERNEL_VERIFIED_VULN verified$GREEN) and $RED$BOLD$EXPLOIT_COUNTER_VERSION$GREEN exploits (including POC's) in $ORANGE$BINARY$GREEN with version $ORANGE$VERSION$GREEN (source ${ORANGE}$VSOURCE$GREEN).${NC}" + else + print_output "[+] Found $RED$BOLD$CVE_COUNTER_VERSION$GREEN CVEs and $RED$BOLD$EXPLOIT_COUNTER_VERSION$GREEN exploits (including POC's) in $ORANGE$BINARY$GREEN with version $ORANGE$VERSION$GREEN (source ${ORANGE}$VSOURCE$GREEN).${NC}" + fi print_ln elif [[ "$CVE_COUNTER_VERSION" -gt 0 ]]; then print_ln grep -v "Statistics" "$LOG_PATH_MODULE"/cve_sum/"$AGG_LOG_FILE" | tee -a "$LOG_FILE" - print_output "[+] Found $ORANGE$BOLD$CVE_COUNTER_VERSION$NC$GREEN CVEs and $ORANGE$BOLD$EXPLOIT_COUNTER_VERSION$NC$GREEN exploits (including POC's) in $ORANGE$BINARY$GREEN with version $ORANGE$VERSION$GREEN (source ${ORANGE}$VSOURCE$GREEN).${NC}" + if [[ "$KERNEL_VERIFIED_VULN" -gt 0 ]]; then + print_output "[+] Found $ORANGE$BOLD$CVE_COUNTER_VERSION$GREEN CVEs ($ORANGE$KERNEL_VERIFIED_VULN verified$GREEN) and $ORANGE$BOLD$EXPLOIT_COUNTER_VERSION$GREEN exploits (including POC's) in $ORANGE$BINARY$GREEN with version $ORANGE$VERSION$GREEN (source ${ORANGE}$VSOURCE$GREEN).${NC}" + else + print_output "[+] Found $ORANGE$BOLD$CVE_COUNTER_VERSION$GREEN CVEs and $ORANGE$BOLD$EXPLOIT_COUNTER_VERSION$GREEN exploits (including POC's) in $ORANGE$BINARY$GREEN with version $ORANGE$VERSION$GREEN (source ${ORANGE}$VSOURCE$GREEN).${NC}" + fi print_ln else print_ln @@ -1066,6 +1086,7 @@ cve_extractor() { print_ln fi + # normally we only print the number of CVEs. If we have verified CVEs in the Linux Kernel we also add this detail CVEs="$CVE_COUNTER_VERSION" if [[ "$KERNEL_VERIFIED_VULN" -gt 0 ]] && [[ "$BINARY" == *"kernel"* ]]; then CVEs="$CVEs"" ($KERNEL_VERIFIED_VULN)" @@ -1123,8 +1144,6 @@ get_kernel_verified() { local S26_LOGS_ARR=("$@") local KERNEL_CVE_VERIFIEDX=() local S26_LOG_DIR="$LOG_DIR""/s26_kernel_vuln_verifier/" - export KERNEL_CVE_VERIFIED=() - export KERNEL_CVE_VERIFIED_VERSION=() for S26_LOG in "${S26_LOGS_ARR[@]}"; do if [[ -f "$S26_LOG" ]]; then diff --git a/modules/F50_base_aggregator.sh b/modules/F50_base_aggregator.sh index 25d4d5f53..54d9773ba 100755 --- a/modules/F50_base_aggregator.sh +++ b/modules/F50_base_aggregator.sh @@ -630,9 +630,9 @@ output_cve_exploits() { echo -e "\n" >> "$LOG_FILE" print_output "[+] Identified ""$ORANGE""$CVE_COUNTER""$GREEN"" CVE entries." write_link "f20#collectcveandexploitdetails" - print_output "$(indent "$(green "Identified $RED$BOLD$HIGH_CVE_COUNTER$NC$GREEN High rated CVE entries / Exploits: $ORANGE${EXPLOIT_HIGH_COUNT:0}$NC")")" - print_output "$(indent "$(green "Identified $ORANGE$BOLD$MEDIUM_CVE_COUNTER$NC$GREEN Medium rated CVE entries / Exploits: $ORANGE${EXPLOIT_MEDIUM_COUNT:0}$NC")")" - print_output "$(indent "$(green "Identified $GREEN$BOLD$LOW_CVE_COUNTER$NC$GREEN Low rated CVE entries /Exploits: $ORANGE${EXPLOIT_LOW_COUNT:0}$NC")")" + print_output "$(indent "$(green "Identified $RED$BOLD$HIGH_CVE_COUNTER$NC$GREEN High rated CVE entries / Exploits: $ORANGE${EXPLOIT_HIGH_COUNT:-0}$NC")")" + print_output "$(indent "$(green "Identified $ORANGE$BOLD$MEDIUM_CVE_COUNTER$NC$GREEN Medium rated CVE entries / Exploits: $ORANGE${EXPLOIT_MEDIUM_COUNT:-0}$NC")")" + print_output "$(indent "$(green "Identified $GREEN$BOLD$LOW_CVE_COUNTER$NC$GREEN Low rated CVE entries /Exploits: $ORANGE${EXPLOIT_LOW_COUNT:-0}$NC")")" write_csv_log "cve_high" "$HIGH_CVE_COUNTER" "NA" write_csv_log "cve_medium" "$MEDIUM_CVE_COUNTER" "NA" write_csv_log "cve_low" "$LOW_CVE_COUNTER" "NA" diff --git a/modules/S24_kernel_bin_identifier.sh b/modules/S24_kernel_bin_identifier.sh index 6eedd1747..793a98459 100755 --- a/modules/S24_kernel_bin_identifier.sh +++ b/modules/S24_kernel_bin_identifier.sh @@ -24,6 +24,7 @@ S24_kernel_bin_identifier() local NEG_LOG=0 local FILE="" local K_VER="" + local K_INITS=() local K_INIT="" local CFG_MD5="" export KCFG_MD5=() @@ -55,15 +56,18 @@ S24_kernel_bin_identifier() print_output "$(indent "$(orange "$K_VER")")" print_ln - K_INIT=$(strings "$FILE" 2>/dev/null | grep -E "init=\/" | sort -u || true) - if [[ "$K_INIT" =~ init=\/.* ]]; then - print_output "[+] Init found in Linux kernel file $ORANGE$FILE$NC" - print_ln - print_output "$(indent "$(orange "$K_INIT")")" - print_ln - else - K_INIT="NA" - fi + # not perfect, but not too bad for now: + mapfile -t K_INITS < <(strings "$FILE" 2>/dev/null | grep -E "init=\/" | sed 's/.*rdinit/rdinit/' | sed 's/.*\ init/init/' | awk '{print $1}' | sort -u || true) + for K_INIT in "${K_INITS[@]}"; do + if [[ "$K_INIT" =~ init=\/.* ]]; then + print_output "[+] Init found in Linux kernel file $ORANGE$FILE$NC" + print_ln + print_output "$(indent "$(orange "$K_INIT")")" + print_ln + else + K_INIT="NA" + fi + done if [[ -e "$EXT_DIR"/vmlinux-to-elf/vmlinux-to-elf ]]; then print_output "[*] Testing possible Linux kernel file $ORANGE$FILE$NC with ${ORANGE}vmlinux-to-elf:$NC" @@ -95,18 +99,24 @@ S24_kernel_bin_identifier() K_VER_TMP="${K_VER/Linux version /}" demess_kv_version "$K_VER_TMP" + # -> KV_ARR if [[ "$K_ELF" == *"ELF "* ]]; then K_ELF="$(echo "$K_ELF" | cut -d: -f1)" K_SYMBOLS="$(readelf -s "$K_ELF" | grep -c "FUNC\|OBJECT" || true)" fi + # we should only get one element back, but as array for K_VER_CLEAN in "${KV_ARR[@]}"; do - # we should only get one element back, but as array - if [[ "$CFG_CNT" -gt 50 ]]; then - write_csv_log "$K_VER" "$K_VER_CLEAN" "$FILE" "$K_ELF" "$K_INIT" "$KCONFIG_EXTRACTED" "$K_SYMBOLS" + if [[ "${#K_INITS[@]}" -gt 0 ]]; then + for K_INIT in "${K_INITS[@]}"; do + if [[ "$CFG_CNT" -lt 50 ]]; then + KCONFIG_EXTRACTED="NA" + fi + write_csv_log "$K_VER" "$K_VER_CLEAN" "$FILE" "$K_ELF" "$K_INIT" "$KCONFIG_EXTRACTED" "$K_SYMBOLS" + done else - write_csv_log "$K_VER" "$K_VER_CLEAN" "$FILE" "$K_ELF" "$K_INIT" "NA" "$K_SYMBOLS" + write_csv_log "$K_VER" "$K_VER_CLEAN" "$FILE" "$K_ELF" "NA" "$KCONFIG_EXTRACTED" "$K_SYMBOLS" fi done NEG_LOG=1 diff --git a/modules/S25_kernel_check.sh b/modules/S25_kernel_check.sh index 26b573669..f3944eda4 100755 --- a/modules/S25_kernel_check.sh +++ b/modules/S25_kernel_check.sh @@ -233,7 +233,8 @@ get_kernel_vulns() demess_kv_version "${KERNEL_VERSION[@]}" IFS=" " read -r -a KV_C_ARR <<< "$(echo "${KV_ARR[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')" for VER in "${KV_C_ARR[@]}" ; do - print_output "[*] Searching for possible exploits via linux-exploit-suggester.sh for kernel version $ORANGE$VER$NC" + sub_module_title "Possible exploits via linux-exploit-suggester.sh for kernel version $ORANGE$VER$NC" + print_output "[*] Search possible exploits via linux-exploit-suggester.sh for kernel version $ORANGE$VER$NC" print_output "$(indent "https://github.com/mzet-/linux-exploit-suggester")" "$EXT_DIR""/linux-exploit-suggester.sh" --skip-more-checks -f -d -k "$VER" >> "$LOG_PATH_MODULE""/linux_exploit_suggester_kernel_$VER.txt" tee -a "$LOG_FILE" < "$LOG_PATH_MODULE""/linux_exploit_suggester_kernel_$VER.txt" diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index 53c4ffb46..71241d56e 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -86,27 +86,33 @@ S26_kernel_vuln_verifier() if [[ "$K_FOUND" -ne 1 ]]; then for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do - # now we check for init entries - if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f2)" == "NA" ]]; then - KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) - # we use the first entry with a kernel init detected - print_output "[+] Found kernel elf file with init entry: $ORANGE$KERNEL_ELF_PATH$NC" - K_FOUND=1 - break + # check for some path indicator for the elf file + if [[ "$(echo "$KERNEL_DATA" | cut -d\; -f1)" == "/"* ]]; then + # now we check for init entries + if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f2)" == "NA" ]]; then + KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) + # we use the first entry with a kernel init detected + print_output "[+] Found kernel elf file with init entry: $ORANGE$KERNEL_ELF_PATH$NC" + K_FOUND=1 + break + fi fi done fi if [[ "$K_FOUND" -ne 1 ]]; then for KERNEL_DATA in "${KERNEL_ELF_EMBA[@]}"; do - # this means we have no kernel configuration found - # and no init entry -> we just use the first valid elf file - if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f1)" == "NA" ]]; then - KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) - print_output "[+] Found kernel elf file: $ORANGE$KERNEL_ELF_PATH$NC" - # we use the first entry as final resort - K_FOUND=1 - break + # check for some path indicator for the elf file + if [[ "$(echo "$KERNEL_DATA" | cut -d\; -f1)" == "/"* ]]; then + # this means we have no kernel configuration found + # and no init entry -> we just use the first valid elf file + if ! [[ "$(echo "$KERNEL_DATA" | cut -d\; -f1)" == "NA" ]]; then + KERNEL_ELF_PATH=$(echo "$KERNEL_DATA" | cut -d\; -f1) + print_output "[+] Found kernel elf file: $ORANGE$KERNEL_ELF_PATH$NC" + # we use the first entry as final resort + K_FOUND=1 + break + fi fi done fi @@ -159,15 +165,19 @@ S26_kernel_vuln_verifier() extract_kernel_arch "$KERNEL_ELF_PATH" fi + if [[ "$K_VERSION" == *".0" ]]; then + K_VERSION_KORG=${K_VERSION%.0} + else + K_VERSION_KORG="$K_VERSION" + fi # we need to wait for the downloaded linux kernel sources from the host WAIT_CNT=0 - while ! [[ -f "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" ]]; do + while ! [[ -f "$KERNEL_ARCH_PATH/linux-$K_VERSION_KORG.tar.gz" ]]; do print_output "[*] Waiting for kernel sources ..." "no_log" ((WAIT_CNT+=1)) - if [[ "$WAIT_CNT" -gt 60 ]]; then - print_output "[-] No kernel source file available ... exit module now" - module_end_log "${FUNCNAME[0]}" "$NEG_LOG" - return + if [[ "$WAIT_CNT" -gt 60 ]] || [[ -f "$TMP_DIR"/linux_download_failed ]]; then + print_output "[-] No valid kernel source file available ... check for further kernel versions" + continue 2 fi sleep 5 done @@ -176,34 +186,33 @@ S26_kernel_vuln_verifier() # Probably it is just downloaded partly and we need to wait a bit longer WAIT_CNT=0 print_output "[*] Testing kernel sources ..." "no_log" - while ! gunzip -t "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" > /dev/null; do + while ! gunzip -t "$KERNEL_ARCH_PATH/linux-$K_VERSION_KORG.tar.gz" > /dev/null; do print_output "[*] Testing kernel sources ..." "no_log" - if [[ "$WAIT_CNT" -gt 60 ]]; then - print_output "[-] No valid kernel source file available ... exit module now" - module_end_log "${FUNCNAME[0]}" "$NEG_LOG" - return + ((WAIT_CNT+=1)) + if [[ "$WAIT_CNT" -gt 60 ]] || [[ -f "$TMP_DIR"/linux_download_failed ]]; then + print_output "[-] No valid kernel source file available ... check for further kernel versions" + continue 2 fi sleep 5 done print_output "[*] Kernel sources for version $ORANGE$K_VERSION$NC available" - KERNEL_DIR="$LOG_PATH_MODULE/linux-$K_VERSION" + KERNEL_DIR="$LOG_PATH_MODULE/linux-$K_VERSION_KORG" if [[ -d "$KERNEL_DIR" ]]; then rm -rf "$KERNEL_DIR" fi - if ! [[ -d "$KERNEL_DIR" ]] && [[ "$(file "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz")" == *"gzip compressed data"* ]]; then + if ! [[ -d "$KERNEL_DIR" ]] && [[ "$(file "$KERNEL_ARCH_PATH/linux-$K_VERSION_KORG.tar.gz")" == *"gzip compressed data"* ]]; then print_output "[*] Kernel version $ORANGE$K_VERSION$NC extraction ... " - tar -xzf "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" -C "$LOG_PATH_MODULE" + tar -xzf "$KERNEL_ARCH_PATH/linux-$K_VERSION_KORG.tar.gz" -C "$LOG_PATH_MODULE" fi # we get a json result file with the results in $CVE_DETAILS_PATH get_cve_kernel_data "$K_VERSION" if ! [[ -f "$CVE_DETAILS_PATH" ]]; then - print_output "[-] No CVE details generated ... return" - module_end_log "${FUNCNAME[0]}" "$NEG_LOG" - return + print_output "[-] No CVE details generated ... check for further kernel version" + continue fi print_output "[*] Create CVE vulnerabilities array for kernel version $ORANGE$K_VERSION$NC ..." @@ -220,8 +229,7 @@ S26_kernel_vuln_verifier() readelf -s "$KERNEL_ELF_PATH" | grep "FUNC\|OBJECT" | sed 's/.*FUNC//' | sed 's/.*OBJECT//' | awk '{print $4}' | \ sed 's/\[\.\.\.\]//' > "$LOG_PATH_MODULE"/symbols.txt SYMBOLS_CNT=$(wc -l "$LOG_PATH_MODULE"/symbols.txt | awk '{print $1}') - print_output "[*] Extracted $SYMBOLS_CNT symbols from kernel" - + print_output "[*] Extracted $ORANGE$SYMBOLS_CNT$NC symbols from kernel" if [[ -d "$LOG_DIR""/firmware" ]]; then print_output "[*] Identify kernel modules symbols ..." @@ -231,14 +239,16 @@ S26_kernel_vuln_verifier() uniq "$LOG_PATH_MODULE"/symbols.txt > "$LOG_PATH_MODULE"/symbols_uniq.txt SYMBOLS_CNT=$(wc -l "$LOG_PATH_MODULE"/symbols_uniq.txt | awk '{print $1}') - print_output "[*] Extracted $ORANGE$SYMBOLS_CNT$NC unique symbols" if [[ "$SYMBOLS_CNT" -eq 0 ]]; then - print_output "[-] No symbols found ... exit" - module_end_log "${FUNCNAME[0]}" "$NEG_LOG" - return + print_output "[-] No symbols found ... check for further kernel version" + continue fi + print_ln + print_output "[+] Extracted $ORANGE$SYMBOLS_CNT$GREEN unique symbols" + print_ln + split_symbols_file sub_module_title "Linux kernel vulnerability verification" @@ -352,6 +362,7 @@ extract_kernel_arch() { ORIG_K_ARCH=${ORIG_K_ARCH/ARM\ aarch64/arm64} # for MIPS64 -> MIPS64 to MIPS ORIG_K_ARCH=${ORIG_K_ARCH/MIPS64/MIPS} + ORIG_K_ARCH=${ORIG_K_ARCH/*PowerPC*/powerpc} ORIG_K_ARCH=$(echo "$ORIG_K_ARCH" | tr -d ' ' | tr "[:upper:]" "[:lower:]") print_output "[+] Identified kernel architecture $ORANGE$ORIG_K_ARCH$NC" @@ -417,26 +428,31 @@ compile_kernel() { export COMPILE_SOURCE_FILES=0 if ! [[ -f "$KERNEL_CONFIG_FILE" ]]; then + print_output "[-] No supported kernel config found - $ORANGE$KERNEL_CONFIG_FILE$NC" return fi if ! [[ -d "$KERNEL_DIR" ]]; then + print_output "[-] No supported kernel source directory found - $ORANGE$KERNEL_DIR$NC" return fi sub_module_title "Compile Linux kernel - dry run mode" KARCH=$(echo "$KARCH" | tr '[:upper:]' '[:lower:]') - # todo check and adjust further architecture details + if ! [[ -d "$KERNEL_DIR"/arch/"$KARCH" ]]; then + print_output "[!] No supported architecture found - $ORANGE$KARCH$NC" + return + fi cd "$KERNEL_DIR" || exit - print_output "[*] Create default kernel config for $ORANGE$KARCH$NC architecture" - LANG=en make ARCH="$KARCH" defconfig | tee -a "$LOG_PATH_MODULE"/kernel-compile-defconfig.log - cp "$KERNEL_CONFIG_FILE" .config - print_output "[*] Finished creating default kernel config for $ORANGE$KARCH$NC architecture" "" "$LOG_PATH_MODULE/kernel-compile-defconfig.log" + # print_output "[*] Create default kernel config for $ORANGE$KARCH$NC architecture" + # LANG=en make ARCH="$KARCH" defconfig | tee -a "$LOG_PATH_MODULE"/kernel-compile-defconfig.log || true + # print_output "[*] Finished creating default kernel config for $ORANGE$KARCH$NC architecture" "" "$LOG_PATH_MODULE/kernel-compile-defconfig.log" print_ln - print_output "[*] Update kernel config with the identified configuration of the firmware" + print_output "[*] Install kernel config of the identified configuration of the firmware" + cp "$KERNEL_CONFIG_FILE" .config # https://stackoverflow.com/questions/4178526/what-does-make-oldconfig-do-exactly-in-the-linux-kernel-makefile LANG=en make ARCH="$KARCH" olddefconfig | tee -a "$LOG_PATH_MODULE"/kernel-compile-olddefconfig.log - print_output "[*] Finished updating kernel config with the identified configuration of the firmware" "" "$LOG_PATH_MODULE/kernel-compile-olddefconfig.log" + print_output "[*] Finished updating kernel config with the identified firmware configuration" "" "$LOG_PATH_MODULE/kernel-compile-olddefconfig.log" print_ln print_output "[*] Starting kernel compile dry run ..." LANG=en make ARCH="$KARCH" target=all -Bndi | tee -a "$LOG_PATH_MODULE"/kernel-compile.log From 6c91896e953b3cb489bfad6aa918e0fbbeb66a5e Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Tue, 3 Jan 2023 15:14:15 +0100 Subject: [PATCH 12/21] make shellcheck happy --- helpers/helpers_emba_internet_access.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/helpers_emba_internet_access.sh b/helpers/helpers_emba_internet_access.sh index b33c4c635..a74e2fbcc 100755 --- a/helpers/helpers_emba_internet_access.sh +++ b/helpers/helpers_emba_internet_access.sh @@ -55,7 +55,7 @@ kernel_downloader() { K_VER_1st=$(echo "$K_VERSION" | cut -d. -f1) K_VER_2nd=$(echo "$K_VERSION" | cut -d. -f2) - K_VER_3rd=$(echo "$K_VERSION" | cut -d. -f3) + # K_VER_3rd=$(echo "$K_VERSION" | cut -d. -f3) # prepare the path in the URL: if [[ "$K_VER_1st" -lt 3 ]]; then From e16a67ef617914d9dbe5fa762ec58e5f7a322763 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Tue, 3 Jan 2023 15:56:51 +0100 Subject: [PATCH 13/21] make shellchecker happy --- helpers/helpers_emba_internet_access.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/helpers_emba_internet_access.sh b/helpers/helpers_emba_internet_access.sh index a74e2fbcc..6cecdd615 100755 --- a/helpers/helpers_emba_internet_access.sh +++ b/helpers/helpers_emba_internet_access.sh @@ -51,7 +51,7 @@ kernel_downloader() { local K_VER_DOWNLOAD="" local K_VER_1st="" local K_VER_2nd="" - local K_VER_3rd="" + # local K_VER_3rd="" K_VER_1st=$(echo "$K_VERSION" | cut -d. -f1) K_VER_2nd=$(echo "$K_VERSION" | cut -d. -f2) From f0aecc7c5a3d6401c4b2eccdecab5ce0d46c8904 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Tue, 3 Jan 2023 22:06:39 +0100 Subject: [PATCH 14/21] log for web report --- modules/S26_kernel_vuln_verifier.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index 71241d56e..73605d1cc 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -217,8 +217,11 @@ S26_kernel_vuln_verifier() print_output "[*] Create CVE vulnerabilities array for kernel version $ORANGE$K_VERSION$NC ..." mapfile -t ALL_KVULNS < <(jq -rc '"\(.id):\(.cvss):\(.cvss3):\(.summary)"' "$CVE_DETAILS_PATH") + # readable log file for the web report: + jq -rc '"\(.id):\(.cvss):\(.cvss3):\(.summary)"' "$CVE_DETAILS_PATH" > "$LOG_PATH_MODULE""/kernel-$K_VERSION-vulns.log" + print_ln - print_output "[+] Extracted $ORANGE${#ALL_KVULNS[@]}$GREEN vulnerabilities based on kernel version only" "" "$CVE_DETAILS_PATH" + print_output "[+] Extracted $ORANGE${#ALL_KVULNS[@]}$GREEN vulnerabilities based on kernel version only" "" "$LOG_PATH_MODULE""/kernel-$K_VERSION-vulns.log" if [[ -f "$KERNEL_CONFIG_PATH" ]] && [[ -d "$KERNEL_DIR" ]]; then compile_kernel "$KERNEL_CONFIG_PATH" "$KERNEL_DIR" "$ORIG_K_ARCH" From 15c97f4419c58db4efe0ab89c5a24ae7ffd3f04c Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Fri, 6 Jan 2023 13:10:29 +0100 Subject: [PATCH 15/21] updates --- modules/S24_kernel_bin_identifier.sh | 4 +--- modules/S26_kernel_vuln_verifier.sh | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/modules/S24_kernel_bin_identifier.sh b/modules/S24_kernel_bin_identifier.sh index 793a98459..e9b4c1203 100755 --- a/modules/S24_kernel_bin_identifier.sh +++ b/modules/S24_kernel_bin_identifier.sh @@ -29,9 +29,7 @@ S24_kernel_bin_identifier() local CFG_MD5="" export KCFG_MD5=() - if ! [[ -v FILE_ARR_LIMITED ]] || [[ "${#FILE_ARR_LIMITED[@]}" -eq 0 ]]; then - prepare_file_arr_limited "$FIRMWARE_PATH_CP" - fi + prepare_file_arr_limited "$FIRMWARE_PATH_CP" write_csv_log "Kernel version orig" "Kernel version stripped" "file" "generated elf" "identified init" "config extracted" "kernel symbols" diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index 73605d1cc..f87bd2515 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -574,7 +574,7 @@ final_log_kernel_vulns() { CVSS2_CRITICAL=$(echo "$CVE_VERIFIED_ONE_CRITICAL_" | cut -d\; -f4) CVSS3_CRITICAL=$(echo "$CVE_VERIFIED_ONE_CRITICAL_" | cut -d\; -f5) identify_exploits "$CVE_CRITICAL" - print_output "$(indent "$(orange "$ORANGE$CVE_CRITICAL$GREEN\t-\t$ORANGE$CVSS2_CRITICAL$GREEN / $ORANGE$CVSS3_CRITICAL$GREEN\t-\tExploit/PoC: $ORANGE$EXPLOIT_DETECTED / $POC_DETECTED$NC")")" + print_output "$(indent "$(orange "$ORANGE$CVE_CRITICAL$GREEN\t-\t$ORANGE$CVSS2_CRITICAL$GREEN / $ORANGE$CVSS3_CRITICAL$GREEN\t-\tExploit/PoC: $ORANGE$EXPLOIT_DETECTED $EXP / $POC_DETECTED $POC$NC")")" done fi @@ -586,7 +586,7 @@ final_log_kernel_vulns() { CVSS2_CRITICAL=$(echo "$CVE_VERIFIED_OVERLAP_CRITICAL_" | cut -d\; -f4) CVSS3_CRITICAL=$(echo "$CVE_VERIFIED_OVERLAP_CRITICAL_" | cut -d\; -f5) identify_exploits "$CVE_CRITICAL" - print_output "$(indent "$(orange "$ORANGE$CVE_CRITICAL$GREEN\t-\t$ORANGE$CVSS2_CRITICAL$GREEN / $ORANGE$CVSS3_CRITICAL$GREEN\t-\tExploit/PoC: $ORANGE$EXPLOIT_DETECTED / $POC_DETECTED$NC")")" + print_output "$(indent "$(orange "$ORANGE$CVE_CRITICAL$GREEN\t-\t$ORANGE$CVSS2_CRITICAL$GREEN / $ORANGE$CVSS3_CRITICAL$GREEN\t-\tExploit/PoC: $ORANGE$EXPLOIT_DETECTED $EXP / $POC_DETECTED $POC$NC")")" done fi print_bar @@ -594,8 +594,10 @@ final_log_kernel_vulns() { identify_exploits() { local CVE_VALUE="${1:-}" - EXPLOIT_DETECTED="no" - POC_DETECTED="no" + export EXPLOIT_DETECTED="no" + export POC_DETECTED="no" + export POC="" + export EXP="" local MSF_DB_PATH="$CONFIG_DIR/msf_cve-db.txt" local KNOWN_EXP_CSV="$EXT_DIR/known_exploited_vulnerabilities.csv" @@ -603,31 +605,37 @@ identify_exploits() { if command -v cve_searchsploit >/dev/null; then if cve_searchsploit "$CVE_VALUE" 2>/dev/null | grep -q "Exploit DB Id:"; then EXPLOIT_DETECTED="yes" + EXP="(EDB)" fi fi if [[ -f "$MSF_DB_PATH" ]]; then if grep -q -E "$CVE_VALUE"$ "$MSF_DB_PATH"; then EXPLOIT_DETECTED="yes" + EXP="$EXP(MSF)" fi fi if [[ -f "$KNOWN_EXP_CSV" ]]; then if grep -q \""${CVE_VALUE}"\", "$KNOWN_EXP_CSV"; then EXPLOIT_DETECTED="yes" + EXP="$EXP(KNOWN)" fi fi if [[ -f "$TRICKEST_DB_PATH" ]]; then if grep -q -E "$CVE_VALUE\.md" "$TRICKEST_DB_PATH"; then POC_DETECTED="yes" + POC="$POC(GH)" fi fi if [[ -f "$CONFIG_DIR/Snyk_PoC_results.csv" ]]; then if grep -q -E "^$CVE_VALUE;" "$CONFIG_DIR/Snyk_PoC_results.csv"; then POC_DETECTED="yes" + POC="$POC(SNYK)" fi fi if [[ -f "$CONFIG_DIR/PS_PoC_results.csv" ]]; then if grep -q -E "^$CVE_VALUE;" "$CONFIG_DIR/PS_PoC_results.csv"; then POC_DETECTED="yes" + POC="$POC(PS)" fi fi } From e91b192b3adc3629249869804181602e5e509fa8 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Fri, 6 Jan 2023 13:15:50 +0100 Subject: [PATCH 16/21] kernel downloader --- config/bin_version_strings.cfg | 2 +- helpers/helpers_emba_dependency_check.sh | 3 +++ helpers/helpers_emba_html_generator.sh | 28 ++++++++++--------- installer/IF20_cve_search.sh | 4 +-- installer/IP12_avm_freetz_ng_extract.sh | 15 +++++++++++ installer/helpers.sh | 3 +++ modules/F20_vul_aggregator.sh | 2 +- modules/L10_system_emulation.sh | 3 ++- modules/L15_emulated_checks_nmap.sh | 4 +-- modules/L35_metasploit_check.sh | 24 +++++++++++------ modules/P12_avm_freetz_ng_extract.sh | 34 +++++++++++++++++++++++- 11 files changed, 94 insertions(+), 28 deletions(-) diff --git a/config/bin_version_strings.cfg b/config/bin_version_strings.cfg index 95c05a6fd..af791ae44 100644 --- a/config/bin_version_strings.cfg +++ b/config/bin_version_strings.cfg @@ -548,7 +548,7 @@ quagga;;gpl;"^(ldpd|linkd)\ version\ 0\.9[\.0-9]+$";"sed -r 's/(ldpd|linkd)\ ver quagga;;gpl;"^Hello,\ this\ is\ Quagga\ \(version\ [0-9](\.[0-9]+)+?\)\.$";"sed -r 's/Hello,\ this\ is\ Quagga\ \(version\ ([0-9](\.[0-9]+)+?)\)\.$/quagga:\1/'"; #quik;;unknown;"QUIK\ version\ [0-9]\.[0-9]+";"NA"; qdiscman;;unknown;"^qdiscman\ [0-9](\.[0-9]+)+?\ release$";"sed -r 's/qdiscman\ ([0-9](\.[0-9]+)+?)$/qdiscman:\1/'"; -radlogin;;unknown;"radlogin\.c,v\ [0-9]\.[0-9]+\ [0-9]+";"sed -r 's/radlogin\.c,v\ ([0-9](\.[0-9]+)+?)$/radlogin:\1/'"; +radlogin;;unknown;"radlogin\.c,v\ [0-9]\.[0-9]+\ [0-9]+";"sed -r 's/radlogin\.c,v\ ([0-9](\.[0-9]+)+?).*/radlogin:\1/'"; radvd;strict;radvd-lic;"Version:\ [0-9]\.[0-9]+$";"sed -r 's/Version:\ ([0-9](\.[0-9]+)+?)$/radvd:\1/'"; radvd;strict;radvd-lic;"Version:\ [0-9]\.[0-9]+\.[0-9]+$";"sed -r 's/Version:\ ([0-9](\.[0-9]+)+?)$/radvd:\1/'"; radvdump;strict;radvd-lic;"Version:\ [0-9]\.[0-9]+$";"sed -r 's/Version:\ ([0-9](\.[0-9]+)+?)$/radvd:\1/'"; diff --git a/helpers/helpers_emba_dependency_check.sh b/helpers/helpers_emba_dependency_check.sh index 17f8f3448..59541a51b 100755 --- a/helpers/helpers_emba_dependency_check.sh +++ b/helpers/helpers_emba_dependency_check.sh @@ -434,6 +434,9 @@ dependency_check() # Freetz-NG check_dep_file "Freetz-NG fwmod" "$EXT_DIR""/freetz-ng/fwmod" + # AVM fitimg extraction script + check_dep_file "fitimg script" "$EXT_DIR""/fitimg-0.8/fitimg" + # EnGenius decryptor - https://gist.github.com/ryancdotorg/914f3ad05bfe0c359b79716f067eaa99 check_dep_file "EnGenius decryptor" "$EXT_DIR""/engenius-decrypt.py" diff --git a/helpers/helpers_emba_html_generator.sh b/helpers/helpers_emba_html_generator.sh index daee7836b..6bceb622b 100755 --- a/helpers/helpers_emba_html_generator.sh +++ b/helpers/helpers_emba_html_generator.sh @@ -293,19 +293,23 @@ add_link_tags() { # CVE links if ( grep -a -q -E '(CVE)' "$LINK_FILE" ) ; then - readarray -t CVE_IDS < <( grep -a -n -E -o 'CVE-[0-9]{4}-[0-9]{4,7}' "$LINK_FILE" | uniq || true) - for CVE_ID in "${CVE_IDS[@]}" ; do - CVE_ID_LINE="$(echo "$CVE_ID" | cut -d ":" -f 1)" - CVE_ID_STRING="$(echo "$CVE_ID" | cut -d ":" -f 2-)" - if [[ -n "$CVE_ID_STRING" ]] ; then - HTML_LINK="$(echo "$CVE_LINK" | sed -e "s@LINK@$CVE_ID_STRING@g")""$CVE_ID_STRING""$LINK_END" - if [[ "$LINK_FILE" == *"f20_vul_aggregator"* ]]; then - LINK_COMMAND_ARR+=( "$CVE_ID_LINE"'s@'"[[:blank:]]$CVE_ID_STRING"'@'"\t$HTML_LINK""@" ) - else - LINK_COMMAND_ARR+=( "$CVE_ID_LINE"'s@'"$CVE_ID_STRING"'@'"$HTML_LINK"'@' ) + # in l35 html report we do not link CVE - we have Metasploit links in there + echo "LINK_FILE $LINK_FILE" + if ! [[ "$LINK_FILE" == *"l35_"* ]]; then + readarray -t CVE_IDS < <( grep -a -n -E -o 'CVE-[0-9]{4}-[0-9]{4,7}' "$LINK_FILE" | uniq || true) + for CVE_ID in "${CVE_IDS[@]}" ; do + CVE_ID_LINE="$(echo "$CVE_ID" | cut -d ":" -f 1)" + CVE_ID_STRING="$(echo "$CVE_ID" | cut -d ":" -f 2-)" + if [[ -n "$CVE_ID_STRING" ]] ; then + HTML_LINK="$(echo "$CVE_LINK" | sed -e "s@LINK@$CVE_ID_STRING@g")""$CVE_ID_STRING""$LINK_END" + if [[ "$LINK_FILE" == *"f20_vul_aggregator"* ]]; then + LINK_COMMAND_ARR+=( "$CVE_ID_LINE"'s@'"[[:blank:]]$CVE_ID_STRING"'@'"\t$HTML_LINK""@" ) + else + LINK_COMMAND_ARR+=( "$CVE_ID_LINE"'s@'"$CVE_ID_STRING"'@'"$HTML_LINK"'@' ) + fi fi - fi - done + done + fi fi # CWE links diff --git a/installer/IF20_cve_search.sh b/installer/IF20_cve_search.sh index 81fae92e0..c257680be 100755 --- a/installer/IF20_cve_search.sh +++ b/installer/IF20_cve_search.sh @@ -72,11 +72,11 @@ IF20_cve_search() { pip3 install dicttoxml==1.7.4 pip3 install redis==4.2.2 pip3 install ijson==3.1.4 - pip3 install jsonpickle==2.1.0 + pip3 install jsonpickle==3.0.1 pip3 install requirements-parser==0.5.0 pip3 install ansicolors==1.1.8 pip3 install nltk==3.7 - pip3 install nested-lookup==0.2.23 + pip3 install nested-lookup==0.2.25 pip3 install dnspython==2.2.1 pip3 install Werkzeug pip3 install python-dateutil diff --git a/installer/IP12_avm_freetz_ng_extract.sh b/installer/IP12_avm_freetz_ng_extract.sh index 0180021d7..1e62f007d 100755 --- a/installer/IP12_avm_freetz_ng_extract.sh +++ b/installer/IP12_avm_freetz_ng_extract.sh @@ -57,6 +57,9 @@ IP12_avm_freetz_ng_extract() { print_tool_info "libsqlite3-dev" 1 print_tool_info "gcc-multilib" 1 print_tool_info "python-is-python3" 1 + print_file_info "fitimg" "fit image extractor" "https://boxmatrix.info/hosted/hippie2000/fitimg-0.8.tar.gz" "external/fitimg-0.8.tar.gz" + print_tool_info "libstring-crc32-perl" 1 + print_tool_info "liblzma-dev" 1 if [[ "$LIST_DEP" -eq 1 ]] || [[ $DOCKER_SETUP -eq 1 ]] ; then ANSWER=("n") @@ -119,6 +122,18 @@ IP12_avm_freetz_ng_extract() { else echo -e "${ORANGE}Found freetz directory ... Not touching it$NC" fi + + # fitimg installation + cd "$HOME_PATH" || ( echo "Could not install EMBA component fitimg" && exit 1 ) + download_file "fitimg" "https://boxmatrix.info/hosted/hippie2000/fitimg-0.8.tar.gz" "external/fitimg-0.8.tar.gz" + if [[ -f "external/fitimg-0.8.tar.gz" ]]; then + echo -e "${ORANGE}[*] Installing fitimg$NC" + tar -zxv -f "external/fitimg-0.8.tar.gz" -C external + rm "external/fitimg-0.8.tar.gz" + else + echo "Warning: fitimg download failed" + exit 1 + fi ;; esac fi diff --git a/installer/helpers.sh b/installer/helpers.sh index a38d4b119..dbc019427 100755 --- a/installer/helpers.sh +++ b/installer/helpers.sh @@ -225,6 +225,9 @@ download_file() echo -e "\\n""$ORANGE""$BOLD""Downloading ""${1:-}""$NC" if ! [[ -f "${3:-}" ]] ; then wget --no-check-certificate --output-file=./.wget.log "${2:-}" -O "${3:-}" + if [[ -f "./.wget.log" ]]; then + cat ./.wget.log + fi else echo -e "$GREEN""${1}"" is already downloaded - no further action performed.""$NC" fi diff --git a/modules/F20_vul_aggregator.sh b/modules/F20_vul_aggregator.sh index aa9862f25..3349437ec 100755 --- a/modules/F20_vul_aggregator.sh +++ b/modules/F20_vul_aggregator.sh @@ -247,7 +247,7 @@ aggregate_versions() { # we ensure that we search for the correct kernel version by adding a : at the end of the search string VERSION=${VERSION/%/:} VERSIONS_KERNEL+=( "$VERSION" ) - #print_output "[+] Added modfied Kernel Version details (${ORANGE}kernel$GREEN): ""$ORANGE$VERSION$NC" + # print_output "[+] Added modfied Kernel Version details (${ORANGE}kernel$GREEN): ""$ORANGE$VERSION$NC" done for CVE_ENTRY in "${CVE_S02_DETAILS[@]}"; do diff --git a/modules/L10_system_emulation.sh b/modules/L10_system_emulation.sh index 93f77db4d..31f1df853 100755 --- a/modules/L10_system_emulation.sh +++ b/modules/L10_system_emulation.sh @@ -230,7 +230,7 @@ create_emulation_filesystem() { # kernelInit is getting the output of the init command line we get from s24 if grep -q "init=" "$CSV_DIR"/s24_kernel_bin_identifier.csv; then print_output "[*] Found init entry for kernel - see $ORANGE$LOG_DIR/s24_kernel_bin_identifier.txt$NC:" - grep "init=/" "$CSV_DIR"/s24_kernel_bin_identifier.csv | cut -d\; -f3 | sed -e 's/.*init=/init=/' | awk '{print $1}'| sort -u | tee -a "${MNT_POINT}"/kernelInit + grep "init=/" "$CSV_DIR"/s24_kernel_bin_identifier.csv | cut -d\; -f5 | sed -e 's/.*init=/init=/' | awk '{print $1}'| sort -u | tee -a "${MNT_POINT}"/kernelInit tee -a "$LOG_FILE" < "${MNT_POINT}"/kernelInit fi else @@ -1287,6 +1287,7 @@ get_networking_details_emulation() { for PANIC in "${PANICS[@]}"; do print_output "[!] WARNING: Kernel Panic detected: $ORANGE$PANIC$NC" + print_output "$NC" done color_qemu_log "$LOG_PATH_MODULE/qemu.initial.serial.log" else diff --git a/modules/L15_emulated_checks_nmap.sh b/modules/L15_emulated_checks_nmap.sh index b5b01c8a6..3d97d7ee0 100755 --- a/modules/L15_emulated_checks_nmap.sh +++ b/modules/L15_emulated_checks_nmap.sh @@ -117,13 +117,14 @@ check_live_nmap_basic() { for SERVICE in "${NMAP_PORTS_SERVICES[@]}"; do print_output "[*] Service detected: $ORANGE$SERVICE$NC" SERVICE_NAME="$(escape_echo "$(echo "$SERVICE" | awk '{print $2}')")" + # just in case we have a / in our SERVICE_NAME + SERVICE_NAME="${SERVICE_NAME/\//\\\/}" if [[ "$SERVICE_NAME" == "unknown" ]] || [[ "$SERVICE_NAME" == "tcpwrapped" ]] || [[ -z "$SERVICE_NAME" ]]; then continue fi if [[ -f "$CSV_DIR"/s09_firmware_base_version_check.csv ]]; then # Let's check if we have already found details about this service in our other modules (S09, S115/S116) - # mapfile -t S09_L15_CHECK < <(grep "$SERVICE_NAME" "$CSV_DIR"/s09_firmware_base_version_check.csv || true) mapfile -t S09_L15_CHECK < <(awk -v IGNORECASE=1 -F\; '$2 $3 ~ /'"$SERVICE_NAME"'/' "$CSV_DIR"/s09_firmware_base_version_check.csv || true) if [[ "${#S09_L15_CHECK[@]}" -gt 0 ]]; then for S09_L15_MATCH in "${S09_L15_CHECK[@]}"; do @@ -134,7 +135,6 @@ check_live_nmap_basic() { fi if [[ -f "$CSV_DIR"/s116_qemu_version_detection.csv ]]; then - # mapfile -t S116_L15_CHECK < <(grep "$SERVICE_NAME" "$CSV_DIR"/s116_qemu_version_detection.csv || true) mapfile -t S116_L15_CHECK < <(awk -v IGNORECASE=1 -F\; '$2 $3 ~ /'"$SERVICE_NAME"'/' "$CSV_DIR"/s116_qemu_version_detection.csv || true) if [[ "${#S116_L15_CHECK[@]}" -gt 0 ]]; then for S116_L15_MATCH in "${S116_L15_CHECK[@]}"; do diff --git a/modules/L35_metasploit_check.sh b/modules/L35_metasploit_check.sh index 176b2368c..5d89fd524 100755 --- a/modules/L35_metasploit_check.sh +++ b/modules/L35_metasploit_check.sh @@ -82,7 +82,7 @@ check_live_metasploit() { if [[ -f "$LOG_PATH_MODULE"/metasploit-check-"$IP_ADDRESS_".txt ]] && [[ $(grep -a -i -c "Vulnerability identified for module" "$LOG_PATH_MODULE"/metasploit-check-"$IP_ADDRESS_".txt) -gt 0 ]]; then write_csv_log "Source" "Module" "CVE" "ARCH_END" "IP_ADDRESS" "PORTS" print_ln - print_output "[+] Possible Metasploit results for verification:" "" "$LOG_PATH_MODULE/metasploit-check-$IP_ADDRESS_.txt" + print_output "[+] Metasploit results for verification" "" "$LOG_PATH_MODULE/metasploit-check-$IP_ADDRESS_.txt" mapfile -t MSF_VULNS_VERIFIED < <(grep -a -i "Vulnerability identified for module" "$LOG_PATH_MODULE"/metasploit-check-"$IP_ADDRESS_".txt || true) for MSF_VULN in "${MSF_VULNS_VERIFIED[@]}"; do local MSF_CVE="" @@ -92,9 +92,11 @@ check_live_metasploit() { MSF_CVE="${MSF_CVE%\ }" if [[ -n "$MSF_CVE" ]]; then print_output "[+] Vulnerability verified: $ORANGE$MSF_MODULE$GREEN / $ORANGE$MSF_CVE$GREEN." + write_link "https://github.com/rapid7/metasploit-framework/tree/master/modules/exploits/${MSF_MODULE}.rb" # we write our csv entry later for every CVE entry else print_output "[+] Vulnerability verified: $ORANGE$MSF_MODULE$GREEN." + write_link "https://github.com/rapid7/metasploit-framework/tree/master/modules/exploits/${MSF_MODULE}.rb" MSF_CVE="NA" # if we have no CVE entry we can directly write our csv entry: write_csv_log "Metasploit framework" "$MSF_MODULE" "$MSF_CVE" "$ARCH_END" "$IP_ADDRESS_" "$PORTS" @@ -107,14 +109,20 @@ check_live_metasploit() { print_ln - print_output "[+] Possible Metasploit sessions for verification:" "" "$LOG_PATH_MODULE/metasploit-check-$IP_ADDRESS_.txt" - # sometimes we need two print_ln to get one in the web report?!? - print_ln - print_ln - # Print the session output from the metasploit log: - sed -n '/Active sessions/,/Stopping all jobs/p' "$LOG_PATH_MODULE"/metasploit-check-"$IP_ADDRESS_".txt | tee -a "$LOG_FILE" || true - print_ln + if grep -q "Active sessions" "$LOG_PATH_MODULE/metasploit-check-$IP_ADDRESS_.txt"; then + print_ln + print_output "[+] Possible Metasploit sessions for verification:" "" "$LOG_PATH_MODULE/metasploit-check-$IP_ADDRESS_.txt" + # sometimes we need two print_ln to get one in the web report?!? + print_ln + print_ln + # Print the session output from the metasploit log: + sed -n '/Active sessions/,/Stopping all jobs/p' "$LOG_PATH_MODULE"/metasploit-check-"$IP_ADDRESS_".txt | tee -a "$LOG_FILE" || true + print_ln + else + print_output "[-] No Metasploit session detected" + fi elif [[ -f "$LOG_PATH_MODULE"/metasploit-check-"$IP_ADDRESS_".txt ]]; then + # just for link the log file in the web reporter print_output "[-] No Metasploit results detected" "" "$LOG_PATH_MODULE/metasploit-check-$IP_ADDRESS_.txt" else print_output "[-] No Metasploit results detected" diff --git a/modules/P12_avm_freetz_ng_extract.sh b/modules/P12_avm_freetz_ng_extract.sh index 72948b9fa..3c7d4def1 100755 --- a/modules/P12_avm_freetz_ng_extract.sh +++ b/modules/P12_avm_freetz_ng_extract.sh @@ -46,6 +46,11 @@ avm_extractor() { return fi local FRITZ_DIRS=0 + local FIT_IMAGES=() + local FIT_IMAGE="" + local RAM_DISKS=() + local RAM_DISK="" + local RAM_DISK_NAME="" export FRITZ_FILE=0 export FRITZ_VERSION="" @@ -67,11 +72,38 @@ avm_extractor() { print_output "[+] Detected Fritz version: $ORANGE$FRITZ_VERSION$NC" fi + # fitimages are handled here with fitimg - binwalk and unblob are also able to handle these images + # but it is currently more beautiful doing the AVM extraction in one place here + mapfile -t FIT_IMAGES < <(find "$EXTRACTION_DIR_" -type f -name "fit-image") + + if [[ "${#FIT_IMAGES[@]}" -gt 0 ]]; then + if [[ -f "$EXT_DIR"/fitimg-0.8/fitimg ]]; then + for FIT_IMAGE in "${FIT_IMAGES[@]}"; do + print_output "[*] Detected fit-image: $ORANGE$FIT_IMAGE$NC" + print_output "[*] Extracting fit-image with fitimg to $ORANGE$EXTRACTION_DIR/fit-image-extraction$NC" + mkdir -p "$EXTRACTION_DIR/fit-image-extraction" + "$EXT_DIR"/fitimg-0.8/fitimg -x "$FIT_IMAGE" -d "$EXTRACTION_DIR"/fit-image-extraction || true + mapfile -t RAM_DISKS < <(find "$EXTRACTION_DIR_"/fit-image-extraction -type f -name "*ramdisk") + print_ln + done + else + print_output "[-] Fitimg installation not available - check your installation" + fi + fi + if [[ "${#RAM_DISKS[@]}" -gt 0 ]]; then + for RAM_DISK in "${RAM_DISKS[@]}"; do + print_output "[*] Detected AVM ramdisk: $ORANGE$RAM_DISK$NC" + RAM_DISK_NAME="$(basename "$RAM_DISK")" + binwalk_deep_extract_helper 1 "$RAM_DISK" "$EXTRACTION_DIR_"/fit-image-extraction/"$RAM_DISK_NAME"_binwalk + print_ln + done + fi + if [[ "$FRITZ_FILES" -gt 0 ]]; then print_ln print_output "[*] Extracted $ORANGE$FRITZ_FILES$NC files and $ORANGE$FRITZ_DIRS$NC directories from the firmware image." write_csv_log "Extractor module" "Original file" "extracted file/dir" "file counter" "directory counter" "further details" - write_csv_log "Freetz-NG" "$AVM_FW_PATH_" "$EXTRACTION_DIR_" "$FRITZ_FILES" "$FRITZ_DIRS" "$FRITZ_VERSION" + write_csv_log "AVM extractor" "$AVM_FW_PATH_" "$EXTRACTION_DIR_" "$FRITZ_FILES" "$FRITZ_DIRS" "$FRITZ_VERSION" export DEEP_EXTRACTOR=1 MD5_DONE_DEEP+=( "$(md5sum "$AVM_FW_PATH_" | awk '{print $1}')" ) From 2fdca668e4ee15e087794a9c4ae5ea580521d597 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Sat, 7 Jan 2023 17:15:01 +0100 Subject: [PATCH 17/21] cleanup and l10 --- check_project.sh | 11 +++++++---- emba.sh | 3 ++- helpers/helpers_emba_dependency_check.sh | 5 ++++- helpers/helpers_emba_prepare.sh | 3 ++- installer.sh | 3 ++- modules/L10_system_emulation.sh | 24 ++++++++++++++---------- modules/S24_kernel_bin_identifier.sh | 2 +- 7 files changed, 32 insertions(+), 19 deletions(-) diff --git a/check_project.sh b/check_project.sh index f776ff444..f62aff9e8 100755 --- a/check_project.sh +++ b/check_project.sh @@ -117,7 +117,8 @@ import_emba_main() { dockerchecker() { - echo -e "\\n""$ORANGE""$BOLD""EMBA docker-files check""$NC""\\n""$BOLD""=================================================================""$NC" + echo -e "\\n""$ORANGE""$BOLD""EMBA docker-files check""$NC" + echo -e "$BOLD""=================================================================""$NC" mapfile -t DOCKER_COMPS < <(find . -maxdepth 1 -iname "docker-compose*.yml") for DOCKER_COMP in "${DOCKER_COMPS[@]}"; do echo -e "\\n""$GREEN""Run docker check on $DOCKER_COMP:""$NC""\\n" @@ -132,7 +133,8 @@ dockerchecker() { } check() { - echo -e "\\n""$ORANGE""$BOLD""Embedded Linux Analyzer Shellcheck""$NC""\\n""$BOLD""=================================================================""$NC" + echo -e "\\n""$ORANGE""$BOLD""Embedded Linux Analyzer Shellcheck""$NC" + echo -e "$BOLD""=================================================================""$NC" echo -e "\\n""$GREEN""Load all files for check:""$NC""\\n" @@ -280,8 +282,9 @@ check dockerchecker summary -if [[ "${#MODULES_TO_CHECK_ARR_TAB[@]}" -gt 0 ]] || [[ "${#MODULES_TO_CHECK_ARR[@]}" -gt 0 ]] || [[ "${#MODULES_TO_CHECK_ARR[@]}" -gt 0 ]] || \ - [[ "${#MODULES_TO_CHECK_ARR_SEMGREP[@]}" -gt 0 ]] || [[ "${#MODULES_TO_CHECK_ARR_DOCKER[@]}" -gt 0 ]] || [[ "${#MODULES_TO_CHECK_ARR_PERM[@]}" -gt 0 ]] || \ +if [[ "${#MODULES_TO_CHECK_ARR_TAB[@]}" -gt 0 ]] || [[ "${#MODULES_TO_CHECK_ARR[@]}" -gt 0 ]] || \ + [[ "${#MODULES_TO_CHECK_ARR[@]}" -gt 0 ]] || [[ "${#MODULES_TO_CHECK_ARR_SEMGREP[@]}" -gt 0 ]] || \ + [[ "${#MODULES_TO_CHECK_ARR_DOCKER[@]}" -gt 0 ]] || [[ "${#MODULES_TO_CHECK_ARR_PERM[@]}" -gt 0 ]] || \ [[ "${#MODULES_TO_CHECK_ARR_COMMENT[@]}" -gt 0 ]]; then exit 1 fi diff --git a/emba.sh b/emba.sh index 96c2cc5dd..406983e3d 100755 --- a/emba.sh +++ b/emba.sh @@ -415,7 +415,8 @@ main() welcome # Print EMBA welcome message if [[ $# -eq 0 ]]; then - print_output "\\n""$ORANGE""In order to be able to use EMBA, you have to specify at least a firmware (-f).\\nIf you don't set a log directory (-l), then ./logs will be used.""$NC" "no_log" + print_output "\\n""$ORANGE""In order to be able to use EMBA, you have to specify at least a firmware (-f)." "no_log" + print_output "If you don't set a log directory (-l), then ./logs will be used.""$NC" "no_log" print_help exit 1 fi diff --git a/helpers/helpers_emba_dependency_check.sh b/helpers/helpers_emba_dependency_check.sh index e3f16733e..50851f7aa 100755 --- a/helpers/helpers_emba_dependency_check.sh +++ b/helpers/helpers_emba_dependency_check.sh @@ -339,7 +339,10 @@ dependency_check() # Check system tools ####################################################################################### if [[ $USE_DOCKER -eq 0 ]] ; then - SYSTEM_TOOLS=("awk" "basename" "bash" "cat" "chmod" "chown" "cp" "cut" "date" "dirname" "dpkg-deb" "echo" "eval" "find" "grep" "head" "kill" "ln" "ls" "md5sum" "mkdir" "mknod" "modinfo" "mv" "netstat" "openssl" "printf" "pwd" "readelf" "realpath" "rm" "rmdir" "sed" "seq" "sleep" "sort" "strings" "tee" "touch" "tr" "uniq" "unzip" "wc") + SYSTEM_TOOLS=("awk" "basename" "bash" "cat" "chmod" "chown" "cp" "cut" "date" "dirname" \ + "dpkg-deb" "echo" "eval" "find" "grep" "head" "kill" "ln" "ls" "md5sum" "mkdir" "mknod" \ + "modinfo" "mv" "netstat" "openssl" "printf" "pwd" "readelf" "realpath" "rm" "rmdir" "sed" \ + "seq" "sleep" "sort" "strings" "tee" "touch" "tr" "uniq" "unzip" "wc") for TOOL in "${SYSTEM_TOOLS[@]}" ; do check_dep_tool "$TOOL" diff --git a/helpers/helpers_emba_prepare.sh b/helpers/helpers_emba_prepare.sh index fc2a1b76e..a08242ffe 100755 --- a/helpers/helpers_emba_prepare.sh +++ b/helpers/helpers_emba_prepare.sh @@ -31,7 +31,8 @@ log_folder() local POSSIBLE_RESTART=0 # used for testing the checksums of the firmware with stored checksum echo -e "\\n[${RED}!${NC}] ${ORANGE}Warning${NC}\\n" - echo -e " There are files in the specified directory: ""$LOG_DIR""\\n You can now delete the content here or start the tool again and specify a different directory." + echo -e " There are files in the specified directory: ""$LOG_DIR" + echo -e " You can now delete the content here or start the tool again and specify a different directory." if [[ -f "$LOG_DIR"/"$MAIN_LOG_FILE" ]]; then if grep -q "Test ended" "$LOG_DIR"/"$MAIN_LOG_FILE"; then diff --git a/installer.sh b/installer.sh index 4c8c7cbc7..44ee310bf 100755 --- a/installer.sh +++ b/installer.sh @@ -65,7 +65,8 @@ export NC="\033[0m" # no color ## Attribute definition export BOLD="\033[1m" -echo -e "\\n""$ORANGE""$BOLD""EMBA - Embedded Linux Analyzer Installer""$NC""\\n""$BOLD""=================================================================""$NC" +echo -e "\\n""$ORANGE""$BOLD""EMBA - Embedded Linux Analyzer Installer""$NC" +echo -e "$BOLD""=================================================================""$NC" # import all the installation modules mapfile -t INSTALLERS < <(find "$INSTALLER_DIR" -iname "*.sh" 2> /dev/null) diff --git a/modules/L10_system_emulation.sh b/modules/L10_system_emulation.sh index f745dedea..07d6c5d12 100755 --- a/modules/L10_system_emulation.sh +++ b/modules/L10_system_emulation.sh @@ -250,7 +250,7 @@ create_emulation_filesystem() { cp "$MODULE_SUB_PATH/inferService.sh" "${MNT_POINT}" || true FIRMAE_BOOT=${FIRMAE_BOOT} FIRMAE_ETC=${FIRMAE_ETC} timeout --preserve-status --signal SIGINT 120 chroot "${MNT_POINT}" /bash-static /inferService.sh | tee -a "$LOG_FILE" - if [ -e "${MNT_POINT}/kernelInit" ]; then + if [[ -e "${MNT_POINT}/kernelInit" ]]; then print_output "[*] Backup ${MNT_POINT}/kernelInit:" tee -a "$LOG_FILE" < "${MNT_POINT}/kernelInit" rm "${MNT_POINT}/kernelInit" @@ -470,7 +470,7 @@ main_emulation() { ############################################################################################### # if we were running into issues with the network identification we poke with rdinit vs init: - # lets check if we have found a startup procedure (preInit script) from FirmAE/EMBA - if not we try it with the other init + # lets check if we have found a startup procedure (preInit script) from EMBA - if not we try it with the other init F_STARTUP=$(grep -a -c "EMBA preInit script starting" "$LOG_PATH_MODULE"/qemu.initial.serial.log || true) F_STARTUP=$(( "$F_STARTUP" + "$(grep -a -c "Network configuration - ACTION" "$LOG_PATH_MODULE"/qemu.initial.serial.log || true)" )) else @@ -480,8 +480,7 @@ main_emulation() { # print_output "[*] Found $ORANGE$F_STARTUP$NC EMBA startup entries." print_ln - - if [[ "${#PANICS[@]}" -gt 0 ]] || [[ "$F_STARTUP" -eq 0 ]]; then + if [[ "${#PANICS[@]}" -gt 0 ]] || [[ "$F_STARTUP" -eq 0 ]] || [[ "$DETECTED_IP" -eq 0 ]]; then # if we are running into a kernel panic during the network detection we are going to check if the # panic is caused from an init failure. If so, we are trying the other init kernel command (init vs rdinit) if [[ "${PANICS[*]}" == *"Kernel panic - not syncing: Attempted to kill init!"* || "${PANICS[*]}" == *"Kernel panic - not syncing: No working init found."* ]]; then @@ -508,10 +507,8 @@ main_emulation() { fi print_ln - # #IPS_INT_VLAN is always at least 1 for the default configuration - # elif [[ "$F_STARTUP" -eq 0 && "$NETWORK_MODE" == "None" && "${#IPS_INT_VLAN[@]}" -lt 2 ]] || \ - # [[ "$F_STARTUP" -eq 0 && "$NETWORK_MODE" == "default" && "${#IPS_INT_VLAN[@]}" -lt 2 ]]; then - elif [[ "$F_STARTUP" -eq 0 && "$NETWORK_MODE" == "None" ]] || [[ "$F_STARTUP" -eq 0 && "$NETWORK_MODE" == "default" ]]; then + elif [[ "$F_STARTUP" -eq 0 && "$NETWORK_MODE" == "None" ]] || \ + [[ "$F_STARTUP" -eq 0 && "$NETWORK_MODE" == "default" ]] || [[ "$DETECTED_IP" -eq 0 ]]; then mv "$LOG_PATH_MODULE"/qemu.initial.serial.log "$LOG_PATH_MODULE"/qemu.initial.serial_"$IMAGE_NAME"_"$INIT_FNAME"_base_init.log if [[ "$KINIT" == "rdinit="* ]]; then print_output "[*] Warning: Unknown EMBA startup found via rdinit - testing init" @@ -531,7 +528,8 @@ main_emulation() { F_STARTUP=$(grep -a -c "EMBA preInit script starting" "$LOG_PATH_MODULE"/qemu.initial.serial.log || true) F_STARTUP=$(( "$F_STARTUP" + "$(grep -a -c "Network configuration - ACTION" "$LOG_PATH_MODULE"/qemu.initial.serial.log || true)" )) # IPS_INT_VLAN is always at least 1 for the default configuration - if [[ "${#PANICS[@]}" -gt 0 ]] || [[ "$F_STARTUP" -eq 0 && "${#IPS_INT_VLAN[@]}" -lt 2 ]]; then + if [[ "${#PANICS[@]}" -gt 0 ]] || [[ "$F_STARTUP" -eq 0 && "${#IPS_INT_VLAN[@]}" -lt 2 ]] || \ + [[ "$DETECTED_IP" -eq 0 ]]; then if [[ "$KINIT" == "rdinit="* ]]; then print_output "[*] Warning: switching back to init" # strip rd from rdinit @@ -671,7 +669,11 @@ main_emulation() { # if we have a working emulation we stop here if [[ "$TCP" == "ok" ]]; then - break 2 + if [[ $(grep -c "tcp.*open" "$LOG_PATH_MODULE"/"$NMAP_LOG" 2>/dev/null) -gt 1 ]]; then + # we only exit if we have more than 1 open port detected. + # Otherwise we try to find a better solution + break 2 + fi fi else print_output "[-] No working emulation - removing emulation archive." @@ -1024,6 +1026,7 @@ get_networking_details_emulation() { sub_module_title "Network identification - $IMAGE_NAME" PANICS=() + export DETECTED_IP=0 if [[ -f "$LOG_PATH_MODULE"/qemu.initial.serial.log ]]; then ETH_INT="NONE" @@ -1129,6 +1132,7 @@ get_networking_details_emulation() { if [[ "$IP_ADDRESS_" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] && ! [[ "$IP_ADDRESS_" == "127."* ]] && ! [[ "$IP_ADDRESS_" == "0.0.0.0" ]]; then print_ln print_output "[*] Identified IP address: $ORANGE$IP_ADDRESS_$NC" + DETECTED_IP=1 # get the network device NETWORK_DEVICE="$(echo "$INTERFACE_CAND" | grep device | cut -d: -f2- | sed "s/^.*\]:\ //" | awk '{print $1}' | cut -d: -f2 | tr -dc '[:print:]' || true)" # INTERFACE_CAND -> __inet_insert_ifa[PID: 139 (ifconfig)]: device:br0 ifa:0xc0a80001 diff --git a/modules/S24_kernel_bin_identifier.sh b/modules/S24_kernel_bin_identifier.sh index d285c128f..56012a1c5 100755 --- a/modules/S24_kernel_bin_identifier.sh +++ b/modules/S24_kernel_bin_identifier.sh @@ -55,7 +55,7 @@ S24_kernel_bin_identifier() print_ln # not perfect, but not too bad for now: - mapfile -t K_INITS < <(strings "$FILE" 2>/dev/null | grep -E "init=\/" | sed 's/.*rdinit/rdinit/' | sed 's/.*\ init/init/' | awk '{print $1}' | sort -u || true) + mapfile -t K_INITS < <(strings "$FILE" 2>/dev/null | grep -E "init=\/" | sed 's/.*rdinit/rdinit/' | sed 's/.*\ init/init/' | awk '{print $1}' | tr -d '"' | sort -u || true) for K_INIT in "${K_INITS[@]}"; do if [[ "$K_INIT" =~ init=\/.* ]]; then print_output "[+] Init found in Linux kernel file $ORANGE$FILE$NC" From dae5c51e1c77626958e663a4c4e3b107962abeca Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Sun, 8 Jan 2023 18:47:25 +0100 Subject: [PATCH 18/21] f50 --- helpers/helpers_emba_html_generator.sh | 1 - helpers/helpers_emba_internet_access.sh | 54 +++++++++++++++++++------ modules/F50_base_aggregator.sh | 20 +++++++++ modules/S26_kernel_vuln_verifier.sh | 4 +- 4 files changed, 65 insertions(+), 14 deletions(-) diff --git a/helpers/helpers_emba_html_generator.sh b/helpers/helpers_emba_html_generator.sh index 5fd16ec08..c36cd3734 100755 --- a/helpers/helpers_emba_html_generator.sh +++ b/helpers/helpers_emba_html_generator.sh @@ -294,7 +294,6 @@ add_link_tags() { # CVE links if ( grep -a -q -E '(CVE)' "$LINK_FILE" ) ; then # in l35 html report we do not link CVE - we have Metasploit links in there - echo "LINK_FILE $LINK_FILE" if ! [[ "$LINK_FILE" == *"l35_"* ]]; then readarray -t CVE_IDS < <( grep -a -n -E -o 'CVE-[0-9]{4}-[0-9]{4,7}' "$LINK_FILE" | uniq || true) for CVE_ID in "${CVE_IDS[@]}" ; do diff --git a/helpers/helpers_emba_internet_access.sh b/helpers/helpers_emba_internet_access.sh index 6cecdd615..04b24bd86 100755 --- a/helpers/helpers_emba_internet_access.sh +++ b/helpers/helpers_emba_internet_access.sh @@ -16,8 +16,8 @@ # kernel downloader waits for s24 results. If we were able to identify a kernel version, -# a kernel config or at least kernel symbols we can use these information to verify the -# vulnerabilities +# a kernel config or at least kernel symbols we can use these details to verify the +# vulnerabilities which we identified based on the kernel version kernel_downloader() { LOG_FILE_KERNEL="$CSV_DIR"/s24_kernel_bin_identifier.csv KERNEL_ARCH_PATH="$EXT_DIR"/linux_kernel_sources/ @@ -38,7 +38,9 @@ kernel_downloader() { # now we should have a csv log with a kernel version: if ! [[ -f "$LOG_FILE_KERNEL" ]]; then - print_output "[-] No Kernel version identified ..." "no_log" + local OUTPUTTER="[-] No Kernel version identified ..." + print_output "$OUTPUTTER" "no_log" + write_log "$OUTPUTTER" "$LOG_DIR/kernel_downloader.log" return fi local K_VERSIONS=() @@ -47,7 +49,9 @@ kernel_downloader() { mapfile -t K_VERSIONS < <(cut -d\; -f2 "$LOG_FILE_KERNEL" | tail -n +2 | sort -u | grep -E "[0-9]+(\.[0-9]+)+?" || true) for K_VERSION in "${K_VERSIONS[@]}"; do - print_output "[*] Checking download of kernel version $ORANGE$K_VERSION$NC" "no_log" + local OUTPUTTER="[*] Checking download of kernel version $ORANGE$K_VERSION$NC" + print_output "$OUTPUTTER" "no_log" + write_log "$OUTPUTTER" "$LOG_DIR/kernel_downloader.log" local K_VER_DOWNLOAD="" local K_VER_1st="" local K_VER_2nd="" @@ -74,32 +78,58 @@ kernel_downloader() { # we check if the sources archive is already available and is a valid tgz file: if ! [[ -f "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz ]] || ! gunzip -t "$KERNEL_ARCH_PATH/linux-$K_VERSION.tar.gz" > /dev/null; then - print_output "[*] Kernel download for version $ORANGE$K_VERSION$NC" "no_log" + local OUTPUTTER="[*] Kernel download for version $ORANGE$K_VERSION$NC" + print_output "$OUTPUTTER" "no_log" + write_log "$OUTPUTTER" "$LOG_DIR/kernel_downloader.log" + + if ! [[ -d "$TMP_DIR" ]]; then + mkdir "$TMP_DIR" + fi + disable_strict_mode "$STRICT_MODE" 0 - wget https://mirrors.edge.kernel.org/pub/linux/kernel/v"$K_VER_DOWNLOAD"/linux-"$K_VERSION".tar.gz -O "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz + wget --output-file="$TMP_DIR"/wget.log https://mirrors.edge.kernel.org/pub/linux/kernel/v"$K_VER_DOWNLOAD"/linux-"$K_VERSION".tar.gz -O "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz 2>&1 D_RETURN="$?" enable_strict_mode "$STRICT_MODE" 0 - # if we have a non zero return something failed and we need to communicate this to the container modules (s26) which checks for - # the file "$TMP_DIR"/linux_download_failed and exits if this file is available + + if [[ -f "$TMP_DIR"/wget.log ]]; then + print_ln + tee -a "$LOG_DIR/kernel_downloader.log" < "$TMP_DIR"/wget.log + rm "$TMP_DIR"/wget.log + fi + # if we have a non zero return something failed and we need to communicate this to the container modules (s26) which + # checks for the file "$TMP_DIR"/linux_download_failed. If this file is available it stops waiting for the kernel + # sources if [[ $D_RETURN -ne 0 ]] ; then + local OUTPUTTER="[-] Kernel download for version $ORANGE$K_VERSION$NC failed" + print_output "$OUTPUTTER" "no_log" + write_log "$OUTPUTTER" "$LOG_DIR/kernel_downloader.log" + echo "failed" > "$TMP_DIR"/linux_download_failed if [[ -f "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz ]]; then rm "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz fi fi else - print_output "[*] Kernel sources of version $ORANGE$K_VERSION$NC already available" "no_log" + local OUTPUTTER="[*] Kernel sources of version $ORANGE$K_VERSION$NC already available" + print_output "$OUTPUTTER" "no_log" + write_log "$OUTPUTTER" "$LOG_DIR/kernel_downloader.log" fi if ! [[ -f "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz ]]; then - print_output "[-] Kernel sources not available ..." "no_log" + local OUTPUTTER="[-] Kernel sources not available ..." + print_output "$OUTPUTTER" "no_log" + write_log "$OUTPUTTER" "$LOG_DIR/kernel_downloader.log" continue fi if ! file "$KERNEL_ARCH_PATH"/linux-"$K_VERSION".tar.gz | grep -q "gzip compressed data"; then - print_output "[-] Kernel sources not available ..." "no_log" + local OUTPUTTER="[-] Kernel sources not available ..." + print_output "$OUTPUTTER" "no_log" + write_log "$OUTPUTTER" "$LOG_DIR/kernel_downloader.log" continue fi - print_output "[*] Kernel source for version $ORANGE$K_VERSION$NC stored in $ORANGE$KERNEL_ARCH_PATH$NC" "no_log" + local OUTPUTTER="[*] Kernel source for version $ORANGE$K_VERSION$NC stored in $ORANGE$KERNEL_ARCH_PATH$NC" + print_output "$OUTPUTTER" "no_log" + write_log "$OUTPUTTER" "$LOG_DIR/kernel_downloader.log" done } diff --git a/modules/F50_base_aggregator.sh b/modules/F50_base_aggregator.sh index e5bc0d073..371185ad1 100755 --- a/modules/F50_base_aggregator.sh +++ b/modules/F50_base_aggregator.sh @@ -36,6 +36,7 @@ F50_base_aggregator() { S22_LOG="s22_php_check.txt" S24_LOG="s24_kernel_bin_identifier.txt" S25_LOG="s25_kernel_check.txt" + S26_LOG="s26_kernel_vuln_verifier.txt" S30_LOG="s30_version_vulnerability_check.txt" S40_LOG="s40_weak_perm_check.txt" S45_LOG="s45_pass_file_check.txt" @@ -251,6 +252,19 @@ output_details() { DATA=1 fi + if [[ "${K_CVE_VERIFIED_SYMBOLS:-0}" -gt 0 ]] || [[ "${K_CVE_VERIFIED_COMPILED:-0}" -gt 0 ]]; then + if [[ "${K_CVE_VERIFIED_SYMBOLS:-0}" -gt 0 ]]; then + print_output "$(indent "$(green "Verified $ORANGE${K_CVE_VERIFIED_SYMBOLS:-0}$GREEN kernel vulnerabilities (kernel symbols).")")" + write_link "s26" + fi + if [[ "${K_CVE_VERIFIED_COMPILED:-0}" -gt 0 ]]; then + print_output "$(indent "$(green "Verified $ORANGE${K_CVE_VERIFIED_COMPILED:-0}$GREEN kernel vulnerabilities (${ORANGE}kernel compilation$GREEN).")")" + write_link "s26" + fi + DATA=1 + write_csv_log "kernel_verified" "${K_CVE_VERIFIED_SYMBOLS:-0}" "${K_CVE_VERIFIED_COMPILED:-0}" + fi + if [[ $DATA -eq 1 ]]; then print_bar fi @@ -734,6 +748,8 @@ get_data() { export CVE_SEARCH=1 export FWHUNTER_CNT=0 export MSF_VERIFIED=0 + export K_CVE_VERIFIED_SYMBOLS=0 + export K_CVE_VERIFIED_COMPILED=0 if [[ -f "$LOG_DIR"/"$P02_LOG" ]]; then ENTROPY=$(grep -a "Entropy" "$LOG_DIR"/"$P02_LOG" | cut -d\; -f2 | cut -d= -f2 | sed 's/^\ //' || true) @@ -796,6 +812,10 @@ get_data() { MOD_DATA_COUNTER=$(grep -a "\[\*\]\ Statistics1:" "$LOG_DIR"/"$S25_LOG" | cut -d: -f2 || true) KMOD_BAD=$(grep -a "\[\*\]\ Statistics1:" "$LOG_DIR"/"$S25_LOG" | cut -d: -f3 || true) fi + if [[ -f "$LOG_DIR"/"$S26_LOG" ]]; then + K_CVE_VERIFIED_SYMBOLS=$(grep -a "\[\*\]\ Statistics:" "$LOG_DIR"/"$S26_LOG" | cut -d: -f4 || true) + K_CVE_VERIFIED_COMPILED=$(grep -a "\[\*\]\ Statistics:" "$LOG_DIR"/"$S26_LOG" | cut -d: -f5 || true) + fi if [[ -f "$LOG_DIR"/"$S30_LOG" ]]; then S30_VUL_COUNTER=$(grep -a "\[\*\]\ Statistics:" "$LOG_DIR"/"$S30_LOG" | cut -d: -f2 || true) fi diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index f87bd2515..9ba8f8ac5 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -186,7 +186,7 @@ S26_kernel_vuln_verifier() # Probably it is just downloaded partly and we need to wait a bit longer WAIT_CNT=0 print_output "[*] Testing kernel sources ..." "no_log" - while ! gunzip -t "$KERNEL_ARCH_PATH/linux-$K_VERSION_KORG.tar.gz" > /dev/null; do + while ! gunzip -t "$KERNEL_ARCH_PATH/linux-$K_VERSION_KORG.tar.gz" 2> /dev/null; do print_output "[*] Testing kernel sources ..." "no_log" ((WAIT_CNT+=1)) if [[ "$WAIT_CNT" -gt 60 ]] || [[ -f "$TMP_DIR"/linux_download_failed ]]; then @@ -197,6 +197,7 @@ S26_kernel_vuln_verifier() done print_output "[*] Kernel sources for version $ORANGE$K_VERSION$NC available" + write_link "$LOG_DIR/kernel_downloader.log" KERNEL_DIR="$LOG_PATH_MODULE/linux-$K_VERSION_KORG" if [[ -d "$KERNEL_DIR" ]]; then @@ -589,6 +590,7 @@ final_log_kernel_vulns() { print_output "$(indent "$(orange "$ORANGE$CVE_CRITICAL$GREEN\t-\t$ORANGE$CVSS2_CRITICAL$GREEN / $ORANGE$CVSS3_CRITICAL$GREEN\t-\tExploit/PoC: $ORANGE$EXPLOIT_DETECTED $EXP / $POC_DETECTED $POC$NC")")" done fi + write_log "[*] Statistics:$K_VERSION:${#ALL_KVULNS[@]}:$CVE_VERIFIED_SYMBOLS:$CVE_VERIFIED_COMPILED" print_bar } From be2f402bb9137090743ae937472315c89ebb4600 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Sun, 8 Jan 2023 22:09:18 +0100 Subject: [PATCH 19/21] template, true --- .../S26_kernel_vuln_verifier-post.sh | 15 +++++++++++++++ modules/S115_usermode_emulator.sh | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100755 config/report_templates/S26_kernel_vuln_verifier-post.sh diff --git a/config/report_templates/S26_kernel_vuln_verifier-post.sh b/config/report_templates/S26_kernel_vuln_verifier-post.sh new file mode 100755 index 000000000..b40b78e7f --- /dev/null +++ b/config/report_templates/S26_kernel_vuln_verifier-post.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +print_output "[*] Exploitability notes:" +print_output "$(indent "${ORANGE}EDB$NC - Exploit code found in the Exploit database")" +write_link "https://exploit-db.com" +print_output "$(indent "${ORANGE}MSF$NC - Exploit code found in the Metasploit framework")" +write_link "https://github.com/rapid7/metasploit-framework" +print_output "$(indent "${ORANGE}GH$NC - PoC code found on Github (via trickest)")" +write_link "https://github.com/trickest/cve" +print_output "$(indent "${ORANGE}PS$NC - PoC code found on Packetstormsecurity")" +write_link "https://packetstormsecurity.com/files/tags/exploit/" +print_output "$(indent "${ORANGE}SNYK$NC - PoC code found on Snyk vulnerability database")" +write_link "https://security.snyk.io/vuln" +print_output "$(indent "${ORANGE}EXP$NC - Vulnerability is known as exploited")" +write_link "https://www.cisa.gov/known-exploited-vulnerabilities-catalog" diff --git a/modules/S115_usermode_emulator.sh b/modules/S115_usermode_emulator.sh index 4e709f448..2b363fe61 100755 --- a/modules/S115_usermode_emulator.sh +++ b/modules/S115_usermode_emulator.sh @@ -750,7 +750,7 @@ s115_cleanup() { fi mapfile -t LOG_FILES < <(find "$LOG_PATH_MODULE""/" -xdev -type f -name "qemu_tmp*" 2>/dev/null) - ILLEGAL_INSTRUCTIONS=$(grep -l "Illegal instruction" "$LOG_PATH_MODULE""/"qemu_tmp* | wc -l) + ILLEGAL_INSTRUCTIONS=$(grep -l "Illegal instruction" "$LOG_PATH_MODULE""/"qemu_tmp* | wc -l || true) print_output "[*] Found $ORANGE$ILLEGAL_INSTRUCTIONS$NC binaries not emulated - Illegal instructions" if [[ "${#LOG_FILES[@]}" -gt 0 ]] ; then sub_module_title "Reporting phase" From 3a8410f2d21f03dcbd300d7127aac2994e760ef8 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Tue, 10 Jan 2023 09:02:58 +0100 Subject: [PATCH 20/21] cleanup --- modules/F50_base_aggregator.sh | 4 ++-- modules/S26_kernel_vuln_verifier.sh | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/F50_base_aggregator.sh b/modules/F50_base_aggregator.sh index 371185ad1..9c35ff588 100755 --- a/modules/F50_base_aggregator.sh +++ b/modules/F50_base_aggregator.sh @@ -254,11 +254,11 @@ output_details() { if [[ "${K_CVE_VERIFIED_SYMBOLS:-0}" -gt 0 ]] || [[ "${K_CVE_VERIFIED_COMPILED:-0}" -gt 0 ]]; then if [[ "${K_CVE_VERIFIED_SYMBOLS:-0}" -gt 0 ]]; then - print_output "$(indent "$(green "Verified $ORANGE${K_CVE_VERIFIED_SYMBOLS:-0}$GREEN kernel vulnerabilities (kernel symbols).")")" + print_output "[+] Verified $ORANGE${K_CVE_VERIFIED_SYMBOLS:-0}$GREEN kernel vulnerabilities (${ORANGE}kernel symbols$GREEN)." write_link "s26" fi if [[ "${K_CVE_VERIFIED_COMPILED:-0}" -gt 0 ]]; then - print_output "$(indent "$(green "Verified $ORANGE${K_CVE_VERIFIED_COMPILED:-0}$GREEN kernel vulnerabilities (${ORANGE}kernel compilation$GREEN).")")" + print_output "[+] Verified $ORANGE${K_CVE_VERIFIED_COMPILED:-0}$GREEN kernel vulnerabilities (${ORANGE}kernel compilation$GREEN)." write_link "s26" fi DATA=1 diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index 9ba8f8ac5..2f7669387 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -591,7 +591,6 @@ final_log_kernel_vulns() { done fi write_log "[*] Statistics:$K_VERSION:${#ALL_KVULNS[@]}:$CVE_VERIFIED_SYMBOLS:$CVE_VERIFIED_COMPILED" - print_bar } identify_exploits() { From 80271a4b3633385d1891510ca23c8dcc7de6cf17 Mon Sep 17 00:00:00 2001 From: m-1-k-3 Date: Wed, 11 Jan 2023 09:07:54 +0100 Subject: [PATCH 21/21] L10 config finder --- helpers/helpers_emba_internet_access.sh | 2 +- modules/L10_system_emulation/inferService.sh | 4 ++-- modules/S26_kernel_vuln_verifier.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/helpers/helpers_emba_internet_access.sh b/helpers/helpers_emba_internet_access.sh index 04b24bd86..5dc9f3f45 100755 --- a/helpers/helpers_emba_internet_access.sh +++ b/helpers/helpers_emba_internet_access.sh @@ -2,7 +2,7 @@ # EMBA - EMBEDDED LINUX ANALYZER # -# Copyright 2020-2022 Siemens Energy AG +# Copyright 2020-2023 Siemens Energy 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. diff --git a/modules/L10_system_emulation/inferService.sh b/modules/L10_system_emulation/inferService.sh index a33a13333..0a3cc0d45 100755 --- a/modules/L10_system_emulation/inferService.sh +++ b/modules/L10_system_emulation/inferService.sh @@ -67,7 +67,7 @@ for BINARY in $("${BUSYBOX}" find / -name "lighttpd" -type f -o -name "upnp" -ty # check if this service is already in the service file: if ! "${BUSYBOX}" grep -q "${SERVICE_NAME}" /firmadyne/service 2>/dev/null; then # check if we have a configuration available and iterate - for LIGHT_CONFIG in $("${BUSYBOX}" find / -name "lighttpd.conf" -type f); do + for LIGHT_CONFIG in $("${BUSYBOX}" find / -name "lighttpd*.conf" -type f); do # write the service starter with config file "${BUSYBOX}" echo -e "[*] Writing EMBA service for $ORANGE${BINARY} - ${LIGHT_CONFIG}$NC" "${BUSYBOX}" echo -e -n "${BINARY} -f ${LIGHT_CONFIG}\n" >> /firmadyne/service @@ -75,7 +75,7 @@ for BINARY in $("${BUSYBOX}" find / -name "lighttpd" -type f -o -name "upnp" -ty fi elif [ "$("${BUSYBOX}" echo "${SERVICE_NAME}")" == "miniupnpd" ]; then if ! "${BUSYBOX}" grep -q "${SERVICE_NAME}" /firmadyne/service 2>/dev/null; then - for MINIUPNPD_CONFIG in $("${BUSYBOX}" find / -name "miniupnpd.conf" -type f); do + for MINIUPNPD_CONFIG in $("${BUSYBOX}" find / -name "miniupnpd*.conf" -type f); do "${BUSYBOX}" echo -e "[*] Writing EMBA service for $ORANGE${BINARY} - ${MINIUPNPD_CONFIG}$NC" "${BUSYBOX}" echo -e -n "${BINARY} -f ${MINIUPNPD_CONFIG}\n" >> /firmadyne/service done diff --git a/modules/S26_kernel_vuln_verifier.sh b/modules/S26_kernel_vuln_verifier.sh index 2f7669387..2a972ac77 100755 --- a/modules/S26_kernel_vuln_verifier.sh +++ b/modules/S26_kernel_vuln_verifier.sh @@ -2,7 +2,7 @@ # EMBA - EMBEDDED LINUX ANALYZER # -# Copyright 2020-2022 Siemens Energy AG +# Copyright 2020-2023 Siemens Energy 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.