Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve s24/s25 handling #1011

Merged
merged 5 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 4 additions & 3 deletions emba
Original file line number Diff line number Diff line change
Expand Up @@ -719,9 +719,9 @@ main() {
disable_strict_mode "${STRICT_MODE}" 0
if [[ "${ONLY_DEP}" -gt 0 ]]; then
# check dependencies mode:
EMBA="${INVOCATION_PATH}" FIRMWARE="${FIRMWARE_PATH}" "${DOCKER_COMPOSE[@]}" run --rm emba -c './emba -f /firmware -i "$@"' _ "${ARGUMENTS[@]}"
EMBA="${INVOCATION_PATH}" FIRMWARE="${FIRMWARE_PATH}" LOG="/tmp" "${DOCKER_COMPOSE[@]}" run --rm emba -c './emba -l /logs -f /firmware -i "$@"' _ "${ARGUMENTS[@]}"
D_RETURN=$?
EMBA="${INVOCATION_PATH}" FIRMWARE="${FIRMWARE_PATH}" "${DOCKER_COMPOSE[@]}" run --rm emba_quest -c './emba -f /firmware -i "$@"' _ "${ARGUMENTS[@]}"
EMBA="${INVOCATION_PATH}" FIRMWARE="${FIRMWARE_PATH}" LOG="/tmp" "${DOCKER_COMPOSE[@]}" run --rm emba_quest -c './emba -l /logs -f /firmware -i "$@"' _ "${ARGUMENTS[@]}"
if [[ $? -ne ${D_RETURN} ]]; then
D_RETURN=1
fi
Expand Down Expand Up @@ -790,11 +790,12 @@ main() {
print_output "[*] $(print_date) - Access the web-report with ${ORANGE}firefox $(abs_path "${HTML_PATH}/index.html")${NC}" "main"
fi
cleaner 0
print_output "[!] $(print_date) - Test ended on ""$(print_date)"" and took about ""$(show_runtime)"" \\n" "main"
else
# we do not need the log dir from dependency checker
[[ -d "${LOG_DIR}" ]] && rm -rf "${LOG_DIR}"
print_output "[!] $(print_date) - Test ended on ""$(print_date)"" and took about ""$(show_runtime)"" \\n" "no_log"
fi
print_output "[!] $(print_date) - Test ended on ""$(print_date)"" and took about ""$(show_runtime)"" \\n" "main"
exit 0
else
print_output "[-] $(print_date) - Test ended on ""$(print_date)"" and EMBA failed in docker mode!" "main"
Expand Down
21 changes: 18 additions & 3 deletions helpers/helpers_emba_status_bar.sh
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,22 @@ update_box_modules() {
fi
MODULES=( "${MODULES_EMBA[@]}" "${MODULES_LOCAL[@]}" )
for MODULE_FILE in "${MODULES[@]}" ; do
if ( file "${MODULE_FILE}" | grep -q "shell script" ) && ! [[ "${MODULE_FILE}" =~ \ |\' ]] ; then
if ( file "${MODULE_FILE}" | grep -q "shell script" ) && ! [[ "${MODULE_FILE}" =~ \ |\' ]]; then
# if system emulation is not enabled, we do not count the L modules
if [[ "$(basename "${MODULE_FILE}")" =~ ^L[0-9]* ]] && [[ "${FULL_EMULATION}" -ne 1 ]]; then
continue
fi
# if diffing is not enabled, we do not count the diffing modules
if [[ "$(basename "${MODULE_FILE}")" =~ ^D[0-9]* ]] && [[ -z "${FIRMWARE_PATH1}" ]]; then
continue
fi
# we do not count the quest modules
if [[ "$(basename "${MODULE_FILE}")" =~ ^Q[0-9]* ]]; then
continue
fi
if [[ "${MODULE_BLACKLIST[*]}" == *"$(basename -s .sh "${MODULE_FILE}")"* ]]; then
continue
fi
(( COUNT_MODULES+=1 ))
fi
done
Expand All @@ -284,8 +299,8 @@ update_box_modules() {
BOX_SIZE="$(sed '1q;d' "${STATUS_TMP_PATH}" 2> /dev/null || true)"
fi
while [[ "${BOX_SIZE}" -gt 0 ]]; do
STARTED_MODULE_STR="$(grep -c "starting" "${LOG_DIR}/emba.log" 2> /dev/null || true )"
FINISHED_MODULE_STR="$(grep "finished" "${LOG_DIR}/emba.log" 2> /dev/null | grep -vc "Quest container finished" || true )"
STARTED_MODULE_STR="$(grep -c "starting\|blacklist triggered" "${LOG_DIR}/emba.log" 2> /dev/null || true )"
FINISHED_MODULE_STR="$(grep "finished\|blacklist triggered" "${LOG_DIR}/emba.log" 2> /dev/null | grep -vc "Quest container finished" || true )"
LAST_FINISHED_MODULE_STR="$(grep "finished" "${LOG_DIR}/emba.log" 2> /dev/null | grep -v "Quest container finished"| tail -1 | awk '{print $9}' | cut -d"_" -f1 || true )"
printf '\e[s\e[%s;55f%s\e[%s;55f%s\e[%s;55f%s\e[u' "$(( LINES - 3 ))" "$(module_util_str 0 "$((STARTED_MODULE_STR - FINISHED_MODULE_STR))")" "$(( LINES - 2 ))" "$(module_util_str 1 "${LAST_FINISHED_MODULE_STR}")" "$(( LINES - 1 ))" "$(module_util_str 2 "${FINISHED_MODULE_STR}/${COUNT_MODULES}")" || true
sleep 1
Expand Down
4 changes: 2 additions & 2 deletions modules/S118_busybox_verifier.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ S118_busybox_verifier()
# finally we search manually for the version
if [[ "${#BB_VERSIONS_ARR[@]}" -eq 0 ]]; then
# first grep is for identification of possible binary files:
mapfile -t BB_BINS_ARR < <(grep -l -a -E "BusyBox\ v[0-9](\.[0-9]+)+?.*" "${LOG_DIR}"/firmware -r 2>/dev/null)
mapfile -t BB_BINS_ARR < <(grep -l -a -E "BusyBox\ v[0-9](\.[0-9]+)+?.*" "${LOG_DIR}"/firmware -r 2>/dev/null || true)
for BB_BIN in "${BB_BINS_ARR[@]}"; do
if ! file "${BB_BIN}" | grep -q "ELF"; then
continue
fi
# now modify the version identifier to use it also for our CVE identification
VERSION_IDENTIFIER=$(strings "${BB_BIN}" | grep -E "BusyBox\ v[0-9](\.[0-9]+)+?.*" | sort -u | sed -r 's/BusyBox\ v([0-9](\.[0-9]+)+?)\ .*/busybox:\1/' | sort -u | head -1)
VERSION_IDENTIFIER=$(strings "${BB_BIN}" | grep -E "BusyBox\ v[0-9](\.[0-9]+)+?.*" | sort -u | sed -r 's/BusyBox\ v([0-9](\.[0-9]+)+?)\ .*/busybox:\1/' | sort -u | head -1 || true)
# build the needed array
BB_VERSIONS_ARR+=( "${BB_BIN};${VERSION_IDENTIFIER}" )
done
Expand Down
2 changes: 2 additions & 0 deletions modules/S24_kernel_bin_identifier.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# Description: This module tries to identify the kernel file and the init command line
# The identified kernel binary file is extracted with vmlinux-to-elf

export THREAD_PRIO=1

S24_kernel_bin_identifier()
{
module_log_init "${FUNCNAME[0]}"
Expand Down
100 changes: 69 additions & 31 deletions modules/S26_kernel_vuln_verifier.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# identifies vulnerabilities via the version number and tries to verify the
# CVEs

export THREAD_PRIO=1

S26_kernel_vuln_verifier()
{
module_log_init "${FUNCNAME[0]}"
Expand Down Expand Up @@ -57,6 +59,7 @@ S26_kernel_vuln_verifier()
export KERNEL_CONFIG_PATH="NA"
export KERNEL_ELF_PATH=""
local K_VERSION_KORG=""
export COMPILE_SOURCE_FILES_VERIFIED=0

for K_VERSION in "${K_VERSIONS[@]}"; do
local K_FOUND=0
Expand Down Expand Up @@ -296,10 +299,14 @@ S26_kernel_vuln_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+=( "$!" )
if [[ "${SYMBOLS_CNT}" -gt 0 ]]; then
symbol_verifier "${CVE}" "${K_VERSION}" "${K_PATH}" "${CVSS2}/${CVSS3}" &
WAIT_PIDS_S26+=( "$!" )
fi
if [[ "${COMPILE_SOURCE_FILES_VERIFIED}" -gt 0 ]]; then
compile_verifier "${CVE}" "${K_VERSION}" "${K_PATH}" "${CVSS2}/${CVSS3}" &
WAIT_PIDS_S26+=( "$!" )
fi
else
# this vulnerability is for a different architecture -> we can skip it for our kernel
OUTx="[-] Vulnerable path for different architecture found for ${ORANGE}${K_PATH}${NC} - not further processing ${ORANGE}${CVE}${NC}"
Expand All @@ -309,10 +316,14 @@ S26_kernel_vuln_verifier()
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+=( "$!" )
if [[ "${SYMBOLS_CNT}" -gt 0 ]]; then
symbol_verifier "${CVE}" "${K_VERSION}" "${K_PATH}" "${CVSS2}/${CVSS3}" &
WAIT_PIDS_S26+=( "$!" )
fi
if [[ "${COMPILE_SOURCE_FILES_VERIFIED}" -gt 0 ]]; then
compile_verifier "${CVE}" "${K_VERSION}" "${K_PATH}" "${CVSS2}/${CVSS3}" &
WAIT_PIDS_S26+=( "$!" )
fi
fi
else
# no source file in our kernel sources -> no vulns
Expand Down Expand Up @@ -429,7 +440,7 @@ compile_kernel() {
local KERNEL_DIR="${2:-}"
local KARCH="${3:-}"
export COMPILE_SOURCE_FILES=0
local COMPILE_SOURCE_FILES_VERIFIED=""
export COMPILE_SOURCE_FILES_VERIFIED=0

if ! [[ -f "${KERNEL_CONFIG_FILE}" ]]; then
print_output "[-] No supported kernel config found - ${ORANGE}${KERNEL_CONFIG_FILE}${NC}"
Expand Down Expand Up @@ -495,6 +506,24 @@ compile_kernel() {
fi
}

report_kvulns_csv() {
local VULN="${1:-}"
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)"
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
}

final_log_kernel_vulns() {
sub_module_title "Linux kernel verification results"
local K_VERSION="${1:-}"
Expand Down Expand Up @@ -526,6 +555,7 @@ final_log_kernel_vulns() {
local CVE_CRITICAL=""
local CVSS2_CRITICAL=""
local CVSS3_CRITICAL=""
local WAIT_PIDS_S26_1=()

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
Expand All @@ -537,20 +567,14 @@ final_log_kernel_vulns() {
# 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=""
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)"
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
if [[ "${THREADED}" -eq 1 ]]; then
report_kvulns_csv "${VULN}" &
local TMP_PID="$!"
WAIT_PIDS_S26_1+=( "${TMP_PID}" )
max_pids_protection "${MAX_MOD_THREADS}" "${WAIT_PIDS_S26_1[@]}"
else
report_kvulns_csv "${VULN}"
fi
done

SYM_USAGE_VERIFIED=$(wc -l "${LOG_PATH_MODULE}"/CVE-*symbol_* 2>/dev/null | tail -1 | awk '{print $1}' 2>/dev/null || true)
Expand All @@ -562,10 +586,6 @@ final_log_kernel_vulns() {
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)
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_output "[+] Identified ${ORANGE}${#ALL_KVULNS[@]}${GREEN} unverified CVE vulnerabilities for kernel version ${ORANGE}${K_VERSION}${NC}"
write_link "${LOG_PATH_MODULE}/cve_results_kernel_${K_VERSION}.csv"
Expand All @@ -584,6 +604,14 @@ final_log_kernel_vulns() {
print_output "[*] ${ORANGE}${VULN_PATHS_VERIFIED_COMPILED}${NC} vulnerable paths verified via compiled paths"
print_ln

# we need to wait for the cve_results_kernel_"${K_VERSION}".csv
[[ ${THREADED} -eq 1 ]] && wait_for_pid "${WAIT_PIDS_S26_1[@]}"

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)

if [[ "${CVE_VERIFIED_SYMBOLS}" -gt 0 ]]; then
print_output "[+] Verified CVEs: ${ORANGE}${CVE_VERIFIED_SYMBOLS}${GREEN} (exported symbols)"
fi
Expand All @@ -604,8 +632,13 @@ final_log_kernel_vulns() {
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}\t-\t${ORANGE}${CVSS2_CRITICAL}${GREEN} / ${ORANGE}${CVSS3_CRITICAL}${GREEN}\t-\tExploit/PoC: ${ORANGE}${EXPLOIT_DETECTED} ${EXP} / ${POC_DETECTED} ${POC}${NC}")")"
# disabled because it is too slow
# identify_exploits "${CVE_CRITICAL}"
if [[ "${EXPLOIT_DETECTED:-"no"}" == "yes" ]] || [[ "${POC_DETECTED:-"no"}" == "yes" ]]; then
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}")")"
else
print_output "$(indent "$(orange "${ORANGE}${CVE_CRITICAL}${GREEN}\t-\t${ORANGE}${CVSS2_CRITICAL}${GREEN} / ${ORANGE}${CVSS3_CRITICAL}${GREEN}")")"
fi
done
fi

Expand All @@ -616,8 +649,13 @@ final_log_kernel_vulns() {
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}\t-\t${ORANGE}${CVSS2_CRITICAL}${GREEN} / ${ORANGE}${CVSS3_CRITICAL}${GREEN}\t-\tExploit/PoC: ${ORANGE}${EXPLOIT_DETECTED} ${EXP} / ${POC_DETECTED} ${POC}${NC}")")"
# disabled because it is too slow
# identify_exploits "${CVE_CRITICAL}"
if [[ "${EXPLOIT_DETECTED:-"no"}" == "yes" ]] || [[ "${POC_DETECTED:-"no"}" == "yes" ]]; then
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}")")"
else
print_output "$(indent "$(orange "${ORANGE}${CVE_CRITICAL}${GREEN}\t-\t${ORANGE}${CVSS2_CRITICAL}${GREEN} / ${ORANGE}${CVSS3_CRITICAL}${GREEN}")")"
fi
done
fi
write_log "[*] Statistics:${K_VERSION}:${#ALL_KVULNS[@]}:${CVE_VERIFIED_SYMBOLS}:${CVE_VERIFIED_COMPILED}"
Expand Down