-
Notifications
You must be signed in to change notification settings - Fork 13
Binary hardening
To protect against various threats, it would be good to harden at least some binaries and libraries with various memory protections / binary hardening.
The following technologies should be considered:
- Relocation Read-Only (RELRO)
- Position-independent executable (PIE)
-
Stack canaries
-
-fstack-protector<-fstack-protector-strong<-fstack-protector-all --param=ssp-buffer-size=4- Do note that when you're checking binary protections with checksec.sh against
stripped bins,checksec.shis unable to find the__stack_chk_failwithreadelf -sas the symbol table section (.symtab) has been removed and it will printNo canary found. You can userabin2 -I file | grep '^canary'instead. - fstack-protector
- "Strong" stack protection for GCC February 5, 2014
-
-
Source Fortification
- -D_FORTIFY_SOURCE=2 21 Sep 2004
- gcc (GCC) 11.2.0 & glibc 2.33:
warning: #warning _FORTIFY_SOURCE > 2 is treated like 2 on this platform [-Wcpp] -
A new builtin provides enhanced buffer size detection (
_FORTIFY_SOURCE=3in GCC 12) September 17, 2022 - Enhance application security with FORTIFY_SOURCE March 26, 2014
- Broadening compiler checks for buffer overflows in _FORTIFY_SOURCE April 16, 2021
- Security Technologies: FORTIFY_SOURCE September 26, 2018
- You can check for the fortified functions with
rabin2 -i file | gawk 'NR<3 || 5ドル ~ /_chk$/{print}'
- -ftrivial-auto-var-init=zero (not available in the GCC version currently packaged in Slackware 15.0)
-
-fstack-clash-protection
- "Most targets do not fully support stack clash protection."
- Stack clash mitigation in GCC, Part 3
- Bringing Stack Clash Protection to Clang / X86 — the Open Source Way
-
-fcf-protection
- "The value
fullis an alias for specifying bothbranchandreturn." - "Currently the x86 GNU/Linux target provides an implementation based on Intel Control-flow Enforcement Technology (CET)."
- Complex Shadow-Stack Updates (Intel® Control-Flow Enforcement Technology)
-
Control-flow Enforcement Technology (CET) Shadow Stack
readelf -n <application> | grep -a SHSTK
- "The value
-
-fhardened
- "When the system glibc is older than 2.35,
-D_FORTIFY_SOURCE=2is used instead."- Slackware 15.0 has glibc 2.33
- "When the system glibc is older than 2.35,
-
-Wformat-security -
-fplugin=annobin(when you have Annobin)- The readelf program can be used to examine the notes:
readelf --notes --wide <file>
- The readelf program can be used to examine the notes:
-mbranch-protection
This can be achieved by using something like the following in SlackBuilds:
SLKCFLAGS="-O2 -fPIC -fPIE -pie -Wl,-z,relro,-z,now -fstack-protector-all -fstack-clash-protection -fcf-protection=full -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS"
Some packages can not be built with PIE, when they try to build shared libraries with it, and you can see the build failing for example like this:
building shared krb5support library (0.1)
set -x; objlist=`set -x && perl -p -e 'BEGIN { $SIG{__WARN__} = sub {die @_} }; $e=$ARGV; $e =~ s/OBJS\...$//; s/^/ /; s/ $//; s/ / $e/g;' OBJS.SH` && gcc -shared -fPIC -Wl,-h,libkrb5support.so.0 -Wl,--no-undefined -o libkrb5support.so.0.1 $objlist -Wl,--enable-new-dtags -Wl,-rpath -Wl,/usr/lib64 -L../../lib -lkeyutils -lresolv -ldl -Wl,--version-script binutils.versions
++ set -x
++ perl -p -e 'BEGIN { $SIG{__WARN__} = sub {die @_} }; $e=$ARGV; $e =~ s/OBJS\...$//; s/^/ /; s/ $//; s/ / $e/g;' OBJS.SH
+ objlist=' threads.so init-addrinfo.so plugins.so errors.so k5buf.so gmt_mktime.so fake-addrinfo.so utf8.so utf8_conv.so zap.so path.so base64.so json.so hex.so hashtab.so bcmp.so strerror_r.so dir_filenames.so strlcpy.so'
+ gcc -shared -fPIC -Wl,-h,libkrb5support.so.0 -Wl,--no-undefined -o libkrb5support.so.0.1 threads.so init-addrinfo.so plugins.so errors.so k5buf.so gmt_mktime.so fake-addrinfo.so utf8.so utf8_conv.so zap.so path.so base64.so json.so hex.so hashtab.so bcmp.so strerror_r.so dir_filenames.so strlcpy.so -Wl,--enable-new-dtags -Wl,-rpath -Wl,/usr/lib64 -L../../lib -lkeyutils -lresolv -ldl -Wl,--version-script binutils.versions
/usr/bin/ld: utf8_conv.so: warning: relocation against `krb5int_utf8_mintab' in read-only section `.text'
/usr/bin/ld: threads.so: relocation R_X86_64_PC32 against symbol `stderr@@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
make[2]: *** [Makefile:925: libkrb5support.so.0.1] Error 1
make[2]: Leaving directory '/tmp/krb5-1.21.3/src/util/support'
make[1]: *** [Makefile:857: all-recurse] Error 1
make[1]: Leaving directory '/tmp/krb5-1.21.3/src/util'
make: *** [Makefile:1521: all-recurse] Error 1
In these cases you need to remove the -fPIE -pie from SLKCFLAGS.
Here's some thoughts about which binaries should/could be hardened:
- SSH (hardened by default)
- Communication clients:
- irssi (has canary, but no RELRO & PIE)
- Pidgin
- BitTorrent clients
- Mail
- mutt
- Postfix
- Dovecot
- Libraries
- OpenSSL
- GnuTLS
- gpgme
- gpg
- git
- coreutils
- Archiving tools:
- tar
- bzip2
- rar
- Tools that are used against binaries etc.
- less
- strings
- file
- *sum
- hexdump
- PDF readers
- Traffic analyzers (tcpdump, wireshark)
- Clamav
- wget/curl
- SUID binaries
sudo
- Apache/PHP
- krb5
- OpenLDAP
- PAM
-
lddall the bins and find the most common libraries to harden.
You can use checksec.sh to check binary hardenings. Do note, that the stack canary check will not work for stripped binaries, as the symbols do not exist and checksec.sh tries to look for __stack_chk_fail (in .dynstr section).
A fork from checksec that is currently maintained is available here: https://github.com/slimm609/checksec.
You can use radare2 to check hardenings:
$ rabin2 -I $(which ssh) | grep '^\(canary\|nx\|pic\|relro\|rpath\)\b'
canary true
nx true
pic true
relro full
rpath NONE
GEF has a checksec command.
- https://wiki.debian.org/Hardening#Environment_variables
- Determining Programs to Immunize
- -fstack-protector-strong
- Using the GNU Compiler Collection (GCC): Code Gen Options
- Hardened compilation flags
- https://gcc.gnu.org/onlinedocs/gccint/target-macros/stack-layout-and-calling-conventions/stack-smashing-protection.html
- Learning Linux Binary Analysis
- Use compiler flags for stack protection in GCC and Clang
-
Hardening
- "Prior to GCC 4.9,
-fstack-protector --param ssp-buffer-size=4is used to cover functions that defines a 4 or more byte local character array, which is an okay balance for security and performance. For those who want to protect all the functions then-fstack-protector-allis recommended."
- "Prior to GCC 4.9,
-
-fstack-protector-strong
- "the default (
-fstack-protector), only includes the canary code when a function defines an 8 (--param=ssp-buffer-size=N, N=8 by default) or more byte local character array" - "Various distributions ended up lowering their default
--param=ssp-buffer-sizeoption down to 4, since there were still cases of functions that should have been protected but the conservative gcc upstream default of 8 wasn’t covering them." - "However, even with the increased function coverage, there are rare cases when a stack overflow happens on other kinds of stack variables. To handle this more paranoid concern,
-fstack-protector-allwas defined to add the canary to all functions."
- "the default (
- Compiler Options Hardening Guide for C and C++
- LQ thread: Hardening options for C and C++ in Slackware
- What’s new in security for Ubuntu 24.04 LTS? (the Binary hardening section)
Secure Code Partitioning With ELF binaries, aka. SCOP:
A Secure ELF binary should have the following mitigations applied:
- RELRO gcc -Wl,-z,relro,-z,now
- SCOP gcc -Wl,-z,code-separation
- PIE (Full ASLR) gcc -fPIC -pie
- Stack Canaries gcc -fstack-protector
- PaX mprotect(2) paxctl -M
Do not forget that statically linked executables do not officially support PIE or RELRO, but have had some solutions proposed in the paper "ASLR and RELRO protection for statically linked executables"
- https://security.stackexchange.com/questions/161799/why-does-checksec-sh-highlight-rpath-and-runpath-as-security-issues/165762#165762:
- rpath security issues (SSA:2024-275-03)
Signing binaries with either elfsign or bsign? Apparently bsign doesn't work against 64-bit binaries
-
https://github.com/struct/mms:
ld -z now - -static-pie
- Check the hardening flags in goom.SlackBuild