Skip to content

Commit

Permalink
Merge pull request #245 from teoberi/Fortify-proccheck-last
Browse files Browse the repository at this point in the history
checksec FORTIFY detection (proccheck) last
  • Loading branch information
slimm609 authored May 23, 2024
2 parents 9a7f535 + 0ed7fad commit a5819f3
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 48 deletions.
2 changes: 1 addition & 1 deletion Dockerfile.photon
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ FROM photon:5.0
RUN tdnf upgrade -y && tdnf remove toybox -y && \
tdnf install -y build-essential git rpm-build coreutils util-linux \
make autoconf automake gcc ncurses-devel sed tar texinfo wget procps-ng grep \
findutils gzip file which libxml2 python3 python3-pip jq clang && \
findutils gzip file which libxml2 python3 python3-pip jq clang nasm binutils && \
pip3 install --upgrade pip && pip3 install setuptools && \
pip3 install demjson3 && mkdir -p /zig && \
wget https://ziglang.org/builds/zig-linux-$(uname -m)-0.12.0-dev.3667+77abd3a96.tar.xz && \
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.ubuntu
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ RUN apt-get update && apt-get -y -q upgrade && DEBIAN_FRONTEND=noninteractive ap
bc bison flex build-essential git file \
libncurses-dev libssl-dev u-boot-tools wget \
xz-utils vim libxml2-utils python3 python3-pip jq \
gcc clang gcc-multilib && apt-get clean \
gcc clang gcc-multilib nasm binutils && apt-get clean \
pip3 install --upgrade pip && pip3 install setuptools && \
pip3 install demjson3 && mkdir -p /zig && \
wget https://ziglang.org/builds/zig-linux-$(uname -m)-0.12.0-dev.3667+77abd3a96.tar.xz && \
Expand Down
27 changes: 23 additions & 4 deletions checksec
Original file line number Diff line number Diff line change
Expand Up @@ -1609,11 +1609,30 @@ proccheck() {
fi

#check for Fortify source support
Proc_FS_functions="$(${readelf} -s "${1}/exe" 2> /dev/null | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//')"
if grep -q '_chk$' <<< "$Proc_FS_functions"; then
echo_message '\033[32mYes\033[m' 'Yes' " fortify_source='yes'>" '"fortify_source":"yes" }'
search_libc
libc_found="false"
if ${readelf} -d "$(readlink "${1}"/exe)" 2> /dev/null | grep 'NEEDED' | grep -q 'libc\.so'; then
libc_found="true"
fi
Proc_FS_filechk_func_libc="$(${readelf} -s "${use_dynamic}" "${FS_libc}" 2> /dev/null | sed -ne 's/.*__\(.*_chk\)@@.*/\1/p')"
Proc_FS_func_libc="${Proc_FS_filechk_func_libc//_chk/}"
Proc_FS_func="$(${readelf} -s "${use_dynamic}" "${1}/exe" 2> /dev/null | awk '{ print $8 }' | sed -e 's/_*//' -e 's/@.*//' -e '/^$/d')"
Proc_FS_cnt_checked=$(grep -cFxf <(sort -u <<< "${Proc_FS_filechk_func_libc}") <(sort -u <<< "${Proc_FS_func}"))
Proc_FS_cnt_unchecked=$(grep -cFxf <(sort -u <<< "${Proc_FS_func_libc}") <(sort -u <<< "${Proc_FS_func}"))
Proc_FS_cnt_total=$((Proc_FS_cnt_unchecked + Proc_FS_cnt_checked))

if [[ "${libc_found}" == "false" ]] || [[ "${Proc_FS_cnt_total}" == "0" ]]; then
echo_message "\033[32mN/A\033[m" "N/A," ' fortify_source="n/a">' '"fortify_source":"n/a" }'
else
echo_message "\033[31mNo\033[m" "No" " fortify_source='no'>" '"fortify_source":"no" }'
if [[ $Proc_FS_cnt_checked -eq $Proc_FS_cnt_total ]]; then
echo_message '\033[32mYes\033[m' 'Yes,' ' fortify_source="yes">' '"fortify_source":"yes" }'
else
if [[ "${Proc_FS_cnt_checked}" == "0" ]]; then
echo_message "\033[31mNo\033[m" "No," ' fortify_source="no">' '"fortify_source":"no" }'
else
echo_message "\033[33mPartial\033[m" "Partial," ' fortify_source="partial">' '"fortify_source":"partial" }'
fi
fi
fi
}

