Live data from Hacker News

Hardening ELF binaries using Relocation Read-Only (2019)

redhat.com

11–20 of 31 posts

Re: Hardening ELF binaries using Relocation Read-Only (2019)

#11

Glad to see this security by default progress from RedHat. I was surprised to not see a discussion of the costs, though. How much slower is program startup for large programs now that all these functions are unconditionally looked up at the start instead of lazily? Even functions that are never called are now looked up.

There’s a one sentence nod to this at the bottom: > Using full RELRO has a slight performance impact during application startup (as the linker has to populate the GOT entries before entering the main function). In general, the difference for a large application is non-negligible and one should carefully consider the impact before enabling this feature by default.

How often are you starting large applications, and how do you define non-negligible here? Milliseconds?

Re: Hardening ELF binaries using Relocation Read-Only (2019)

#12

last time I checked the Debian and Gentoo hardening guides relro/pie were standard practice. I can't remember the time we didn't use it and I've been around for a minute. this is my template for most Linux projects (except when "something else" is needed :)) ... please don't copy paste without certainty of what it does: CFLAGS_BASE := -c -O2 -Wall -Werror -Wpedantic -pipe $(CFLAGS) CFLAGS_HARD := -fPIE -Wformat-secur…

   ... please don't copy paste without certainty of what it does
Would you be willing to explain why this specific set of flags (I realize I could google them all, but I also realize that some flags have interactions with other flags and trying to find those is not straightforward)?

Genuinely interested, not holding you accountable for my computer exploding.

Re: Hardening ELF binaries using Relocation Read-Only (2019)

#13

last time I checked the Debian and Gentoo hardening guides relro/pie were standard practice. I can't remember the time we didn't use it and I've been around for a minute. this is my template for most Linux projects (except when "something else" is needed :)) ... please don't copy paste without certainty of what it does: CFLAGS_BASE := -c -O2 -Wall -Werror -Wpedantic -pipe $(CFLAGS) CFLAGS_HARD := -fPIE -Wformat-secur…

Also, one can use checksec to confirm that the protections are actually in place. https://github.com/slimm609/checksec.sh

I happened to be looking at this for Go binaries last night and it seems that -buildmode=pie gets you part of the way there. Was trying to see if full relro was possible with CGO_ENABLED=0 but it seems only partial was achievable in the few hours I spent.

Re: Hardening ELF binaries using Relocation Read-Only (2019)

#14

One might wonder how high this raises the bar; that is, what how an attacker would generally respond to full RELRO. The answer is usually that one would go after other data pointers not secured by RELRO. If there’s any in the binary, that’s the best, but otherwise usually you leak information about libc and target something like the malloc or free hooks which are likely to be called.

It definitely makes generic exploits harder. Without RELRO it's easy to leak libc once you find an overflow. You can also easily take control via overwriting the GOT pointers. Unsure what you mean by any in the binary - with PIE you can't do much even if you know a fixed offset, unless you can leak the binary location. Although if you can read/write into the stack you can usually find something useful regardless of RELRO/etc.

One of my favorite examples of bypassing relro is the sudo exploit that took advantage of a simple format string vulnerability. It was downplayed at the time by the sudo maintainer as not easy to exploit due to FORTIFY. But you could get full root just doing a very simple payload, because sudo already calls system(/bin/sh) and FORTIFY itself was easily exploitable. [1][2]

1: https://www.sudo.ws/alerts/sudo_debug.html

2: https://www.vnsecurity.net/research/2012/02/16/exploiting-su...

Re: Hardening ELF binaries using Relocation Read-Only (2019)

#15

last time I checked the Debian and Gentoo hardening guides relro/pie were standard practice. I can't remember the time we didn't use it and I've been around for a minute. this is my template for most Linux projects (except when "something else" is needed :)) ... please don't copy paste without certainty of what it does: CFLAGS_BASE := -c -O2 -Wall -Werror -Wpedantic -pipe $(CFLAGS) CFLAGS_HARD := -fPIE -Wformat-secur…

If there's a religion for hating systemd, I want to be one of the high priests.

Re: Hardening ELF binaries using Relocation Read-Only (2019)

#16

last time I checked the Debian and Gentoo hardening guides relro/pie were standard practice. I can't remember the time we didn't use it and I've been around for a minute. this is my template for most Linux projects (except when "something else" is needed :)) ... please don't copy paste without certainty of what it does: CFLAGS_BASE := -c -O2 -Wall -Werror -Wpedantic -pipe $(CFLAGS) CFLAGS_HARD := -fPIE -Wformat-secur…

... please don't copy paste without certainty of what it does Would you be willing to explain why this specific set of flags (I realize I could google them all, but I also realize that some flags have interactions with other flags and trying to find those is not straightforward)? Genuinely interested, not holding you accountable for my computer exploding.

If nothing else, I'd like to call out -Werror as a footgun when shipping for other people to use. By all means use it for dev work when you control the environment, but as an end-user (well, downstream, at least) it's a problem when packages outright break because I'm building with a newer compiler version that added more warnings.

Re: Hardening ELF binaries using Relocation Read-Only (2019)

#17

last time I checked the Debian and Gentoo hardening guides relro/pie were standard practice. I can't remember the time we didn't use it and I've been around for a minute. this is my template for most Linux projects (except when "something else" is needed :)) ... please don't copy paste without certainty of what it does: CFLAGS_BASE := -c -O2 -Wall -Werror -Wpedantic -pipe $(CFLAGS) CFLAGS_HARD := -fPIE -Wformat-secur…

... please don't copy paste without certainty of what it does Would you be willing to explain why this specific set of flags (I realize I could google them all, but I also realize that some flags have interactions with other flags and trying to find those is not straightforward)? Genuinely interested, not holding you accountable for my computer exploding.

