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

checksec FORTIFY detection (proccheck) #243

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
26 changes: 18 additions & 8 deletions tests/binaries/build_binaries.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,22 @@ 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
set +x
if ! command -v nasm >/dev/null 2>&1; then
printf "\033[31mError: This script requires Netwide Assembler (NASM) to be installed and on your PATH ...\033[m\n\n"
exit 1
else
set -x
nasm -f elf64 -o nolibc.o nolibc.asm
nasm -f elf32 -o nolibc32.o nolibc32.asm
fi
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"
Loading