Expand Down
27 changes: 23 additions & 4 deletions src/functions/proccheck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,29 @@ proccheck() {
fi

#check for Fortify source support
Proc_FS_functions="$(${readelf} -s "${1}/exe" 2> /dev/null | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//')"
if grep -q '_chk$' <<< "$Proc_FS_functions"; then
echo_message '\033[32mYes\033[m' 'Yes' " fortify_source='yes'>" '"fortify_source":"yes" }'
search_libc
libc_found="false"
if ${readelf} -d "$(readlink "${1}"/exe)" 2> /dev/null | grep 'NEEDED' | grep -q 'libc\.so'; then
libc_found="true"
fi
Proc_FS_filechk_func_libc="$(${readelf} -s "${use_dynamic}" "${FS_libc}" 2> /dev/null | sed -ne 's/.*__\(.*_chk\)@@.*/\1/p')"
Proc_FS_func_libc="${Proc_FS_filechk_func_libc//_chk/}"
Proc_FS_func="$(${readelf} -s "${use_dynamic}" "${1}/exe" 2> /dev/null | awk '{ print $8 }' | sed -e 's/_*//' -e 's/@.*//' -e '/^$/d')"
Proc_FS_cnt_checked=$(grep -cFxf <(sort -u <<< "${Proc_FS_filechk_func_libc}") <(sort -u <<< "${Proc_FS_func}"))
Proc_FS_cnt_unchecked=$(grep -cFxf <(sort -u <<< "${Proc_FS_func_libc}") <(sort -u <<< "${Proc_FS_func}"))
Proc_FS_cnt_total=$((Proc_FS_cnt_unchecked + Proc_FS_cnt_checked))

if [[ "${libc_found}" == "false" ]] || [[ "${Proc_FS_cnt_total}" == "0" ]]; then
echo_message "\033[32mN/A\033[m" "N/A," ' fortify_source="n/a">' '"fortify_source":"n/a" }'
else
echo_message "\033[31mNo\033[m" "No" " fortify_source='no'>" '"fortify_source":"no" }'
if [[ $Proc_FS_cnt_checked -eq $Proc_FS_cnt_total ]]; then
echo_message '\033[32mYes\033[m' 'Yes,' ' fortify_source="yes">' '"fortify_source":"yes" }'
else
if [[ "${Proc_FS_cnt_checked}" == "0" ]]; then
echo_message "\033[31mNo\033[m" "No," ' fortify_source="no">' '"fortify_source":"no" }'
else
echo_message "\033[33mPartial\033[m" "Partial," ' fortify_source="partial">' '"fortify_source":"partial" }'
fi
fi
fi
}
19 changes: 11 additions & 8 deletions tests/binaries/build_binaries.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,15 @@ clang -m32 -o output/none_cl32 test.c -w -D_FORTIFY_SOURCE=0 -fno-stack-protecto
clang -m32 -c test.c -o output/rel_cl32.o
clang -m32 -shared -fPIC -o output/dso_cl32.so test.c -w -D_FORTIFY_SOURCE=2 -fstack-protector-strong -O2 -z relro -z now -z noexecstack -s

gcc -o output/nolibc main.c start.S hello.S -w -nostdlib -no-pie -s
clang -o output/nolibc_cl main.c start.S hello.S -w -nostdlib -no-pie -s
gcc -m32 -o output/nolibc32 main.c start.S hello.S -w -nostdlib -no-pie -s
clang -m32 -o output/nolibc_cl32 main.c start.S hello.S -w -nostdlib -no-pie -s
# Fortify source (NASM assembler installation is required)
nasm -f elf64 -o nolibc.o nolibc.asm
nasm -f elf32 -o nolibc32.o nolibc32.asm
gcc -o output/nolibc nolibc.o -w -nostdlib -no-pie -s
clang -o output/nolibc_cl nolibc.o -w -nostdlib -no-pie -s
gcc -m32 -o output/nolibc32 nolibc32.o -w -nostdlib -no-pie -s
clang -m32 -o output/nolibc_cl32 nolibc32.o -w -nostdlib -no-pie -s