Not OP, but here goes:

* -fPIE : Compile as a 'position-independent executable'. This allows code and data sections of the executable to be installed at random locations in the address space, and comes with a mild cost due to needing extra indirections to handle position-independent code.

* -Wformat-security: adds some extra warnings around possible misuse of printf and scanf.

* -fstack-protector-strong --param=ssp-buffer-size=4: adds extra code in functions to check that stack buffer overflows likely haven't occurred. The second bit does it for every variable at least 4 bytes in size.

* -fcf-protection: this enables Intel CET instructions to check control flow integrity. This essentially causes the hardware to have a shadow stack and other tracking bits to prevent ROP attacks from occurring, but it does require very new hardware to work correctly.

* -Wimplicit-fallthrough: warns if switch cases don't have breaks.

* -D_FORTIFY_SOURCE=2: this causes several basic C functions (such as memcpy) in glibc to compile in a somewhat more secure manner, namely aborting the program if it can detect that it's going to overflow the bounds of an object. The '2' level adds extra checks that prohibits some legal C behavior (for example, buffer overflows that run into a different subobject of the same object).

* -s: Strip the resulting binary after linking.

* -fomit-frame-pointer: This is already the default on x86-64, and maybe ARM/AArch64 as well (I don't have those ABIs thoroughly memorized).

* -Wl,-z,now: Dynamic symbol resolution has to happen at load time rather than lazily. This can cause issues if you're relying on a symbol to be provided by a shared library you're loading dynamically (not a common case, as most people are liable to use dladdr instead).

* -Wl,-z,relro: Make sections that need to be writable only for dynamic relocations be read-only post-relocation-fixup phase.

* -Wl,-z,defs: Make it a linker error if there's a symbol that isn't available in the main executable/library you're building or any of the dynamic libraries you've linked. (Like -Wl,-z,now, this is again something that is unlikely to cause you issues).

* -Wl,-pie: This again enables position-independent executables (and should be triggered by -fPIE, so I'm somewhat curious why -fPIE isn't being passed here instead of -Wl,-pie).

* -Wl,--no-copy-dt-needed-entries: The secondary effect here is likely what is intended. If you're linking against liba.so, and liba.so depends on libb.so, this prevents the application from using libb.so to provide symbols, at least for the purposes of deciding whether to cause an error for -Wl,-z,defs (it should still load those symbols at runtime anyways).

Re: Hardening ELF binaries using Relocation Read-Only (2019)

#18

Earlier quoted context omitted.

... please don't copy paste without certainty of what it does Would you be willing to explain why this specific set of flags (I realize I could google them all, but I also realize that some flags have interactions with other flags and trying to find those is not straightforward)? Genuinely interested, not holding you accountable for my computer exploding.

Not OP, but here goes: * -fPIE : Compile as a 'position-independent executable'. This allows code and data sections of the executable to be installed at random locations in the address space, and comes with a mild cost due to needing extra indirections to handle position-independent code. * -Wformat-security: adds some extra warnings around possible misuse of printf and scanf. * -fstack-protector-strong --param=ssp-b…

Thank you so much

Re: Hardening ELF binaries using Relocation Read-Only (2019)

#19

last time I checked the Debian and Gentoo hardening guides relro/pie were standard practice. I can't remember the time we didn't use it and I've been around for a minute. this is my template for most Linux projects (except when "something else" is needed :)) ... please don't copy paste without certainty of what it does: CFLAGS_BASE := -c -O2 -Wall -Werror -Wpedantic -pipe $(CFLAGS) CFLAGS_HARD := -fPIE -Wformat-secur…

... please don't copy paste without certainty of what it does Would you be willing to explain why this specific set of flags (I realize I could google them all, but I also realize that some flags have interactions with other flags and trying to find those is not straightforward)? Genuinely interested, not holding you accountable for my computer exploding.

EPEL has this package:

    $ rpm -q hardening-check
    hardening-check-2.6-1.el7.noarch

    $ rpm -qi hardening-check | grep URL
    URL         : http://packages.debian.org/hardening-wrapper
It will tell you basic protections in ELF binaries.

    $ hardening-check /bin/ls
    /bin/ls:
     Position Independent Executable: no, normal executable!
     Stack protected: yes
     Fortify Source functions: yes (some protected functions found)
     Read-only relocations: yes
     Immediate binding: no, not found!
This is the configure directive for new software to pass all of the above tests:

    CFLAGS='-O2 -D_FORTIFY_SOURCE=2 -fstack-protector-strong -fpic -pie' \
    LDFLAGS='-Wl,-z,relro,-z,now -Wl,-z,now' ./configure
The package comes with a manual page with basic explanations of each test.

Re: Hardening ELF binaries using Relocation Read-Only (2019)

#20

last time I checked the Debian and Gentoo hardening guides relro/pie were standard practice. I can't remember the time we didn't use it and I've been around for a minute. this is my template for most Linux projects (except when "something else" is needed :)) ... please don't copy paste without certainty of what it does: CFLAGS_BASE := -c -O2 -Wall -Werror -Wpedantic -pipe $(CFLAGS) CFLAGS_HARD := -fPIE -Wformat-secur…

Wouldn't some of this be mitigated by specifying function visiblity? AIUI, when building a shared lib, all functions are visible in case a user wants to hook any functions via, e.g. LD_PRELOAD

Yes, fvisibility=hidden is a great addition; combined with LTO and a Clang toolchain, you can also add fsanitize=cfi. The CFI sanitizer adds a 1% perf penalty for a significant exploit mitigation. It complements -fcf-protection=full nicely.

You can also add fsanitize=shadow-stack (ARM) or fsanitize=safe-stack (x86_64) for stronger protection than -fstack-protector-all. This will cause many programs to crash.

Post reply on HN