Binary vulnerabilities are executable files (PE, ELF files, etc.) that are not properly considered when encoding, causing softwares to perform unexpected functions.
Binary vulnerabilities include:
- buffer(stack, bss or heap) overflow
- integer overflow
- format string vulnerability
- use after free
- race condition
- sandbox escape
- IO flie related
- …
Security Protection Mechanism is needed for software security.
Linux Security Protection Mechanism
To pwn, the initial step to check file’s format is:
1 | $ file xxxxx |
The next and important step is:
1 | $ checksec xxxxx |
Now the question is, what are those above means?
Canary (GS)
Attacks caused by stack overflows are very common and very old. A mitigation technique called canary has long appeared in glibc and has been the first line of defense for system security.
Canary is simple and efficient in both implementation and design. It is to insert a value. At the end of the high-risk area where stack overflow occurs, when the function returns, check if the value of canary has been changed to determine whether stack/buffer overflow is occur.
Canary and GS protection under Windows are effective means to prevent stack overflow. Its appearance largely prevents stack overflow, and since it hardly consumes system resources, it has become the standard of protection mechanism under Linux.
Canary can be set in GCC using the following parameters:
1 | -fstack-protector (default) |
Fortify
This has something to do with a macro: _FORTIFY_SOURCE
Defining this macro causes some lightweight checks to be performed to detect some buffer overflow errors when employing various string and memory manipulation functions (for example, memcpy, memset, stpcpy, strcpy, strncpy, strcat, strncat, sprintf, snprintf, vsprintf, vsnprintf, gets, and wide character variants thereof).
For some functions, argument consistency is checked; for example, a check is made that open has been supplied with a mode argument when the specified flags include O_CREAT
. For printf
the %n
is forbidden and %num$s
can only exist when %num-1$s
, %num-2$s
, … %2$s
and %1$s
(%s
) all exist. Not all problems are detected, just some common cases.
Some of the checks can be performed at compile time (via macros logic implemented in header files), and result in compiler warnings; other checks take place at run time, and result in a run-time error if the check fails.
Use of this macro requires compiler support, available with gcc since version 4.0.
Fortify can be set in GCC using the following parameters:
1 | -U_FORTIFY_SOURCE |
NX (DEP)
The basic principle of NX (No-eXecute) is to identify the memory page where the data is located as non-executable.
When the program overflows and transfers to shellcode successfully, the program will try to execute instructions on the data page, and the CPU will throw an exception instead of executing malicious instructions.
The principle is the same as DEP under windows.
NX can be set in GCC using the following parameters:
1 | -z execstack |
PIE (ASLR)
In general, NX (called DEP on Windows platforms) and Address Space Distribution Randomization (ASLR) will work simultaneously.
Memory address randomization mechanism (address space layout randomization) has three levels
- 0: off ASLR. no randomization, same base address for stack & heap, and same address for libc.so
- 1: normal ASLR. random base address for mmap, stack and libc.so , but not randomize for heap
- 2: advanced/enhanced ASLR, random heap address added
Check ASLR condition
1 | $ sysctl -n kernel.randomize_va_space |
Off ASLR (same way as changing level)
1 | $ sysctl -w kernel.randomize_va_space=0 |
As for PIE : Position-Independent-Executable
It’s the name for ASLR on Linux.
Difference:
- PIE (on executable) is a power giver. It enables program to randomize address or not.
- ASLR (on process) is the power user. It tells operating system to do program address randomization.
PIE can be set in GCC using the following parameters:
1 | -no-pie # Disable PIE (default) |
As for PIC : Position-Independent Code
The difference between PIE and PIC:
PIE parameter is for executable files
PIC parameter is for shared library
RELRO
In the area of Linux system security, the data storage area that can be written will be the target of the attack, especially the area where function pointers are stored. So from the perspective of security protection, minimizing the writable storage area will be of great benefit to security.
GCC, GNU linker, and Glibc-dynamic linker work together to implement a technology called RELRO: read only relocation. The approximate implementation is setting the area of the binary specified by the linker after the dynamic linker has processed the relocation as read-only.
1 | -z norelro # No RELRO |
Sum-Up
NX:-z execstack / -z noexecstack (Off / On)
Canary:-fno-stack-protector /-fstack-protector / -fstack-protector-all (Off / On / All Func On)
PIE:-no-pie / -pie (Off / On)
RELRO:-z norelro / -z lazy / -z now (Off / Partial / Full)
Windows Security Protection Mechanism
There’re always many compiling options in Visual Studio when coding.
They can be set in Visual Studio before compilation.
Some parameters explained as below.
GS
Similar to Canary.
After the GS option is enabled, a piece of data is saved on the stack at the beginning of the function execution, and the data is checked when the function returns. If it is inconsistent, it is overwritten, so it jumps into the corresponding processing process and no longer returns, so the shellcode cannot be executed, this value is called “Security cookie”. Software calls Check_Security_Cookie () to check whether the stack is covered.
SafeSEH
Canary is useful for stack overflow.
However, they ignored that the SEH chain of exception handling is also on the stack, so they can overwrite the address of the SEH chain as jmp esp, and then trigger an exception to jump to the esp to execute the shellcode.
SafeSEH registers all exception handling functions when the program is compiled to a registered list. After an exception is triggered during execution, a check function is performed to check whether the address pointed to by the SEH chain is in the registered list.
DEP
Similar to NX.
However, in the logic of the check function, the execution is prevented only when the SEH chain points/links to the module (exe, dll) address. If the address pointed/linked to by the SEH chain is not in these modules, then it can be executed. Therefore, the program is not a module Find the jmp esp in the data space, such as the resource file with the nls suffix, etc., or in software that supports JS scripts (browser, etc.) bypass by writing shellcode through the script to allocated heap.
Data execution protection (DEP) refers to the heap and stack with only read and write permissions and no execute permissions. Therefore no shellcodes can be executed.
ASLR
Similar to PIE.
Load code to random space to prevent ROP.
CFG
CFI stands for Control-Flow Integrity.
It mainly adds dynamic security to the binary executable file by dynamically rewriting it.
e.g.
Insert a check ID agreed in the rewrite before the destination address of jmp, and check if the data in front of the destination address is the agreed check ID in jmp. If not, enter the error processing flow.
Insert the check ID before the destination address of the call and the return address of ret, and then the check of the check ID is added to the rewritten call and ret. If it does not meet the expectations, enter the error processing flow.
The implementation of CFI requires that when jmp, or call to a register (or use register indirect addressing), the destination address must sometimes be obtained dynamically, and the overhead of rewriting is very large, which has caused certain difficulties in the practical application of CFI.
CFG is the abbreviation of Control Flow Guard, which is a control flow protection. It is a combination of compiler and operating system protection, the purpose is to prevent untrusted indirect calls.
In the course of the vulnerability attack, a common exploitation method is to overwrite or directly tamper with the value of a register, tamper with the address of the indirect call, and then control the program execution flow. CFG records all indirect call information during compilation and linking, and records them in the final executable file, and inserts additional checks before all indirect calls. When the address of the indirect call is tampered, An exception is triggered and the operating system intervenes.