note: this grimoire is not maintained anymore!

draft by Thomas Houssin

Creation of this grimoire was decided in [WWW] bug #8670. The Hardened Grimoire is currently work in progress. It's usable, but there are probably some bugs left.

Quickstart

Adding the hardened grimoire

The hardened grimoire is not a full grimoire. It redefines several spells, to add new patches, features, etc. That's why you still need a full grimoire (test, stable-rc or stable) behind the hardened grimoire.

To begin to use the hardened grimoire, just do scribe add hardened. scribe index should then give you something like :

 [0] : hardened : /var/lib/sorcery/codex/hardened
 [1] : test : /var/lib/sorcery/codex/test
 [2] : z-rejected : /var/lib/sorcery/codex/z-rejected
 [3] : games : /var/lib/sorcery/codex/games

Choosing the features

Then cast the hardened-profile spell. It'll let you choose various features.

This will then trigger a run_script, to recast needed spells based on your choices. Do not try to avoid this step, or it may lead to a broken box. If you choose to use SSP and/or PaX, it's a good idea to rebuild everything to benefit of the protection, and and ensure everything will work as expected. sorcery rebuild is a good way... You can then rebuild your kernel.

Rebuilding the kernel

To rebuild the kernel, recast linux : cast -r linux. Latest supported kernel is version 2.6.11.12 (only 2.6 kernel is supported).

The following patches are available :

    # permissions
    KERNEL="erandom", OWNER="root", GROUP="root", MODE="0644"
    KERNEL="frandom", OWNER="root", GROUP="root", MODE="0644"

Available features

PIE

By default, gcc and g++ use special specs. gcc -fPIC, ld -pie, and cpp -D_PIC -DPIC are used by default to build dynamical programs. -z relro and -r now are also user by default. Moreother, if you choose to use SSP, -fstack-protector-all can also be used by default. Unsupported flags are disabled in the spells. If you find a spell where it should, please report a bug.

Other available features are:

Stack Smashing Protector

[WWW] Stack Smashing Protector It was developed for protecting applications from stack smashing attacks (mainly linear buffer overflows). This is done by adding some code at compilation time. This will typically gives a performance loss around 2% at run time.

This feature needs gcc and glibc to be recompiled. Patches mainly come from HLFS. The patch for glibc adds _guard_setup and _stack_smash_handler to libc.so. _guard_setup is a function used to create a unique and random value for _guard each run time. In the event of a stack overflow, the _stack_smash_handler function will use the glibc syslog facility to record the overflow, and will then abort the program. More information, see [WWW] http://www.research.ibm.com/trl/projects/security/ssp/

Be aware that using -O3 optimisations and SSP can be problematical. You should disable speedy in the optimisations menu ; if you want to optimize your apps, add -O2 to the custom CFLAGS and CXXFLGAS.

GRSecurity

[WWW] grsecurity This kernel patch offer various new features, such as chroot restrictions, /tmp race prevention, extra logging, ...

PaX

[WWW] PaX With this, you'll benefit from non-executable stack and address space layout randomisation. Used with PIE programs, ASLR randomize their return addresses. This can prevent security bugs from being taken advantage of by attackers. Non-executable stack can prevent injected code from being executed. Most of PaX features can be disabled on a per file basis. This is done by adding PT_PAX_FLAGS to the program headers (binutils is patched to do this in the hardened grimoire), and can be tweaked thanks to the paxctl program. (binary only executables can use the EI_PAX old header marking scheme, and chpax utility). For few programs, some features need to be disabled. These are taken care in the spells.

If you find other spells that need suchs precautions, please report a bug. The further informations, [WWW] http://pax.grsecurity.net/docs/index.html is a good place.

Using these settings in the kernel is a good beginning :

 [ ] Support soft mode`
 [*] Use legacy ELF header marking
 [*] Use ELF program header marking
     MAC system integration (none)  --->

 [*] Enforce non-executable pages
 [*]   Paging based non-executable pages
 [*]   Segmentation based non-executable pages
         Default non-executable page method (SEGMEXEC)  --->
 [ ] Emulate trampolines
 [*] Restrict mprotect()
 [ ]   Disallow ELF text relocations

 [*] Address Space Layout Randomization
 [*]   Randomize kernel stack base
 [*]   Randomize user stack base
 [*]   Randomize mmap() base
 ---   Disable the vsyscall page

Work in progress

This grimoire plans to add support for :

How to test

You can use the following code (from HLFS) for a quick test:

cat > test.c << "EOF"
#include <stdio.h>
#include <unistd.h>
extern long __guard[];
int overflow(char *test) {
  char buffer[7];
  sprintf(buffer, "12345678901234567890123456789012345678901234567890");
  return(1234);
}
int main(int argc, char **argv) {
  printf("__guard\\t=\\t0x%08x;\
", __guard[0]);
  overflow("test");
  printf("This line should never get printed.\
");
}
EOF

Compile it with gcc and run it :

# gcc -o test test.c
# ./test

You'll have something like :

__guard =       0x6c8f1eec;
test: stack smashing attack in function overflow()
Abandon

You'll also have a line in your log file:

[test] test: stack smashing attack in function overflow()

you can check that this application is dynamically linked with readelf -l test:

Elf file type is DYN (Shared object file)
Entry point 0x684
There are 9 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x00000034 0x00000034 0x00120 0x00120 R E 0x4
  INTERP         0x000154 0x00000154 0x00000154 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x00000000 0x00000000 0x00ab0 0x00ab0 R E 0x1000
  LOAD           0x000edc 0x00001edc 0x00001edc 0x00130 0x00134 RW  0x1000
  DYNAMIC        0x000ef0 0x00001ef0 0x00001ef0 0x000d8 0x000d8 RW  0x4
  NOTE           0x000168 0x00000168 0x00000168 0x00020 0x00020 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
  GNU_RELRO      0x000edc 0x00001edc 0x00001edc 0x00124 0x00124 R   0x1
  PAX_FLAGS      0x000000 0x00000000 0x00000000 0x00000 0x00000     0x4

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame
   03     .ctors .dtors .jcr .dynamic .got .data .bss
   04     .dynamic
   05     .note.ABI-tag
   06
   07     .ctors .dtors .jcr .dynamic .got
   08

First line shows that file type is Shared object file. Also note the additional GNU_RELRO and PAX_FLAGS (if you choose to use PaX) headers.

You can check for -z now with readelf -d test | grep BIND_NOW:

0x00000018 (BIND_NOW)

Hopefully a PaX test suite will be available soon.

last edited 2008-03-03 14:21:43 by JakaKranjc