CVE-2023-23457: Improper Restriction of Operations within the Bounds of a Memory Buffer (CWE-119)
value: A Segmentation fault was found in UPX in PackLinuxElf64::invert_pt_dynamic() in p_lx_elf.cpp. An attacker with a crafted input file allows invalid memory address access that could lead to a denial of service.
CWE description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
CVSS v3 base score: 5.5
Published: 2023-01-12T19:15Z
Repository: https://github.com/upx/upx
Language: C++
Files changed: src/p_lx_elf.cpp
Commit date: 2022-11-23 19:49:28 -0800
Commit message: invert_pt_dynamic: fix thinko; PackLinuxElf64help1 insist on ELF

https://github.com/upx/upx/issues/631
	modified:   src/p_lx_elf.cpp

Diff: diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp
index fa55470f7..b698ee0a2 100644
--- a/src/p_lx_elf.cpp
+++ b/src/p_lx_elf.cpp
@@ -254,11 +254,12 @@ PackLinuxElf32::PackLinuxElf32help1(InputFile *f)
 {
     e_type  = get_te16(&ehdri.e_type);
     e_phnum = get_te16(&ehdri.e_phnum);
     e_shnum = get_te16(&ehdri.e_shnum);
     unsigned const e_phentsize = get_te16(&ehdri.e_phentsize);
-    if (ehdri.e_ident[Elf32_Ehdr::EI_CLASS]!=Elf32_Ehdr::ELFCLASS32
+    if (memcmp((char const *)&ehdri, "\x7f\x45\x4c\x46", 4)  // "\177ELF"
+    || ehdri.e_ident[Elf32_Ehdr::EI_CLASS]!=Elf32_Ehdr::ELFCLASS32
     || sizeof(Elf32_Phdr) != e_phentsize
     || (Elf32_Ehdr::ELFDATA2MSB == ehdri.e_ident[Elf32_Ehdr::EI_DATA]
             && &N_BELE_RTP::be_policy != bele)
     || (Elf32_Ehdr::ELFDATA2LSB == ehdri.e_ident[Elf32_Ehdr::EI_DATA]
             && &N_BELE_RTP::le_policy != bele)) {
@@ -759,11 +760,12 @@ PackLinuxElf64::PackLinuxElf64help1(InputFile *f)
 {
     e_type  = get_te16(&ehdri.e_type);
     e_phnum = get_te16(&ehdri.e_phnum);
     e_shnum = get_te16(&ehdri.e_shnum);
     unsigned const e_phentsize = get_te16(&ehdri.e_phentsize);
-    if (ehdri.e_ident[Elf64_Ehdr::EI_CLASS]!=Elf64_Ehdr::ELFCLASS64
+    if (memcmp((char const *)&ehdri, "\x7f\x45\x4c\x46", 4)  // "\177ELF"
+    || ehdri.e_ident[Elf64_Ehdr::EI_CLASS]!=Elf64_Ehdr::ELFCLASS64
     || sizeof(Elf64_Phdr) != e_phentsize
     || (Elf64_Ehdr::ELFDATA2MSB == ehdri.e_ident[Elf64_Ehdr::EI_DATA]
             && &N_BELE_RTP::be_policy != bele)
     || (Elf64_Ehdr::ELFDATA2LSB == ehdri.e_ident[Elf64_Ehdr::EI_DATA]
             && &N_BELE_RTP::le_policy != bele)) {
@@ -5778,11 +5780,11 @@ PackLinuxElf64::invert_pt_dynamic(Elf64_Dyn const *dynp, upx_uint64_t headway)
                 dt_offsets[n_off] = elf_unsigned_dynamic(k);  // zero if not found
             }
         }
         if (file_size <= dt_offsets[n_off]) {
             char msg[60]; snprintf(msg, sizeof(msg), "bad DT_{%#x} = %#x (beyond EOF)",
-                dt_names[k], dt_offsets[n_off]);
+                k, dt_offsets[n_off]);
                 throwCantPack(msg);
         }
         n_off += !!dt_offsets[n_off];
     }
     dt_offsets[n_off++] = file_size;  // sentinel

Vulnerable code:     if (ehdri.e_ident[Elf32_Ehdr::EI_CLASS]!=Elf32_Ehdr::ELFCLASS32
    if (ehdri.e_ident[Elf64_Ehdr::EI_CLASS]!=Elf64_Ehdr::ELFCLASS64
                dt_names[k], dt_offsets[n_off]);
Fixed code:     if (memcmp((char const *)&ehdri, "\x7f\x45\x4c\x46", 4)  // "\177ELF"
    || ehdri.e_ident[Elf32_Ehdr::EI_CLASS]!=Elf32_Ehdr::ELFCLASS32
    if (memcmp((char const *)&ehdri, "\x7f\x45\x4c\x46", 4)  // "\177ELF"
    || ehdri.e_ident[Elf64_Ehdr::EI_CLASS]!=Elf64_Ehdr::ELFCLASS64
                k, dt_offsets[n_off]);