gcc -o output/fszero helloworld.c -w -D_FORTIFY_SOURCE=0 -O2 -s
clang -o output/fszero_cl helloworld.c -w -D_FORTIFY_SOURCE=0 -O2 -s
gcc -m32 -o output/fszero32 helloworld.c -w -D_FORTIFY_SOURCE=0 -O2 -s
clang -m32 -o output/fszero_cl32 helloworld.c -w -D_FORTIFY_SOURCE=0 -O2 -s
gcc -o output/fszero fszero.c -w -D_FORTIFY_SOURCE=0 -O2 -s
clang -o output/fszero_cl fszero.c -w -D_FORTIFY_SOURCE=0 -O2 -s
gcc -m32 -o output/fszero32 fszero.c -w -D_FORTIFY_SOURCE=0 -O2 -s
clang -m32 -o output/fszero_cl32 fszero.c -w -D_FORTIFY_SOURCE=0 -O2 -s
2 changes: 2 additions & 0 deletions tests/binaries/helloworld.c → tests/binaries/fszero.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#include <stdio.h>
#include <unistd.h>

int main()
{
printf("Hello World\n");
sleep(2);
return 0;
}
18 changes: 0 additions & 18 deletions tests/binaries/hello.S

This file was deleted.

7 changes: 0 additions & 7 deletions tests/binaries/main.c

This file was deleted.

23 changes: 23 additions & 0 deletions tests/binaries/nolibc.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
section .data
msg db 'Hello, World!', 0ah ;note the newline (Line Feed-LF) at the end (hex:0ah; decimal:10)
len equ $ - msg ;calculate the length of the message
delay dq 2, 100000000 ;define delay with Timespec structure members tv_sec, tv_nsec (qwords, 64-bit integer values)

section .text
global _start ;must be declared for linker (ld)

_start: ;tells linker entry point
mov rax, 1 ;system call for write (sys_write 1)
mov rdi, 1 ;file descriptor (1 is stdout)
mov rsi, msg ;address of string to output
mov rdx, len ;message length
syscall ;invoke operating system to do the write

mov rax, 35 ;system call for nanosleep (sys_nanosleep 35)
mov rdi, delay ;load the pointer to our delay
mov rsi, 0 ;exit code 0
syscall ;invoke operating system to do the delay

mov rax, 60 ;system call for exit (sys_exit 60)
xor rdi, rdi ;exit code 0
syscall ;invoke operating system to exit
23 changes: 23 additions & 0 deletions tests/binaries/nolibc32.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
section .data
msg db "Hello, world!", 0xa ;note the newline (Line Feed-LF) at the end (hex:0ah; decimal:10)
len equ $ - msg ;calculate the length of the message
delay dd 2, 100000000 ;define delay with Timespec structure members tv_sec, tv_nsec (dwords, 32-bit integer values)

section .text
global _start ;must be declared for linker (ld)

_start: ;tells linker entry point
mov eax,4 ;system call for write (sys_write 4)
mov ebx,1 ;file descriptor (1 is stdout)
mov ecx,msg ;address of string to output
mov edx,len ;message length
int 0x80 ;invoke operating system to do the write

mov eax, 162 ;system call for nanosleep (sys_nanosleep 162)
mov ebx, delay ;load the pointer to our delay
mov ecx, 0 ;exit code 0
int 0x80 ;invoke operating system to do the delay

mov eax,1 ;system call for exit (sys_exit 1)
xor ebx, ebx ;exit code 0
int 0x80 ;invoke operating system to exit
5 changes: 0 additions & 5 deletions tests/binaries/start.S

This file was deleted.

16 changes: 16 additions & 0 deletions tests/hardening-checks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,22 @@ for bin in none none32 none_cl none_cl32; do
exit 1
fi
done
# N/A
for bin in nolibc nolibc_cl nolibc32 nolibc_cl32 fszero fszero_cl fszero32 fszero_cl32; do
"${DIR}"/binaries/output/${bin} > /dev/null &
if [[ $("${PARENT}"/checksec --proc=${bin} --format=csv | cut -d, -f8) != "N/A" ]]; then
echo "No Fortify process validation failed on \"${bin}\": $("${PARENT}"/checksec --proc=${bin} --format=csv | cut -d, -f8)"
exit 1
fi
done
# Partial
for bin in partial partial32 partial_cl partial_cl32; do
"${DIR}"/binaries/output/${bin} > /dev/null &
if [[ $("${PARENT}"/checksec --proc=${bin} --format=csv | cut -d, -f8) != "Partial" ]]; then
echo "No Fortify process validation failed on \"${bin}\": $("${PARENT}"/checksec --proc=${bin} --format=csv | cut -d, -f8)"
exit 1
fi
done
echo "Fortify process validation tests passed"
echo "Done."
echo "All hardening validation tests passed"

0 comments on commit a5819f3

Please sign in to comment.