mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-09 11:27:28 -03:00
contrib: test for FORTIFY_SOURCE in security-check.py
This commit is contained in:
parent
94bc3c4cc0
commit
be4f78275f
2 changed files with 33 additions and 8 deletions
|
@ -7,6 +7,7 @@ Perform basic security checks on a series of executables.
|
|||
Exit status will be 0 if successful, and the program will be silent.
|
||||
Otherwise the exit status will be 1 and it will log which executables failed which checks.
|
||||
'''
|
||||
import re
|
||||
import sys
|
||||
|
||||
import lief
|
||||
|
@ -116,6 +117,25 @@ def check_ELF_CONTROL_FLOW(binary) -> bool:
|
|||
return True
|
||||
return False
|
||||
|
||||
def check_ELF_FORTIFY(binary) -> bool:
|
||||
|
||||
# bitcoin-util does not currently contain any fortified functions
|
||||
if 'Bitcoin Core bitcoin-util utility version ' in binary.strings:
|
||||
return True
|
||||
|
||||
chk_funcs = set()
|
||||
|
||||
for sym in binary.imported_symbols:
|
||||
match = re.search(r'__[a-z]*_chk', sym.name)
|
||||
if match:
|
||||
chk_funcs.add(match.group(0))
|
||||
|
||||
# ignore stack-protector and bdb
|
||||
chk_funcs.discard('__stack_chk')
|
||||
chk_funcs.discard('__db_chk')
|
||||
|
||||
return len(chk_funcs) >= 1
|
||||
|
||||
def check_PE_DYNAMIC_BASE(binary) -> bool:
|
||||
'''PIE: DllCharacteristics bit 0x40 signifies dynamicbase (ASLR)'''
|
||||
return lief.PE.DLL_CHARACTERISTICS.DYNAMIC_BASE in binary.optional_header.dll_characteristics_lists
|
||||
|
@ -228,11 +248,11 @@ BASE_MACHO = [
|
|||
|
||||
CHECKS = {
|
||||
lief.EXE_FORMATS.ELF: {
|
||||
lief.ARCHITECTURES.X86: BASE_ELF + [('CONTROL_FLOW', check_ELF_CONTROL_FLOW)],
|
||||
lief.ARCHITECTURES.ARM: BASE_ELF,
|
||||
lief.ARCHITECTURES.ARM64: BASE_ELF,
|
||||
lief.ARCHITECTURES.PPC: BASE_ELF,
|
||||
lief.ARCHITECTURES.RISCV: BASE_ELF,
|
||||
lief.ARCHITECTURES.X86: BASE_ELF + [('CONTROL_FLOW', check_ELF_CONTROL_FLOW), ('FORTIFY', check_ELF_FORTIFY)],
|
||||
lief.ARCHITECTURES.ARM: BASE_ELF + [('FORTIFY', check_ELF_FORTIFY)],
|
||||
lief.ARCHITECTURES.ARM64: BASE_ELF + [('FORTIFY', check_ELF_FORTIFY)],
|
||||
lief.ARCHITECTURES.PPC: BASE_ELF + [('FORTIFY', check_ELF_FORTIFY)],
|
||||
lief.ARCHITECTURES.RISCV: BASE_ELF, # Skip FORTIFY. See https://github.com/lief-project/LIEF/issues/1082.
|
||||
},
|
||||
lief.EXE_FORMATS.PE: {
|
||||
lief.ARCHITECTURES.X86: BASE_PE,
|
||||
|
|
|
@ -59,17 +59,22 @@ class TestSecurityChecks(unittest.TestCase):
|
|||
arch = get_arch(cxx, source, executable)
|
||||
|
||||
if arch == lief.ARCHITECTURES.X86:
|
||||
pass_flags = ['-Wl,-znoexecstack', '-Wl,-zrelro', '-Wl,-z,now', '-pie', '-fPIE', '-Wl,-z,separate-code', '-fcf-protection=full']
|
||||
pass_flags = ['-D_FORTIFY_SOURCE=3', '-Wl,-znoexecstack', '-Wl,-zrelro', '-Wl,-z,now', '-pie', '-fPIE', '-Wl,-z,separate-code', '-fcf-protection=full']
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags + ['-Wl,-zexecstack']), (1, executable + ': failed NX'))
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags + ['-no-pie','-fno-PIE']), (1, executable + ': failed PIE'))
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags + ['-Wl,-znorelro']), (1, executable + ': failed RELRO'))
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags + ['-Wl,-z,noseparate-code']), (1, executable + ': failed SEPARATE_CODE'))
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags + ['-fcf-protection=none']), (1, executable + ': failed CONTROL_FLOW'))
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags + ['-U_FORTIFY_SOURCE']), (1, executable + ': failed FORTIFY'))
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags), (0, ''))
|
||||
else:
|
||||
pass_flags = ['-Wl,-znoexecstack', '-Wl,-zrelro', '-Wl,-z,now', '-pie', '-fPIE', '-Wl,-z,separate-code']
|
||||
pass_flags = ['-D_FORTIFY_SOURCE=3', '-Wl,-znoexecstack', '-Wl,-zrelro', '-Wl,-z,now', '-pie', '-fPIE', '-Wl,-z,separate-code']
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags + ['-Wl,-zexecstack']), (1, executable + ': failed NX'))
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags + ['-no-pie','-fno-PIE']), (1, executable + ': failed PIE'))
|
||||
# LIEF fails to parse RISC-V with no PIE correctly, and doesn't detect the fortified function,
|
||||
# so skip this test for RISC-V (for now). See https://github.com/lief-project/LIEF/issues/1082.
|
||||
if arch != lief.ARCHITECTURES.RISCV:
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags + ['-no-pie','-fno-PIE']), (1, executable + ': failed PIE'))
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags + ['-U_FORTIFY_SOURCE']), (1, executable + ': failed FORTIFY'))
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags + ['-Wl,-znorelro']), (1, executable + ': failed RELRO'))
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags + ['-Wl,-z,noseparate-code']), (1, executable + ': failed SEPARATE_CODE'))
|
||||
self.assertEqual(call_security_check(cxx, source, executable, pass_flags), (0, ''))
|
||||
|
|
Loading…
Reference in a new issue